Proper flow for processing non-displayed database fields in RoR forms?
I have the following database table:
account
-
id
first_name
last_name
email_address
password_md5_hash
last_logged_in
last_ip_address
date_time_created
As you can see, an account record has several fields with values the user will not enter themselves. For instance, the password_md5_hash will be the hashed value of the password they enter, and date_time_created will be set to the current date/time when the record is created.
So, my form will not necessarily contain entry fields for all values, or the values entered will be manipulated before being written to the database (the same would be true if I wanted to strip HTML from a text field before saving to the database).
What would be the proper flow for 1) hashing the password entered in the form and storing that and 2) setting and storing the date_time_created field's value in the database on form submission? These things would take place in the model, no? Can someone provide a code sample or link to one that explain开发者_如何学运维s this?
Thanks.
The best way would probably to use an ActiveRecord callback, I will use an accessor here so when you create User.new(:password => "something") in your controller, it'll be assigned to something that's available, but not stored in the database.
class User < ActiveRecord::Base
attr_accessor :password
before_save :hash_password
...
private
def hash_password
attribute(:password_md5_hash => Digest::MD5.hexdigest(password))
end
end
I'm not that an MD5 is the best way to store passwords (I think the general accepted practice is to use a hash and a salt, check out the way restful_authentication or authlogic does it for best practices)
For date_time_created, you should checkout the 'created_at' and 'updated_at' fields that are already given to you. If you need another column, you can use the same callback technique if you need to manipulate it before saving to the database.
When using the attr_accessor, my understanding is you're basically creating a reader and writer, so:
attr_accessor :password
is equal to
#Reader
def password
@password
end
#Writer
def password=(pwd)
write_attribute( :password, pwd )
end
In cases like this where you need to modify the field before saving the model's info to DB, you just need to manually create the writer and modify it how you wish... so in this case take the writer method and use it to create the salt and encrypt... something like:
def password=(pwd)
@password = pwd
return if pwd.blank?
create_new_salt
self.password_md5_hash = User.encrypted_password(self.password, self.salt)
end
Examples of the methods used above:
def create_new_salt
self.salt = "#{object_id}#{rand}"
end
def self.encrypted_password(password, salt)
hashme = password + "morerandomtexthere" + salt
Digest::SHA1.hexdigest(hashme)
end
Also, for the date_time_created, just use "t.timestamps" in your migration and if I'm not mistaken, Rails will handle those for you.
精彩评论