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

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

Ajedi32
источник

Ответы:

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
mipadi
источник
Хеш-нотация может работать, но self.attributeперебивает стек на 3.2.16.
jrhorn424
Это имеет то преимущество, что поддерживает ||=дефолт:def name; self[:name] ||= 'anon'; end
Пол Кантрелл
Для меня эта хэш-нотация работает. Но я не знаю причину, почему это работает. Может кто-нибудь объяснить?
Radiantshaw
-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"
chriseppstein
источник