QA@IT

多対多のために作ったクラスで起こったvalidationを、どうやってコントローラで取得するのか?

2941 PV

現在、Rails3.2で開発しているのですが、多対多のために作ったクラスで定義したvalidationを、どうやってコントローラで取ればいいのかわかりません。

具体的にこのQA@ITを例に説明させていただきます。

前提として「質問=question」、「タグ=tag」とさせていただきます。
そしてこの2つは、「QuestionTag」というテーブルで関連付けされているものとします。

  • Validation条件

このQA@ITの質問には、タグが10個以上つけれないものとする。

  • 上記のValidationを実装したQuestionTagモデルのソース
# coding: utf-8

class QuestionTag < ActiveRecord::Base
  attr_accessible :question_id, :tag_id

  belongs_to :tag
  belongs_to :question

  validate do
      if question.try(:tags).try(:count).try(:>=,10)
        errors.add("tag_id","タグを10個以上登録できません")
      end
  end
end
  • 上記のQuestionTagを呼び出すコントローラのnewメソッド
class QuestionTagsController < ApplicationController
     def new
       begin
         qeustion.tags << tag ##これで10個こえてしまうものとする
       rescue => ex
         ???.errors   ##ここでどうやってQuestionTag.errorsを取ればいいのかわからない
         return render :nothing => true, :status => 400
       end
     end
end

上記のようにvalidationが発生した場合に、「タグを10個以上登録できません」という文字を取得して、Viewに投げたいのですが、どのインスタンスにアクセスすればいいのかわかりません。

他にも、もっといいValidationの掛け方があるとか、本題とずれた指摘もあればご指摘いただけると幸いです。

回答

valildation 失敗時に raise される ActiveRecord::RecordInvalid 例外は、record メソッドで検証に失敗したオブジェクトを取得できます。

rescue ActiveRecord::RecordInvalid => ex
  ex.record.errors.messages #=> {:tag_id=>["タグを10個以上登録できません"]}

ちょっとトリッキーなので、下記のように明示的に QuestionTag インスタンスを作るほうがわかりやすいかもしれません。

question_tag = QuestionTag.new(question: question, tag: tag)
question_tag.save #=> false
question_tag.errors.messages #=> {:tag_id=>["タグを10個以上登録できません"]}
編集 履歴 (0)
  • なるほど、exからとれるという発想がなかったです。
    またおとなしくQuestionTagでやるという方法も確かにありですよね。
    どちらの方法を実装するかは、周りのソースと相談して決めようと思います。
    ご回答ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。