如何使用Rails中的instance_eval子句删除验证?

mdr*_*iel 37 ruby validation activerecord ruby-on-rails

我想使用instance_eval增强现有的类.原始定义包含验证,需要存在某些字段,即:

class Dummy < ActiveRecord::Base
  validates :field, :presence => true 
end
Run Code Online (Sandbox Code Playgroud)

现在我想使用instance_eval(或任何其他方法,实际上)将其更改为可选:

Dummy.instance_eval do
  ...
end
Run Code Online (Sandbox Code Playgroud)

删除验证的正确语法是什么,因此该字段是可选的.我宁愿直接在模型层上执行此操作,而是在控制器或视图中执行奇怪的操作.实际上并不需要使用instance_eval,但据我所知,这通常是增强Rails中类的最佳方法.

编辑#1

一般来说 - 原始类是gem的一部分,我不想分叉它,也不想绑定到特定的版本.一般原因并不重要.简单地编辑原始模型比猴子修补具有更糟糕的后果.

Nic*_*roi 28

我找到了一个解决方案,不确定它有多坚固,但在我的情况下效果很好.@aVenger实际上接近他的回答.只是_validators访问者只包含用于反射的信息,而不包含实际的验证器回调!它们包含在_validate_callbacks访问器中,不要混淆_validations_callbacks.

Dummy.class_eval do
  _validators.reject!{ |key, _| key == :field }

  _validate_callbacks.reject! do |callback|
    callback.raw_filter.attributes == [:field]
  end
end
Run Code Online (Sandbox Code Playgroud)

这将删除所有验证器:field.如果您想更精确,可以拒绝与验证回调_validatorsraw_filter访问者相同的特定验证器.

  • 不再使用rails 4.1,因为_validate_callbacks不再是一个数组,但包括Enumerable,所以尝试使用reject而不是拒绝!现在... (3认同)
  • 顺便说一句,是的......这是邪恶的,但对于修补包含您认为过于严格的验证规则的 gem 非常有用!不要在家里这样做!;-) (2认同)

tos*_*osh 11

最简单的方法来删除所有验证:

clear_validators!
Run Code Online (Sandbox Code Playgroud)


18a*_*gst 10

我认为这是目前最实际的解决方案(我使用的是rails 4.1.6):

# Common ninja
class Ninja < ActiveRecord::Base
  validates :name, :martial_art, presence: true
end

# Wow! He has no martial skills
Ninja.class_eval do
  _validators[:martial_art]
    .find { |v| v.is_a? ActiveRecord::Validations::PresenceValidator }
    .attributes
    .delete(:martial_art)
end
Run Code Online (Sandbox Code Playgroud)

  • 是的!终于成功了......现在也可以使用`Ninja.validators_on` (2认同)

Bla*_*ake 9

当我试图这样做以从狂欢地址模型中删除电话验证时,下面是我开始工作的代码.我添加了callback.raw_filter的类型检查,因为我只想删除电话字段上的状态验证器.我还必须添加它,因为它在尝试针对Spree :: Address模型中指定的其他验证器运行时会失败,该函数没有callback.raw_filter的'attributes'键,因此抛出异常.

Spree::Address.class_eval do

   # Remove the requirement on :phone being present.
  _validators.reject!{ |key, _| key == :phone }

  _validate_callbacks.each do |callback|
    callback.raw_filter.attributes.delete :phone if callback.raw_filter.is_a?(ActiveModel::Validations::PresenceValidator)
  end

end
Run Code Online (Sandbox Code Playgroud)


Jef*_*ran 5

我遇到了类似的问题,并且能够使用以下方法解决它:

class MyModel << Dummy
  # erase the validations defined in the plugin/gem because they interfere with our own
  Dummy.reset_callbacks(:validate)
  ...
end
Run Code Online (Sandbox Code Playgroud)

这是在 Rails 3.0 下。警告:它确实删除了所有验证,因此如果您想保留其他验证,您可以尝试Dummy.skip_callback(...),但我无法找出使该工作有效的参数的正确咒语。