Railsのフォームでは以下のような記述で簡単にバリデーションを追加することができます。
class ModelName < ActiveRecord::Base
attr_accessible :attr
validates :attr, presence: true
end
このバリデーションの部分はActiveModel::Validations
としてモジュールになっているので、永続化機構を持たない(DBにテーブルがない)場合でもバリデーションの機能のみ利用することができます。
僕はこれを利用してフォームとして利用することがよくあります。
class SomeForm
extend ActiveModel::Naming
include ActiveModel::Validations
attr_accessor :attr
validates :attr, presence: true
end
大抵の場合はこれでまったく問題ないのですが、フォームの項目が動的に変わる場合、バリデーションルールも動的に追加したいのですがそうするとうまく動かないという現象に遭遇しました。
(稀なケースだと思いますが、例えば管理画面で設問を設定する場合など。)
class DynamicForm
extend ActiveModel::Naming
include ActiveModel::Validations
def initialize(attrs = [ :attr1, attr2 ])
@attrs = {}
attrs.each do |attr|
instance_eval <<-DEFINE_GETTER_AND_SETTER_AND_PRESENCE_VALIDATOR
class << self
validates :#{attr}, presence: true # これが動かない!
def #{attr}
@attr[#{attr}]
end
def #{attr}=(value)
@attr[#{attr}] = value
end
end
DEFINE_GETTER_AND_SETTER_AND_PRESENCE_VALIDATOR
end
end
end
まだ解決できていないのですが備忘録として書きました。
余裕で来たらソースコード追ってみます。
Rails4ではActiveModel::Model
を利用することができるようになったのでこれ使えば大丈夫なのかなぁ…