2

我最近被这个咬了,准确地知道发生了什么事情会发生这种情况会很有用,所以其他人会避免这个错误。

我有一个模型用户,其架构如下:

create_table "users", :force => true do |t|
    t.string   "user_name"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email"
    t.string   "location"
    t.string   "town"
    t.string   "country"
    t.string   "postcode"
    t.boolean  "newsletter"

在 user.rb 类中,我有一个 attr_accessor 用于三种方法:

class User < ActiveRecord::Base

# lots of code

  attr_protected :admin, :active

# relevant accessor methods

  attr_accessor :town, :postcode, :country 

end

现在在我的用户控制器中,如果我有以下方法:

def create
    @user = User.new params[:user]
end

当我尝试使用此参数哈希中的内容创建新用户时:

  --- !map:HashWithIndifferentAccess 
  # other values
  country: United Kingdom
  dob(1i): "1985"
  dob(2i): "9"
  dob(3i): "19"
  town: london

返回的对象对于country,town和 postcodepostcode值有空字符串,就像这样。

(rdb:53) y user1
--- !ruby/object:User 
attributes: 
  # lots of attributes that aren't relevant for this example, and are filled in okay
  postcode: 
  country: 
  town: 

我可以看出 attr_accessor 方法正在破坏 Active Record 现有的访问器方法,因为当我将它们取出时一切正常,因此解决方案相当简单——只需取出它们即可。

但是这里到底发生了什么?

我在Rails API 文档中查看 Active RecordRuby 自己的文档 aboutattr_accessor,但我仍然对attr_accessor这里的破坏方式有点模糊。

有没有人能够提供一些启示来阻止其他一些可怜的灵魂对此犯规?

4

3 回答 3

8

当你添加一个attr_accessor 到一个类时,它定义了两个方法,例如User#postcode 和User#postcode=。

如果访问器的名称等于模型属性的名称,事情就会中断(如果你不小心的话)。当您为模型分配属性时,会调用 User#postcode= ,在您的情况下它什么也不做,除了

@postcode = value

所以该值只是存储在实例变量中,不会出现在属性哈希中。

而在正常情况下(没有访问器),这将转到 method_missing 并最终触发类似

write_attribute(:postcode, value)

然后它会出现在模型的属性中。希望这是有道理的。

于 2009-09-19T12:13:45.183 回答
0

您可能希望attr_accessible在 ActiveRecord 模型上使用以启用属性的批量分配。您不需要attr_accessor,因为已经为模型属性定义了 getter / setter。

于 2009-09-19T12:43:07.240 回答
0

你为什么首先使用 attr_accessor :town, :postcode, :country?Active Record 为您提供了 setter/getter 方法。放下那条线,事情应该会奏效。

于 2009-09-19T12:04:43.970 回答