即时更改验证规则

时间:2014-11-04 16:56:52

标签: ruby-on-rails ruby metaprogramming

我需要在我的应用的某些部分进行条件验证。现在我使用以下方案:

User.create
User::WithPassword.create
User::WithPhone.create

如果我可以像这样改变课堂行为,那会很酷:

User.with_phone.with_password.create

所以我试着这样做:

class User < ActiveRecord::Base
  validates :phone, presence: true, if: :phone_required?

  def self.with_phone
    define_method(:phone_required?) { true }
    self
  end

  private

  def phone_required?
    false
  end
end

因此可以在需要时使用它:

User.with_phone.create(user_params)

这种方法的问题在于,自实际类更改以来,User的所有实例都会获得新的行为。

有没有办法只使用新的实例方法User返回phone_required?类的修改后的副本而不影响“基类”?

更新

感谢您的评论,因为这更多是一个想法,要求是我创建用户而不自动进行某些验证,然后当他们编辑个人资料时,他们正在处理原始的User模型。我在需要时会在方法中创建with_/without_

这是我的下一次迭代:

class User < ActiveRecord::Base
  validates :phone, presence: true, if: :phone_required?

  def self.with_password
    define_singleton_method(:password_required?) { true }
    self
  end

  def password_required?
    self.class.try :password_required?
  end
end

显然它并不是更好,因为单身人士方法一直都在那里。

1 个答案:

答案 0 :(得分:1)

为什么不简单地使用在创建时初始化的实例变量?

class User < ActiveRecord::Base
  validates :phone, presence: true, if: :phone_required?

  @phone_required = false

  def self.create_with_phone(params)
    obj = self.create(params)
    obj.phone_required = true
  end

  private

  def phone_required=(v)
    @phone_required = v
  end

  def phone_required?
    @phone_required
  end
end

User.create_with_phone(user_params)