假设我的UserModel
和InvitationModel
都包含属性email
。让我们说我需要对这两个模型中的email
进行相同的验证(例如,长度应该少于100个字符)。
而不是在两个模型中复制这个,这会使以后更改最大限额更难(如果有五个/六个或更多模型与电子邮件更多,我想在一个地方保持验证) 。但我宁愿把它作为一个组合而不是继承(因为用户有一封电子邮件,而不是用户是电子邮件)。
使用Ruby / Rails实现这一目标的最佳方法是什么?
答案 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
,其中属性username
和email
以及Campaign
包含属性name
和email
User#email
和Campaign#email
应用相同的验证。此外,您可以自由地对User#username
和Campaign#name
使用相同的验证,即使它们的名称不同。minimum
验证中说length
)以获得相同价值但另一个选项(比如maximum
验证中的length
)要求的情况下不同的价值观
如果是User#username
和Campaign#name
,则minimum to be 2 characters
maximum
User#username
和30
minimum
需要Campaign#name
50
为app/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 的精彩阅读,供您参考。
答案 2 :(得分:1)
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
当然,您也可以将它与模块或子类结合起来