「フォームから入力された値が不正だった場合にエラーメッセージを表示しよう」というメソッドの中で、「もし、このケースであればすぐに次の処理に移りたい」というときその行で「return」させてみたのですがそれだとメソッド自体から離脱してしまい次の行の処理ができなくなってしまったので別の方法を探してみました。
return
その時のコードはこのような形
def hoge
error_messages = []
CSV.parse(tsv_text, headers: true, col_sep: "\t") do |row|
error_messages << "shop_id:#{row["shop_id"]}は存在しないIDです" if Shop.find_by(id: row["shop_id"]).blank?
error_messages << "user_id:#{row["user_id"]}は存在しないIDです" if User.find_by(id: row["user_id"]).blank?
error_messages << "comment_id:#{row["comment_id"]}は存在しないIDです" if Comment.find_by(id: row["comment_id"]).blank?
end
errors.add(:tsv_text, error_messages.join("<br/>").html_safe) if error_messages.present?
end
この時、「shop_idがなければその後の検証はしなくてもいい」という処理をしたかったので
def hoge
error_messages = []
CSV.parse(self.tsv_text, headers: true, col_sep: "\t") do |row|
return error_messages << "shop_id:#{row["shop_id"]}は存在しないIDです" if Shop.find_by(id: row["shop_id"]).blank?
error_messages << "user_id:#{row["user_id"]}は存在しないIDです" if User.find_by(id: row["user_id"]).blank?
error_messages << "comment_id:#{row["comment_id"]}は存在しないIDです" if Comment.find_by(id: row["comment_id"]).blank?
end
errors.add(:tsv_text, error_messages.join("<br/>").html_safe) if error_messages.present?
end
としていました。しかしこれだとreturnした時にメソッド自体を離脱してしまい次の行の処理に移れなくなってしまうので何か違う方法で処理をしなければなりませんでした。
break
調べてみたところ途中で処理を止める方法はbreakとnextの二つあるようでした。結果的に後述するnextを使うことになるのですが、breakを使った場合どうなるのかも載せておきます。
def hoge
error_messages = []
CSV.parse(tsv_text, headers: true, col_sep: "\t") do |row|
break error_messages << "shop_id:#{row["shop_id"]}は存在しないIDです" if Shop.find_by(id: row["shop_id"]).blank?
error_messages << "user_id:#{row["user_id"]}は存在しないIDです" if User.find_by(id: row["user_id"]).blank?
error_messages << "comment_id:#{row["comment_id"]}は存在しないIDです" if Comment.find_by(id: row["comment_id"]).blank?
end
# breakした場合直後にこの行が実行される
errors.add(:tsv_text, error_messages.join("<br/>").html_safe) if error_messages.present?
end
breakの場合メソット自体は抜け出さないが「その繰り返し処理を全て終了する」という挙動になるようで、もし最初の行でbreakしてしまった場合、それ以降の行に対する検証をしてくれなくなってしまいます。
next
条件を満たす挙動をしてくれたのがこのnext。
def hoge
error_messages = []
CSV.parse(tsv_text, headers: true, col_sep: "\t") do |row|
next error_messages << "shop_id:#{row["shop_id"]}は存在しないIDです" if Shop.find_by(id: row["shop_id"]).blank?
error_messages << "user_id:#{row["user_id"]}は存在しないIDです" if User.find_by(id: row["user_id"]).blank?
error_messages << "comment_id:#{row["comment_id"]}は存在しないIDです" if Comment.find_by(id: row["comment_id"]).blank?
end
errors.add(:tsv_text, error_messages.join("<br/>").html_safe) if error_messages.present?
end
nextの場合「次の繰り返しを終了する」という挙動になり、複数行の検証をできるようになりました。