如何在Rails模型中validation两个值是否彼此不相等?

我有一个用户模型,它有一个电子邮件和一个密码字段。 为安全起见,这些可能并不相同。 我怎样才能在我的模型中定义它?

创建自定义validataion :

validate :check_email_and_password def check_email_and_password errors.add(:password, "can't be the same as email") if email == password end 

但请记住,将密码存储为纯文本是个坏主意。 你应该把它存储起来。 尝试一些身份validation插件,如authlogic或Restful身份validation 。

您可以使用自定义validation方法来检查此问题。

 class User < ActiveRecord::Base # ... def validate if (self.email == self.password) errors.add(:password, "password cannot equal email") errors.add(:email, "email cannot equal password") end end end 

新方法:

 validates :password, exclusion: { in: lambda{ |user| [user.email] } } 

要么:

 validates :password, exclusion: { in: ->(user) { [user.email] } } 

这取决于您的密码存储方式:

 class User < ActiveRecord::Base validate :email_and_password_validation def email_and_password_validation if self.email == self.password errors.add_to_base("Password must be different from email") end end end 

如果您的密码是按字面意思存储的,那么这将起作用,但您可以使用电子邮件执行相同的操作(例如,创建哈希版本)并检查密码是否相等。 例如:

 class User < ActiveRecord::Base validate :email_and_password_validation def email_and_password_validation if make_hash(self.email) == self.hashed_password errors.add_to_base("Password must be different from email") end end end 

我的例子来自http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002162

您的情况非常普遍,因此您可能有兴趣创建自定义validation方法。 这里涵盖了所有内容: http : //guides.rubyonrails.org/active_record_validations_callbacks.html#creating-custom-validation-methods

使用自定义validation器更明智,这里是可以使用的通用validation器的代码

 class ValuesNotEqualValidator < ActiveModel::Validator def validate(record) if options[:fields].any? && options[:fields].size >= 2 field_values = options[:fields].collect { |f| record.send(f) } unless field_values.size == field_values.uniq.size record.errors[:base] << (options[:msg].blank? ? "fields: #{options[:fields].join(", ")} - should not be equal" : options[:msg]) end else raise "#{self.class.name} require at least two fields as options [eg fields: [:giver_id, :receiver_id]" end end end 

然后使用它像:

 class User < ActiveRecord::Base # ... validates_with ValuesNotEqualValidator, fields: [:email, :password], msg: "This Person is evil" end 

您所需要的只是在模型中创建validation规则

 class User < ActiveRecord::Base def validate_on_create if email == password errors.add("password", "email and password can't be the same") end end end 

如果要支持多种语言,则必须提供另一种解决方案,该解决方案可以转换错误消息和属性名称。 所以我为此创建了一个新的validation器。

validators/values_not_equal_validator.rb

 class ValuesNotEqualValidator < ActiveModel::EachValidator def validate(record) @past = Hash.new super end def validate_each(record, attribute, value) @past.each do |k, v| if v == value record.errors.add(attribute, I18n.t('errors.messages.should_not_be_equal_to') + " " + record.class.human_attribute_name(k)) end end @past[attribute] = value end end 

我在模型中称它为:

 class User < ActiveRecord::Base validates :forename, :surname, values_not_equal: true end 

我将它翻译成这样的消息:

 de: activerecord: attributes: user: forename: 'Vorname' surname: 'Nachname' errors: messages: should_not_be_equal_to: 'darf nicht gleich sein wie' 

通过使用自定义validation,我们可以执行此操作

validate:validate_address

def validate_address
如果self.present_address == self.permenent_address end,errors.add(:permenent_address,“不能与present_address相同”)