我刚遇到Rails问题,我想用它们来验证我的模型。但我希望验证是通用的,因此仅当我包含我关注的类具有该属性时才使用验证。我认为这很容易,但我尝试了很多方法,比如使用column_names,constantize,send等等但没有任何作用。做正确的方法是什么?代码:
module CommonValidator
extend ActiveSupport::Concern
included do
validates :email, presence: { message: I18n.t(:"validations.commons.email_missing") },
format: { with: /\A[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\z/i,
message: I18n.t(:"validations.commons.email_wrong_format"),
allow_blank: true } if self.column_names.include? :email
end
end
class Restaurant < ActiveRecord::Base
include CommonValidator
.
.
.
end
餐厅当然有一个电子邮件属性。是否有可能检查包含我关注的类中是否存在属性?我希望将我的CommonValidations包含在许多不具有电子邮件属性的模型中。我正在使用rails 4。
答案 0 :(得分:1)
您可以在当前实例上使用respond_to?
,如下所示:
validates :email, presence: { message: I18n.t(:"validations.commons.email_missing") },
format: { with: /\A[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\z/i,
message: I18n.t(:"validations.commons.email_wrong_format"),
allow_blank: true },
if: lambda { |o| o.respond_to?(:email) }
@ coreyward建议的另一个选项是定义一个扩展EachValidator
的类。例如,对于电子邮件验证:
# app/validators/email_validator.rb
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value =~ /\A[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
record.errors[attribute] << (options[:message] || I18n.t(:"validations.commons.email_wrong_format"))
end
end
end
然后您可以将验证调用更新为:
validates :email,
presence: { message: I18n.t(:"validations.commons.email_missing") },
email: true,
allow_blank: true
答案 1 :(得分:1)
我正在寻找类似的东西,但有自定义验证。 我最终得到了一些我认为可以分享的东西,包括通用测试。
首先,设置问题app/models/concern/my_concern.rb
。
请注意,我们不会将validate_my_field
定义为ClassMethods
模块。
module MyConcern
extend ActiveSupport::Concern
included do
validate :my_field, :validate_my_field
end
private
def validate_my_field
...
end
end
将问题纳入您的模型app/models/my_model.rb
class MyModel < ActiveRecord::Base
include MyConcern
end
加载spec/support/rails_helper
中的共享示例:
…
Dir[Rails.root.join('spec/concerns/**/*.rb')].each { |f| require f }
…
创建关注共享示例spec/concerns/models/my_field_concern_spec.rb
:
RSpec.shared_examples_for 'my_field_concern' do
let(:model) { described_class } # the class that includes the concern
it 'has a valid my_field' do
instance = create(model.to_s.underscore.to_sym, my_field: …)
expect(instance).not_to be_valid
…
end
end
然后最后将共享示例调用到您的模型规范spec/models/my_model_spec.rb
:
require 'rails_helper'
RSpec.describe MyModel do
include_examples 'my_field_concern'
it_behaves_like 'my_field_concern'
end
我希望这可以提供帮助。