2016-03-13 4 views
1

Я читаю Michael Hartl's Ruby On Rails Tutorial (3rd). В главе 9 приведен пример, показывающий, как обновлять информацию о пользователе. Я запутался в том, что allow_nil прилагается сюда. Я упростил код, как показано ниже:Как allow_nil пусть пустая строка проходит проверку

class User < ActiveRecord::Base 
    has_secure_password 
    validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 
end 

myuser=User.new(name: "Foo_bar",email: "[email protected]", password: "123456", password_confirmation: "123456") 
myuser.save 
myuser=User.find(myuser.id) 
myuser.update_attributes(name: "Bar_Foo",email: "[email protected]", password: "", password_confirmation: "") # It will succeed! But WHY? 

Я понимаю, что allow_nil: true пропускает проверку, когда значение проверяемого равна нулю. Тем не менее, очевидно, password: "" не является нулевым значением. Как может allow_nil: true разрешить пустую строку?

ответ

1

Вы можете попробовать это в IRB:

user = User.new 
    user.password = '123' 
    user.password_confirmation = '123' 
    user.password_digest.nil? => false 

    user = User.new 
    user.password = '' 
    user.password_confirmation = '' 
    user.password_digest.nil? => true 
+0

Неправильная пустая строка не равна нулю, и если вы попытались использовать любое значение, отличное от пустой строки, оно также вернет нуль. –

+0

'puts' всегда возвращает nil, это не значит, что' a' равно нулю. Протестируйте его с помощью 'a.nil?' – BroiSatse

+0

метод 'puts' возвращает nil – illusionist

1

Такое поведение обусловлено has_secure_password магии. Короче говоря, он проверяет, пуст ли заданный пароль или нет, и не присваивает ничего @password, если это так. Следовательно:

user = User.new 
user.password = '' # This is not an assignment, but invocation of `password=` method. 
user.password #=> nil 

Вы можете увидеть исходный код за password= методом здесь: https://github.com/rails/rails/blob/869a90512f36b04914d73cbf58317d953caea7c5/activemodel/lib/active_model/secure_password.rb#L122

Также отметим, что has_secure_password уже определяет проверку паролей по умолчанию, так что если вы хотите создать свой собственный, вы должны назвать его с has_secure_password validation: false

+0

'user.password.nil? # => false' как это будет nil –

+0

Это произойдет, только если в вашей модели реализовано 'has_secure_password'. – BroiSatse

+0

Да, я добавил в свой ответ проверить. –

Смежные вопросы