Rails将相同的验证应用于不同模型中的相同属性

时间:2014-05-06 23:31:00

标签: ruby-on-rails ruby validation oop ruby-on-rails-4

假设我的UserModelInvitationModel都包含属性email。让我们说我需要对这两个模型中的email进行相同的验证(例如,长度应该少于100个字符)。

而不是在两个模型中复制这个,这会使以后更改最大限额更难(如果有五个/六个或更多模型与电子邮件更多,我想在一个地方保持验证) 。但我宁愿把它作为一个组合而不是继承(因为用户有一封电子邮件,而不是用户是电子邮件)。

使用Ruby / Rails实现这一目标的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

您希望将验证放在模块中,并将其包含在需要验证的模型中。

module EmailValidation
    extend ActiveSupport::Concern

    included do
        validates :email, length: {minimum: 3, maximum: 100}, presence: true,   uniqueness: true
    end
end 

然后只包括模块

class User < ActiveRecord::Base
    include EmailValidation
    ...
end

答案 1 :(得分:1)

有两种方法可以做到这一点,我更喜欢将全局常量存储在初始化文件夹下。

例如:

创建初始化文件为/config/initializers/my_constants.rb

class MyConstants
  MAX_LENGTH = 100
  ##.. other constants
end

在此之后使用它在您的模型中:

validates :email, length: { maximum: MyConstants::MAX_LENGTH }

请注意,每次使用新的全局常量更新此初始化程序文件时,必须重新启动并使用rails s重新加载更改。

假设您有两个模型User,其中属性usernameemail以及Campaign包含属性nameemail

  • 当您需要对不同模型中具有相同/不同名称的属性进行相同的验证时,此方法会更有用,例如,在上述情况下,您可以对User#emailCampaign#email应用相同的验证。此外,您可以自由地对User#usernameCampaign#name使用相同的验证,即使它们的名称不同。
  • 即使在您需要一个选项(在minimum验证中说length)以获得相同价值但另一个选项(比如maximum验证中的length)要求的情况下不同的价值观 如果是User#usernameCampaign#name,则minimum to be 2 characters maximum User#username30 minimum需要Campaign#name 50app/models/concerns然后你就可以轻松实现这一目标。

就像我说的,你可以通过各种方式实现这一目标。 @CaptChrisD 建议的另一种方法 对于你需要完全相同的验证并且你不打算在将来调整它的情况也很好。

在这种情况下,您可以使用 ActiveSupport::Concern

您需要将模块放在email_validation.rb目录中,并将文件命名为module EmailValidation extend ActiveSupport::Concern included do validates :email, length: { minimum: 5, maximum: 100 } end end

email

在此之后,您需要在class MyModel < ActiveRecord::Base include EmailValidation ## Add this ##.. end 字段中需要相同验证的模型中包含模块

{{1}}

这是对 Ruby Mixins & ActiveSupport::Concern 的精彩阅读,供您参考。

您还可以查看 SO Answer: Rails put validation in a module mixin?

答案 2 :(得分:1)

你可以write your own validator

class MyEmailValidator < ActiveModel::Validator
  def validate(record)
    # Whatever validation you want on the record
  end
end

然后在你的两个课程中使用它:

class User < ActiveRecord::Base
    validates_with MyEmailValidator
end

class InvitationModel < ActiveRecord::Base
    validates_with MyEmailValidator
end

当然,您也可以将它与模块或子类结合起来