简体   繁体   English

如何验证 Rails 模型中的两个值不相等?

[英]How do I validate that two values do not equal each other in a Rails model?

I have a User model, which has an email and a password field.我有一个 User 模型,它有一个电子邮件和一个密码字段。 For security, these may not be equal to each other.为了安全起见,这些可能并不相等。 How can I define this in my model?我如何在我的模型中定义它?

Create custom 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

But keep in mind that storing password as a plain text is bad idea.但请记住,将密码存储为纯文本是个坏主意。 You should store it hashed.您应该将其散列存储。 Try some authentication plugin like authlogic or Restful authentication .尝试一些身份验证插件,如authlogicRestful authentication

New way:新方法:

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

or:或者:

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

You can use a custom validation method to check this.您可以使用自定义验证方法来检查这一点。

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

it is much wiser to use custom validator, here is code for universal validator that can be used使用自定义验证器更明智,这里是可以使用的通用验证器的代码

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 [e.g. fields: [:giver_id, :receiver_id]"
    end
  end
end

and then use it like:然后像这样使用它:

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

It depends how Your password is stored:这取决于您的密码是如何存储的:

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

This would work if Your password is stored literally, but You can perform the same thing with email (eg create a hashed version) and check for equality with password.如果您的密码按字面存储,这将起作用,但您可以使用电子邮件执行相同的操作(例如创建散列版本)并检查与密码的相等性。 Eg:例如:

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

My example is taken from http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002162我的例子取自http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M002162

Your situation is quite general so You can be interested in creating custom validation method.您的情况非常普遍,因此您可能对创建自定义验证方法感兴趣。 Everything is covered here: http://guides.rubyonrails.org/active_record_validations_callbacks.html#creating-custom-validation-methods这里涵盖了所有内容: http : //guides.rubyonrails.org/active_record_validations_callbacks.html#creating-custom-validation-methods

more fun:更多乐趣:

  validates :password, exclusion: { in: ->(person) { [person.email] }, message: "cannot use protected password" }

which might be even better in this case, since you could check for other forbidden values with something like在这种情况下可能会更好,因为您可以使用类似的方法检查其他禁止值

  validates :password, exclusion: { in: ->(person) { [person.email, person.first_name, person.last_name, person.phone_number, person.department_name] }, message: "cannot use protected password" }

all you need is to create validation rule in your model for example例如,您只需要在模型中创建验证规则

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

If you want to support multiple languages, you have to come up with another solution, which translates the error messages and the attribute names.如果您想支持多种语言,您必须想出另一种解决方案,它可以翻译错误消息和属性名称。 So I created a new each validator for that.所以我为此创建了一个新的每个验证器。

validators/values_not_equal_validator.rb : 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

I call it in the model like this:我在模型中这样称呼它:

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

And I translate it the messages like this:我把它翻译成这样的消息:

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

By using custom validations we can do this operation通过使用自定义验证,我们可以执行此操作

validate :validate_address验证:validate_address

def validate_address定义验证地址
errors.add(:permenent_address, "can't be the same as present_address") if self.present_address== self.permenent_address end errors.add(:permenent_address, "can't be the same as present_address") if self.present_address== self.permenent_address end

Ruby on Rails 7.0 添加了validates_comparison_of这样的validates_comparison_of验证的支持

validates :password, comparison: { other_than: :email }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM