Переопределить методы атрибута ActiveRecord
Пример того, о чем я говорю:
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 docs, и он предлагает использовать методы read_attribute
и write_attribute
. Я думал, что что-то не так с тем, что я делаю в приведенном выше примере; в противном случае, почему они благословляют эти методы как "правильный путь" для переопределения методов атрибутов? Они также вызывают гораздо более уродливую идиому, поэтому должна быть веская причина...
Мой реальный вопрос: что-то не так с этим примером?
Ответы
Ответ 1
Повторяя комментарии Гарета... ваш код не будет работать так, как написано. Его следует переписать следующим образом:
def name=(name)
write_attribute(:name, name.capitalize)
end
def name
read_attribute(:name).downcase # No test for nil?
end
Ответ 2
В качестве расширения для ответа Аарона Лонгвелла вы также можете использовать "хэш-нотацию" для доступа к атрибутам с переопределенными аксессуарами и мутаторами:
def name=(name)
self[:name] = name.capitalize
end
def name
self[:name].downcase
end
Ответ 3
В этой теме есть большая информация по http://errtheblog.com/posts/18-accessor-missing.
Длинным и коротким является то, что ActiveRecord корректно обрабатывает супервызов для аксессуаров атрибутов ActiveRecord.
Ответ 4
У меня есть плагин rails, который заставляет атрибут overriding работать с супер, как и следовало ожидать. Вы можете найти его на 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"