为什么 attr_accessor 会破坏 Ruby on Rails 模型中的现有变量? [英] Why does attr_accessor clobber the existing variables in this model in Ruby on Rails?

查看:17
本文介绍了为什么 attr_accessor 会破坏 Ruby on Rails 模型中的现有变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近被这件事咬了一口,准确地知道发生了什么事情会导致这种情况发生,这样其他人就可以避免这个错误.

I was bitten by this recently, and it'd be useful to know precisely what's happening to make this happen, so others avoid this mistake.

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

I have a model User, with a schema like so:

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:

In the class user.rb, I have a attr_accessor for three methods:

class User < ActiveRecord::Base

# lots of code

  attr_protected :admin, :active

# relevant accessor methods

  attr_accessor :town, :postcode, :country 

end

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

Now in my user controller, if I have the following method:

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

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

When when I try to create a new user with the contents in this params hash:

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

返回的对象对于countrytown 和postcode postcode 值有空字符串,就像这样.

The returned object has empty strings for the country, town and postcode postcode values, like so.

(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 现有的访问器方法,因为当我将它们取出时一切正常,所以解决方案相当简单 - 取出它们即可.

I can tell that the attr_accessor methods are clobbering Active Record's existing accessor methods, because when I take them out all works fine, so the solution is fairly straightforward - just take them out.

但是这里究竟发生了什么?

我在 中查看这里Active Record 的 Rails API 文档,在 Ruby 自己的关于 attr_accessor 的文档,但我对 attr_accessor 在这里破坏的方式仍然有些模糊.

I'm looking here in the Rails API docs for Active Record, and here in Ruby's own docs about attr_accessor, but I'm still slightly hazy about how attr_accessor is breaking things here.

有没有人能够阻止其他一些可怜的灵魂犯规?

Any able to shed some light to stop some other poor soul falling foul of this?

推荐答案

当你向一个类添加一个 attr_accessor 时,它定义了两个方法,例如用户#postcode 和用户#postcode=.

When you add an attr_accessor to a class, it defines two methods on it, e.g. User#postcode and User#postcode=.

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

If the name of the accessor is equal to a name of a model attribute, things break (if you're not careful). When you assign attributes to the model, User#postcode= is called and in your case it does nothing except

@postcode = value

所以该值只是存储在一个实例变量中,并没有出现在属性哈希中.

So the value just gets stored in an instance variable and doesn't appear in the attributes hash.

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

Whereas in a normal scenario (without an accessor) this would go to method_missing and eventually trigger something like

write_attribute(:postcode, value)

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

And then it would appear in your model's attributes. Hope that makes sense.

这篇关于为什么 attr_accessor 会破坏 Ruby on Rails 模型中的现有变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆