Reputation: 447
I am making a Ruby on Rails app and am having trouble setting some attributes of my model. The problem is that I have a :before_save method, yet for some reason the encrypted_password and salt aren't getting saved to the database. Here's the model:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :username, :email, :password
before_save :encrypt_password
...
private
def encrypt_password
logger.debug "Got to encrypt_password 1"
logger.debug "encrypted_password is #{ @encrypted_password }"
if @encrypted_password != nil and @encrypted_password != ""
return # @encrypted_password was already set
end
logger.debug "Got to encrypt_password 2"
@salt = make_salt if new_record?
logger.debug "New salt = #{ @salt }"
@encrypted_password = encrypt(@password)
logger.debug "New encrypted_password = #{ @encrypted_password }"
@password = "(encrypted)"
logger.debug "Got to encrypt_password 3"
end
In the log file, I see the following:
Started POST "/users" for 127.0.0.1 at Wed May 02 22:55:20 -0500 2012
Processing by UsersController#create as HTML
Parameters: {"commit"=>"Submit", "authenticity_token"=>"RY9fSMqb2+tdQ0fIjiEz8cfMTWTi012vCWdCvbxACLk=", "utf8"=>"\342\234\223", "user"=>{"username"=>"test6", "password"=>"[FILTERED]", "email"=>"[email protected]"}}
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
[1m[35mUser Exists (0.2ms)[0m SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('[email protected]') LIMIT 1
Got to encrypt_password 1
encrypted_password is
Got to encrypt_password 2
New salt = 4f3464029393829aa562e533773f668c8471c51231611f6f214e654275f37184
New encrypted_password = 0dafcff2fe75bb6f2b53afda79789cfe13bd3f733b817a0e2e30df98af5829bc
Got to encrypt_password 3
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "users" ("created_at", "email", "encrypted_password", "is_done", "last_seen", "salt", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?)[0m [["created_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["email", "[email protected]"], ["encrypted_password", nil], ["is_done", false], ["last_seen", nil], ["salt", nil], ["updated_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["username", "test6"]]
[1m[35m (0.7ms)[0m commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 7ms (ActiveRecord: 1.4ms)
So it's definitely making the salt and the encrypted password. Yet the database isn't getting updated?!
>> User.find(6)
=> #<User id: 6, username: "test6", email: "[email protected]", encrypted_password: nil, is_done: false, salt: nil, last_seen: nil, created_at: "2012-05-03 03:55:20", updated_at: "2012-05-03 03:55:20">
Upvotes: 1
Views: 1065
Reputation: 1719
Try using self.encrypted_password
.
ActiveRecord makes getter/setter methods for your attributes, i.e.
def encrypted_password
...
# return something from the db
end
def encrypted_password=(x)
...
# set something in the db to x
end
And when you write @encrypted_password
, you're not actually using these methods, so the database doesn't get updated.
You can see this in your log:
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "users" ("created_at", "email", "encrypted_password", "is_done", "last_seen", "salt", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?)[0m [["created_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["email", "[email protected]"], ["encrypted_password", nil], ["is_done", false], ["last_seen", nil], ["salt", nil], ["updated_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["username", "test6"]]
salt
and encrpyed_password
is being set to nil, because you didn't update the attribute, you updated a class member variable.
Upvotes: 2
Reputation: 4187
I think you forgot self.encrypted_password = @encrypted_password
at the end of def encrypt_password
.
Upvotes: 1