这可能是一个非常愚蠢的问题但是我们走了
class Foo < ActiveRecord::Base
attr_accessor :group_id
end
来自 irb
# gets record which has group_id set to 106
foo = Foo.find(1)
foo.group_id
=> nil
如果我去除
attr_accessor:group_id
一切正常,
foo = Foo.find(1)
foo.group_id
=> 106
我的问题是为什么?不应该为attr_accessor创建属性的accessor / mutator:group_id以及为什么所有应该都有效。我错过了什么?
更新
下面有好的答案,就像我在这里的动机解释一样,我想使用某些属性的质量分配(从Rails 3.2.x起你需要这个)。为此您需要attr_accessible,我发现代码更加清晰,当然如果负责任地使用:)
答案 0 :(得分:4)
看起来group_id
已经是Foo
对象上的属性(由省略attr_accessor
时返回106的事实显示)。通过添加attr_accessor
,您将覆盖已存在的内容并创建名为group_id
的方法读取器和编写器。由于您没有定义任何内容,因此新定义的group_id
的返回值为零。
从概念上讲,你最终会遇到这样的事情:
class Foo < ActiveRecord::Base
def group_id # overriding previous definition of 'group_id'
nil
end
end
<小时/> 修改强>
如果您的目标是公开属性,那么请使用attr_accessible
答案 1 :(得分:4)
这是因为ActiveRecord会自动将数据库表中的属性映射到实际模型中的属性。当您添加attr_accessor
时,您将使用您自己的新定义的属性覆盖数据库属性。
基本上,rails会自动为相应数据库表中的所有属性定义attr_accessor
(或类似的东西)。
如果您正在寻找一些方法来解决如何仅为多项任务设置某些属性,则应该查看attr_accessible
。
答案 2 :(得分:0)
如果没有访问者,肯定你的Foo模型中有一个'belongs_to :group'
,所以如果你将'group_id'称为'Foo'的实例,你将获得该字段的值。
例如,如果你设置一个名为like that attribute(group_id)的访问器,它将覆盖原始字段,如果没有分配任何值,它将返回nil。
class Foo < ActiveRecord::Base
attr_accessor :group_id
end
# gets record which has group_id set to 106
foo = Foo.find(1)
foo.group_id
=> nil
foo.group_id = "wadus"
=> "wadus"
foo.group_id
=> "wadus"
答案 3 :(得分:0)
如果表中有一个名为group_id的列,则ActiveRecord会为您定义访问者。当你像你一样覆盖它时,你的调用只是搜索一个名为group_id的常规实例变量,它返回nil。