Reputation: 614
Usually when we create a model, say User
, its attributes match with database fields.
For example, if my corresponding database table users_development
has fields name
and score
then when I create an instance of the User
class I simply type user = User.create(:name => "MyName", :score => 85)
.
Now, Devise created a migration file including fields email
and encrypted_password
, but I cannot see the field password
(which is quite logically from the security point of view).
While looking through forum posts I saw many examples like User.create(:email =>"[email protected]", :password => "foo")
. So, where did the password
come from? It is not a field of table users_development
. What is going on behind the scene? I looked through the documentation on http://rubydoc.info/github/plataformatec/devise/master/Devise but couldn't find any explanation.
Upvotes: 0
Views: 84
Reputation: 20948
This method from devise source code does the trick :
# Generates password encryption based on the given value.
def password=(new_password)
@password = new_password
self.encrypted_password = password_digest(@password) if @password.present?
end
When calling create, update attributes, build, etc, rails will try to call for each field the method field=
, so when you pass :password => 'foo'
to create
it will do something like :
user = User.new
user.password = 'foo'
user.save
Here this method allows to build the model with an unhashed password but to store the hashed password in the database.
Upvotes: 2
Reputation: 124469
User.create(:email => "[email protected]", :password => "foo")
does not directly create a database record with those exact fields. Rather, it uses public_send("#{k}=", v)
for each pair in the parameters hash. So really, it's doing something like this internally:
user = User.new
user.email = "[email protected]"
user.password = "foo"
user.save
Even though you don't have a password
database field, Devise's DatabaseAuthenticatable
module adds a password=
method, which updates the encrypted_password
field:
def password=(new_password)
@password = new_password
self.encrypted_password = password_digest(@password) if @password.present?
end
Upvotes: 3