问题
What happens in the background with the following code?
class User < ActiveRecord::Base
attr_accessor :name
attr_accessible :name
end
Hint: When instantiating the class, will it be persisted to the database? Why or why not?
回答1:
attr_accessor is ruby code and is used when you do not have a column in your database, but still want to show a field in your forms. The only way to allow this is to attr_accessor :fieldname
and you can use this field in your View, or model, if you wanted, but mostly in your View.
attr_accessible allows you to list all the columns you want to allow Mass Assignment, as andy eluded to above. The opposite of this is attr_protected which means this field i do NOT want anyone to be allowed to Mass Assign to. More then likely it is going to be a field in your database that you don't want anyone monkeying around with. Like a status field, or the like.
回答2:
In most cases, you don't need to use attr_accessor
if the field is a column in the users
table in your database. ActiveRecord will figure it out for you.
attr_accessible
simply allows to field to be assigned via mass assignment (e.g., with update_attributes
). This is good for security purposes. More information from the MassAssignmentSecurity API docs.
回答3:
Thanks everyone for quick answers! Your answers combined gave me the pieces I needed to understand this puzzle, I think.
(In a related problem, I was getting a lot of nil errors like "Object doesn’t support #inspect", and "undefined method ‘keys’ for nil:NilClass". I managed to solve it now, by removing the att_accessor field altogether.)
By experimenting with this particular case, this is what I've found out:
Actually, the :name field won't be persisted to the database.
user = User.new(:name=>"somename")
Will only set the attribute on the object, but not persist the :name column to the database. Like the following 'rails console' output shows:
> user
=> <User id: nil, created_at: nil, updated_at: nil>
> user.save
=> true
> user
=> <User id:1, created_at: 2011-01-19 12:37:21, updated_at: 2011-01-19 12:37:21>
I assume this is because *the setter made by attr_accessor will override ActiveRecord's setter* (which takes care of the database persistence). You can still retrieve the value from the :name field from the object though, like this:
> user.name
=> "somename"
So, in conclusion, I've learnt that using attr_accessor on fields might lead to them not being persisted to the database. And while I thought attr_accessible describes fields in the database that should be accessible from the outside, it doesn't seem to make a difference in this case.
回答4:
Since it inherits ActiveRecord
, it will be persisted when you call the save
method (but not when it is instantiated).
If you don't have any attributes for that model, I assume ActiveRecord
will simply save a new row in the database (i.e. your object will only have a persisted id
). This makes sense, as you might later add attributes to your User
model, and the persisted instances should still be retrievable.
来源:https://stackoverflow.com/questions/4700785/using-attr-accessor-and-attr-accessible-on-the-same-field