在同一字段上使用 attr_accessor 和 attr_accessible
使用以下代码在后台会发生什么?
class User < ActiveRecord::Base
attr_accessor :name
attr_accessible :name
end
提示:实例化类时,会持久化到数据库吗?为什么或为什么不呢?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
attr_accessor 是 ruby 代码,当您的数据库中没有列,但仍想在表单中显示字段时使用。允许此操作的唯一方法是
attr_accessor :fieldname
,如果需要,您可以在视图或模型中使用此字段,但主要是在视图中。attr_accessible 允许您列出您想要允许批量分配的所有列,正如 andy 上面所回避的那样。与此相反的是 attr_protected ,这意味着我不希望任何人被允许批量分配该字段。更有可能的是,它会成为您数据库中的一个字段,您不希望任何人乱动。比如状态字段等。
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.
在大多数情况下,如果该字段是数据库中
users
表中的列,则不需要使用attr_accessor
。 ActiveRecord 会为您解决这个问题。attr_accessible
仅允许通过批量分配(例如,使用update_attributes
)来分配字段。这对于安全目的很有好处。更多信息请参阅 MassAssignmentSecurity API 文档 。In most cases, you don't need to use
attr_accessor
if the field is a column in theusers
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., withupdate_attributes
). This is good for security purposes. More information from the MassAssignmentSecurity API docs.感谢大家的快速解答!
我想,你的答案综合起来给了我理解这个难题所需的部分。
(在一个相关的问题中,我收到了很多 nil 错误,例如“对象不支持 #inspect”和“nil:NilClass 的未定义方法'keys'”。我现在通过删除 att_accessor 字段设法解决了它)
通过对这种特殊情况进行实验,我发现:
实际上, :name 字段不会保留到数据库中。
只会在对象上设置属性,但不会将 :name 列保留到数据库中。就像下面的“rails console”输出所示:
我认为这是因为 *attr_accessor 生成的 setter 将覆盖 ActiveRecord 的 setter*(负责数据库持久性)。不过,您仍然可以从对象的 :name 字段中检索值,如下所示:
因此,总而言之,我了解到在字段上使用 attr_accessor 可能会导致它们无法保留到数据库中。虽然我认为 attr_accessible 描述了数据库中应该可以从外部访问的字段,但在这种情况下似乎没有什么区别。
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.
Will only set the attribute on the object, but not persist the :name column to the database. Like the following 'rails console' output shows:
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:
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.
由于它继承了
ActiveRecord
,因此当您调用save
方法时(但在实例化它时不会),它将被持久化。如果您没有该模型的任何属性,我假设
ActiveRecord
将仅在数据库中保存一个新行(即您的对象将仅具有持久的id
)。这是有道理的,因为您稍后可能会向您的User
模型添加属性,并且持久化的实例应该仍然是可检索的。Since it inherits
ActiveRecord
, it will be persisted when you call thesave
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 persistedid
). This makes sense, as you might later add attributes to yourUser
model, and the persisted instances should still be retrievable.