通过扩展向 ActiveRecord 模块添加自定义验证?

Posted

技术标签:

【中文标题】通过扩展向 ActiveRecord 模块添加自定义验证?【英文标题】:Adding custom validations to ActiveRecord module via extend? 【发布时间】:2012-02-20 01:31:26 【问题描述】:

我正在尝试将我的验证移至一个模块。我想将现有对象扩展为一组验证器,但我正在努力弄清楚如何让它们执行。有什么想法吗?

活动记录对象

class Test < ActiveRecord::Base
  has_many :resources
end

验证器

module TestValidator
  extend ActiveSupport::Concern

  included do
    validates_associated :resources
  end
end

控制台

t = Test.new
t.extend TestValidator
t.valid?
# true ... should be false

【问题讨论】:

【参考方案1】:

希望对你有帮助

6.1 自定义验证器 自定义验证器是扩展 ActiveModel::Validator 的类。这些类必须实现一个 validate 方法,该方法将记录作为参数并对其执行验证。使用 validates_with 方法调用自定义验证器。

class MyValidator < ActiveModel::Validator
  def validate(record)
    unless record.name.starts_with? 'X'
      record.errors[:name] << 'Need a name starting with X please!'
    end
  end
end



class Person
  include ActiveModel::Validations
  validates_with MyValidator
end

添加自定义验证器以验证单个属性的最简单方法是使用方便的 ActiveModel::EachValidator。在这种情况下,自定义验证器类必须实现一个 validate_each 方法,该方法接受三个参数:对应于实例的记录、属性和值、要验证的属性和传递的实例中的属性值。

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]2,)\z/i
      record.errors[attribute] << (options[:message] || "is not an email")
    end
  end
end

class Person < ActiveRecord::Base
  validates :email, :presence => true, :email => true
end

如示例所示,您还可以将标准验证与您自己的自定义验证器结合起来。

https://guides.rubyonrails.org/active_record_validations.html#custom-validators

【讨论】:

嗨,本,感谢您的帖子。这绝对是进行验证的理智/正确的方法。我试图让模块/混合方法继续下去,原因是我试图在 DCI 意义上使用验证,因为有一个“TestValidator”角色。但仔细考虑之后,我认为您在上面指出的标准方法效果更好,因为在某种意义上验证就是数据。

以上是关于通过扩展向 ActiveRecord 模块添加自定义验证?的主要内容,如果未能解决你的问题,请参考以下文章

仅列出 ActiveRecord 子类方法

如何向 Rails 4 中的所有 ActiveRecord 模型添加 `audited` 方法调用?

LayUi创建一个自定义通用模块

Firebase onCreate 向 auth.user 添加自定义声明

向 ID 令牌 OpenID 添加自定义声明

Python / C-Api:向模块添加类