Переопределить методы атрибута ActiveRecord - PullRequest
147 голосов
/ 17 декабря 2008

Пример того, о чем я говорю:

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. Я думал, что должно быть что-то не так с тем, что я делаю в примере выше; в противном случае, почему они благословили бы эти методы как «правильный способ» переопределить методы атрибута? Они также вынуждают гораздо более уродливую идиому, поэтому должна быть веская причина ...

Мой реальный вопрос: что-то не так с этим примером?

Ответы [ 4 ]

208 голосов
/ 19 декабря 2008

Повторяя комментарии Гарета ... ваш код не будет работать так, как написано. Это следует переписать так:

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

def name
  read_attribute(:name).downcase  # No test for nil?
end
91 голосов
/ 24 июня 2009

В качестве дополнения к ответу Аарона Лонгвелла вы также можете использовать «хэш-нотацию» для доступа к атрибутам, которые имеют переопределенные методы доступа и мутаторы:

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

def name
  self[:name].downcase
end
7 голосов
/ 22 января 2010

По этой теме доступна отличная информация на http://errtheblog.com/posts/18-accessor-missing.

Суть в том, что ActiveRecord правильно обрабатывает супер-вызовы для средств доступа к атрибутам ActiveRecord.

0 голосов
/ 03 июля 2009

У меня есть плагин rails, который заставляет атрибуты переопределять работу с super, как и следовало ожидать. Вы можете найти его на 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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...