attr_accessor,无法访问属性

时间:2012-07-17 11:09:10

标签: ruby-on-rails ruby

这可能是一个非常愚蠢的问题但是我们走了

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,我发现代码更加清晰,当然如果负责任地使用:)

4 个答案:

答案 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。