Почему attr_accessor блокирует существующие переменные в этой модели в Ruby on Rails?

StackOverflow https://stackoverflow.com/questions/1448414

  •  11-09-2019
  •  | 
  •  

Вопрос

Недавно меня это задело, и было бы полезно точно знать, что происходит, чтобы это произошло, чтобы другие избежали этой ошибки.

У меня есть модель пользователя, со схемой, подобной такой:

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

Когда, когда я пытаюсь создать нового пользователя с содержимым в этом параметре hash:

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

Возвращаемый объект содержит пустые строки для 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: 

Я могу сказать, что методы attr_accessor загромождают существующие методы доступа Active Record, потому что, когда я их удаляю, все работает нормально, поэтому решение довольно простое - просто удалите их.

Но что что именно происходит, когда здесь?

Я смотрю здесь, в Документы Rails API для Активной записи, и здесь в Собственные документы Ruby о attr_accessor, но я все еще немного смутно представляю , как attr_accessor это все здесь ломает.

Кто-нибудь может пролить какой-нибудь свет, чтобы остановить какую-нибудь другую бедную душу, впавшую в это нечестие?

Это было полезно?

Решение

Когда вы добавляете attr_accessor к классу, он определяет для него два метода, напримерПользователь#почтовый индекс и Пользователь#почтовый индекс=.

Если имя средства доступа равно имени атрибута модели, все ломается (если вы не будете осторожны).Когда вы назначаете атрибуты модели, вызывается User#postcode=, и в вашем случае он ничего не делает, кроме

@postcode = value

Таким образом, значение просто сохраняется в переменной экземпляра и не отображается в хэше атрибутов.

Принимая во внимание, что в обычном сценарии (без средства доступа) это привело бы к method_missing и в конечном итоге вызвало бы что-то вроде

write_attribute(:postcode, value)

И тогда это появится в атрибутах вашей модели.Надеюсь, в этом есть смысл.

Другие советы

Почему в первую очередь вы используете attr_accessor :town, :postcode, :country?У Active Record есть методы установки / получения для вас.Просто отбрось эту фразу, все должно сработать.

Возможно, вы захотите использовать attr_accessible в моделях ActiveRecord для обеспечения массового присвоения атрибутов.Тебе не нужно attr_accessor поскольку получатели / установщики уже определены для атрибутов модели.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top