Перевизначення методів атрибутів ActiveRecord


150

Приклад того, про що я говорю:

class Person < ActiveRecord::Base
  def name=(name)
    super(name.capitalize)
  end
  def name
    super().downcase  # not sure why you'd do this; this is just an example
  end
end

Це, здається, працює, але я щойно прочитав розділ про переважаючі методи атрибутів у документах ActiveRecord :: Base , і він пропонує використовувати read_attributeі write_attributeметоди. Я подумав, що має бути щось не так у тому, що я роблю у наведеному вище прикладі; в іншому випадку, чому б вони благословляли ці методи як "правильний шлях" для перекриття атрибутивних методів? Вони також змушують набагато потворнішу ідіому, тому має бути вагома причина ...

Моє справжнє запитання: чи не в цьому прикладі щось не так?

Відповіді:


211

Відгуки коментарів Гарета ... ваш код не працюватиме так, як написано. Це слід переписати так:

def name=(name)
  write_attribute(:name, name.capitalize)
end

def name
  read_attribute(:name).downcase  # No test for nil?
end

Саме те, що мені було потрібно. Спасибі Аарон
бон

18
Це вже не так. Або супер, або це працює зараз. Однак я не перевіряв хеш-позначення.
heartpunk

2
У рейках 3 метод зчитування, вказаний тут Аароном, працює, але автор, який вказав оригінальний плакат (подає ім’я супер), працює чудово, а IMHO чистіший, ніж вручну писати атрибут, як пропонує Аарон.
Баткінс

1
Я перевірив хеш-метод, поданий mipadi нижче, і він працює як шарм (Rails v 3.2.6)
almathie

Це не правильна відповідь? Дякую @Aaron, працював і для мене.
Садикша Гаутам

94

Як доповнення до відповіді Аарона Лонгвелла, ви також можете використовувати "хеш-нотацію" для доступу до атрибутів, які мають перекриті доступу та мутатори:

def name=(name)
  self[:name] = name.capitalize
end

def name
  self[:name].downcase
end

Хеш-нотація може спрацювати, але self.attributeпробиває стек 3.2.16.
jrhorn424

Це має ту перевагу, яку він підтримує ||=для дефолту:def name; self[:name] ||= 'anon'; end
Пол Кантрелл

Для мене це хеш-позначення працює. Але я не знаю, чому це працює. Може хтось пояснить?
радіантшоу

7

На цю тему доступна чудова інформація на http://errtheblog.com/posts/18-accessor-missing .

Довгий і короткий факт полягає в тому, що ActiveRecord правильно обробляє супервиклики для атрибутів атрибутів ActiveRecord.


-1

У мене є плагін для rails, який змушує атрибути переосмислювати роботу з супер, як можна було очікувати. Ви можете знайти його на github .

Щоб встановити:

./script/plugin install git://github.com/chriseppstein/has_overrides.git

Використовувати:

class Post < ActiveRecord::Base

  has_overrides

  module Overrides
    # put your getter and setter overrides in this module.
    def title=(t)
      super(t.titleize)
    end
  end
end

Після того, як ви все зробите:

$ ./script/console 
Loading development environment (Rails 2.3.2)
>> post = Post.new(:title => "a simple title")
=> #<Post id: nil, title: "A Simple Title", body: nil, created_at: nil, updated_at: nil>
>> post.title = "another simple title"
=> "another simple title"
>> post.title
=> "Another Simple Title"
>> post.update_attributes(:title => "updated title")
=> true
>> post.title
=> "Updated Title"
>> post.update_attribute(:title, "singly updated title")
=> true
>> post.title
=> "Singly Updated Title"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.