1

这可能是一个非常愚蠢的问题,但我们开始吧

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 为属性 :group_id 创建访问器/突变器,这就是为什么一切都应该工作的原因。我错过了什么?

更新

好的答案如下,正如我在这里的动机的解释是我想使用某些属性的质量分配(从 Rails 3.2.x 开始你需要这个)。为此,您需要 attr_accessible ,我发现这样代码更干净,当然如果负责任地使用:)

4

4 回答 4

4

看起来group_id已经是您对象上的一个属性(从省略Foo时返回 106 的事实可以看出)。attr_accessor通过添加attr_accessor,您将覆盖已经存在的内容并创建一个名为 reader 和 writer 的方法group_id。新定义的返回group_id为零,因为您没有定义任何内容。

从概念上讲,你最终会得到这样的结果:

class Foo < ActiveRecord::Base
  def group_id  # overriding previous definition of 'group_id'
    nil
  end
end


编辑:

如果您的目标是公开属性,那么可以,使用attr_accessible

于 2012-07-17T11:13:24.980 回答
4

这是因为 ActiveRecord 自动将数据库表中的属性映射到实际模型中的属性。当您添加时attr_accessor,您使用自己的新定义属性掩盖了数据库属性。

基本上,rails 会自动attr_accessor为相应数据库表中的所有属性定义(或类似的东西)。

如果您正在寻找一些方法来使您的某些属性仅可用于多重分配,您应该查看attr_accessible.

于 2012-07-17T11:15:29.723 回答
0

如果没有访问器,肯定你'belongs_to :group' 的 Foo 模型中有一个,所以如果你调用 'group_id' 到 'Foo' 的一个实例,你将得到这个字段的值。

例如,如果您设置了一个名为该属性(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"
于 2012-07-17T11:17:31.333 回答
0

如果表中有名为 group_id 的列,则 ActiveRecord 会为您定义访问器。当你像你一样覆盖它时,你的调用只是搜索一个名为 group_id 的常规实例变量,它返回 nil。

于 2012-07-17T11:20:31.330 回答