Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 动态更改验证规则_Ruby On Rails_Ruby_Metaprogramming - Fatal编程技术网

Ruby on rails 动态更改验证规则

Ruby on rails 动态更改验证规则,ruby-on-rails,ruby,metaprogramming,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?

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

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.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
类的修改副本
phone\u required?

更新

感谢您的评论,因为这更像是一个想法,要求我在没有特定验证的情况下自动创建用户,然后当他们编辑配置文件时,他们处理的是原始的
用户
模型。我在需要时动态创建
带/不带
的方法

下面是我的下一次迭代:

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
class用户

很显然,这并没有什么好处,因为singleton方法一直都在那里。

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

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)
class用户
请不要这样做。除非您试图采用“通过猖獗的模糊化实现工作安全”模式,否则它将与正确的面向对象设计背道而驰。为什么不使用
attr\u访问器
标志或一级列来持久化此布尔值?此方法将不再显示,因此当您尝试重新保存现有记录时,您的验证将失败。感谢您的输入,事实上,我只需要在创建时使用自定义类。我正在从
User::WithoutPassword
模型中重构它。我已经用singleton方法创建更新了原来的问题,所以它不会污染基类。谢谢你的建议,我希望尽可能清晰地模拟基类的接口,而不必添加虚拟字段。问题是,在创建时,我需要
用户。没有密码。没有电话
,然后只需要
用户。没有密码
,但一旦用户开始编辑他的个人资料,它就是
用户
。我用新的想法更新了原来的帖子。