在同一个字段上使用attr_accessor和attr_accessible

时间:2011-01-15 16:45:17

标签: ruby-on-rails field attr-accessible attr-accessor

使用以下代码在后台会发生什么?

class User < ActiveRecord::Base

 attr_accessor :name
 attr_accessible :name

end

提示:实例化类时,是否会持久化到数据库?为什么或为什么不呢?

4 个答案:

答案 0 :(得分:70)

attr_accessor是ruby代码,在数据库中没有列但仍希望在表单中显示字段时使用。允许此操作的唯一方法是attr_accessor :fieldname,如果您愿意,可以在视图或模型中使用此字段,但主要在您的视图中。

attr_accessible允许您列出要允许批量分配的所有列,如上所述。与此相反的是attr_protected,这意味着这个字段我不希望任何人被允许进行质量分配。更有可能的是,你不希望任何人围绕着你的数据库中的一个字段。像状态字段一样。

答案 1 :(得分:5)

在大多数情况下,如果字段是数据库中attr_accessor表中的列,则不需要使用users。 ActiveRecord会为你解决这个问题。

attr_accessible只允许通过质量分配来指定字段(例如,使用update_attributes)。这有利于安全目的。来自MassAssignmentSecurity API docs的更多信息。

答案 2 :(得分:4)

感谢大家快速解答! 你的答案结合起来给了我理解这个难题所需的部分,我想。

(在一个相关的问题中,我得到了很多nil错误,例如“Object不支持#inspect”,以及nil的“undefined方法'键':NilClass”。我设法现在通过删除完全是att_accessor字段。)

通过试验这个特例,这就是我发现的:

实际上,:name字段不会持久保存到数据库中。

user = User.new(:name=>"somename")

只会在对象上设置属性,但不会将:name列保存到数据库中。像下面的'rails console'输出显示:

> 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>

我认为这是因为* attr_accessor创建的setter将覆盖ActiveRecord的setter *(它负责数据库持久性)。您仍然可以从对象的:name字段中检索值,如下所示:

> user.name
=> "somename"

因此,总而言之,我已经了解到在字段上使用attr_accessor可能会导致它们不会持久存储到数据库中。虽然我认为attr_accessible描述了数据库中应该可以从外部访问的字段,但在这种情况下似乎没有什么区别。

答案 3 :(得分:1)

由于它继承了ActiveRecord,因此在调用save方法时会保留它(但在实例化时不会保留)。

如果你没有该模型的任何属性,我认为ActiveRecord只会在数据库中保存一个新行(即你的对象只有一个持久的id)。这是有道理的,因为您稍后可能会向User模型添加属性,并且仍应检索持久化实例。