为什么attr_accessor在Ruby on Rails中破坏了这个模型中的现有变量?

Chr*_*ams 2 ruby-on-rails accessor models

最近我被这种情况所困扰,确切地知道发生了什么事情是有用的,所以其他人避免这种错误.

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

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"
Run Code Online (Sandbox Code Playgroud)

在类user.rb中,我有三个方法的attr_accessor:

class User < ActiveRecord::Base

# lots of code

  attr_protected :admin, :active

# relevant accessor methods

  attr_accessor :town, :postcode, :country 

end
Run Code Online (Sandbox Code Playgroud)

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

def create
    @user = User.new params[:user]
end
Run Code Online (Sandbox Code Playgroud)

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

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

返回的对象为空字符串country,town以及邮政编码postcode值,就像这样.

(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: 
Run Code Online (Sandbox Code Playgroud)

我可以说attr_accessor方法正在破坏Active Record现有的访问器方法,因为当我把它们拿出来时一切正常,所以解决方案相当简单 - 只需将它们取出即可.

什么到底正在发生的时候,这里?

我在这里看看有关Active RecordRails API文档,这里有Ruby自己的文档attr_accessor,但我对于如何attr_accessor在这里破坏事物仍然有些模糊.

任何能够摆脱一些光线来阻止其他一些可怜的灵魂掉下来的犯规?

ale*_*dev 8

将attr_accessor添加到类时,它会在其上定义两个方法,例如User#postcode和User#postcode =.

如果访问者的名称等于模型属性的名称,则事情会中断(如果您不小心).当您为模型指定属性时,会调用User#postcode =,在您的情况下,除了

@postcode = value
Run Code Online (Sandbox Code Playgroud)

因此,值只存储在实例变量中,不会出现在属性哈希中.

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

write_attribute(:postcode, value)
Run Code Online (Sandbox Code Playgroud)

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