Understanding Rails validation: what does allow_blank do?

后端 未结 6 1810
一个人的身影
一个人的身影 2020-12-09 01:15

I\'m quite new to Rails and found a little snippet to validate presence and uniqueness step by step: first check presence, then check uniqueness.

validates :         


        
6条回答
  •  眼角桃花
    2020-12-09 02:17

    In your code, :presence => and :uniqueness => are validators, while :allow_blank => is a default option that gets passed to other validators.

    So your code:

    validates(
        :email,
        :presence => true,
        :allow_blank => true,
        :uniqueness => { :case_sensitive => false }
    )
    

    Is equivalent to this code:

    validates(
        :email,
        :presence => { :allow_blank => true },
        :uniqueness => { :allow_blank => true, :case_sensitive => false }
    )
    

    However, the presence validator ignores the allow_blank option, so your code ends up being essentially this:

    validates(
        :email,
        :presence => { }, # `{ }` is equivalent to `true`
        :uniqueness => { :allow_blank => true, :case_sensitive => false }
    )
    

    Having :allow_blank => true in :uniqueness means that when the email is blank, the uniqueness validation will not be run.

    One effect of this is that you eliminate a DB query.

    E.g., without the :allow_blank => true condition you would see this:

    >> user = User.new(email: nil)
    >> user.valid?
      User Exists (0.2ms) SELECT  1 AS one FROM "users" WHERE "users"."name" IS NULL LIMIT 1
    => false
    >> user.errors.messages
    => {:email=>["can't be blank"]}
    

    But with the :allow_blank => true option you won't see that User Exists DB query happen.

    Another edge-case side effect happens when you have a record with a blank email address in your DB already. In that case if you don't have the :allow_blank => true option on the uniqueness validator, then you'll see two errors come back:

    >> user = User.new(email: nil)
    >> user.valid?
      User Exists (0.2ms) SELECT  1 AS one FROM "users" WHERE "users"."name" IS NULL LIMIT 1
    => false
    >> user.errors.messages
    => {:email=>["has already been taken", "can't be blank"]}
    

    But with the :allow_blank => true option you'll only see the "can't be blank" error (because the uniqueness validation won't run when the email is blank).

提交回复
热议问题