10608


繰り返し文の中で`redo`が使えることを初めて知り、動作についてはわかりました。  
具体的な処理としては毎ループ特定の変数の値を変更させて使うようですが、  
効率が悪かったり、読みづらい処理しか自分には思いつきませんでした。

具体的にどのような場合に`redo`を使えば処理がきれいに書けるのか何か例を一つ教えていただけないでしょうか？


CC BY-SA 3.0
2015-05-25T11:32:15.630
10598
2015-05-25T22:23:25.110
3271
question
ruby
Rubyのredoを使うと良い処理

[code]

    # -*- encoding: utf-8 -*-
    
    items = ["名前", "ニックネーム", "出身地", "座右の銘"]
    
    puts "あなたの情報を教えてください"
    
    p items.inject(Hash.new) {|h, i|
        print "#{i}は？: "
        redo if (h[i] = gets.chomp).empty?
        h
    }
    
[/code]


CC BY-SA 3.0
2015-05-25T14:03:56.280
10608
2015-05-25T14:03:56.280
3639
10598
answer


例えばrailsを使っていると、楽観ロックと呼ばれる仕組みがあり、一度読んだレコードを更新しようとしたときに、そのレコードの読み込みから書き込みまでの間に別のトランザクションが同じレコードを変更済みだと例外が発生します。

この仕組みは明示的にロックを使用するのに比べると(いくつかの要因から起こる)デッドロックのリスクを気にせずに済むため便利ですが、更新失敗のたびに「更新に失敗しました。再度更新してください」とは出しにくいアプリケーションもあり、可能ならリトライを自動で行わせたい、という要求もありえます（実際にあります）。  
そういうときに、redo
の仕掛けは一定度、使えます。以下は簡易コードで、本当なら例外の型を確認してrescueすべきな他、リトライの待機時間もsleepで調整などするべきです。

[code]

    i = 0
    begin
      i += 1
      u = User.find(id)
      u.name = 'hoge'
      u.save!　# ここで例外が発生することがある
    rescue
      redo if i <= 3 #3回まで試行させる
    end
    
[/code]


CC BY-SA 3.0
2015-05-25T22:23:25.110
10618
2015-05-25T22:23:25.110
9403
10598
answer