質問: モデルのバリデーションで ``` class Hoge < ActiveRecord::Base validates :foo, presence: true end ``` となっていた場合、必須項目であることをフォームに表示させたいと思っています。 メタプログラミング的にモデルに`presence`が`true`か`false`問い合わせる方法はありませんか? 追記 -- 考慮漏れしていたのですが `validates :foo, presence: true, if: -> { false }` とifを使ったパターンが抜けてしまっていました。できればこれにも対応したいです。 (ifオプションがtrueかfalseか知る方法がわかればいけそうな気が...) いけました。 `.options[:if]`にProcが入っているので、 `.options[:if].call`でifオプションの結果が取得できました。 だたしやはり、 `if: :admin?`のパターンはシンボルが入っているので`.call`できないですね...
回答: こういうヘルパーメソッドを作ると便利かもしれません。 ``` def required_field?(obj, attribute) obj.class.validators_on(attribute).map(&:class).include?(ActiveRecord::Validations::PresenceValidator) end <% if required_field?(@user, :email) %> 必須 <% end %> ``` 追記 > > `validates :foo, presence: true, if: -> { false }` でもtrueになってしまうようです。できればこのパターンも考慮したいです。 > > > `.options[:if].call`でifオプションの結果が取得できました。 > > > うーん、ifが指定された場合は、「ある程度」なら対応できるかもしれませんが、完璧を目指すのは難しそうです。 ifにはいろいろな指定方法があります。 ``` # シンボルを使う validates :name, presence: true, if: :admin? # 文字列を使う validates :name, presence: true, if: "admin?" # 関連先のオブジェクトを参照する validates :name, presence: true, if: -> { self.company.present? } ``` さらに、ifと逆パターンのunlessオプションや、`on: :create`、`on: :update`といった、onオプションもあります。 こういったケースにすべて対応させようと思うとかなり面倒なロジックが必要になりそうです。 そもそもifやunlessを使うと、オブジェクトの状態(条件)によって必須かどうかも変わるので、フォームを表示した時点では必須かどうか決定できない場合もあります。 (例:フォームの管理者チェックボックスにチェックを入れた場合のみ名前が必須、等) 要件によっては「`.options[:if].call` で十分」ということもあるかもしれませんが、万能ではないという点に留意された方が良いと思います。 参考:5 条件付きバリデーション