Как можно переписать метод getter в модели ActiveRecord?

Я пытаюсь перезаписать метод getter для модели ActiveRecord. У меня есть атрибут name в модели Category, и я хотел бы сделать что-то вроде этого:

def name
  name_trans || name
end

Если атрибут name_trans не равен nil, тогда верните его, иначе возвращайте атрибут name. Как мне это сделать?

Затем это должно быть вызвано обычно следующим образом:

@category.name

Ответ 1

Руководство по стилю Rails рекомендует использовать self[:attr] над read_attribute(:attr).

Вы можете использовать его следующим образом:

def name
  name_trans || self[:name]
end

Ответ 2

Обновление: предпочтительный метод в соответствии с Руководство по стилю Rails заключается в использовании self[:name] вместо read_attribute и write_attribute. Я бы посоветовал вам пропустить мой ответ и вместо этого предпочитаю этот.


Вы можете сделать это именно так, за исключением того, что вам нужно использовать read_attribute для фактического получения значения атрибута имени и избежать рекурсивного вызова метода name:

def name 
  name_trans || read_attribute(:name)
end

Ответ 3

Я хотел бы добавить еще один вариант для перезаписи метода getter, который просто: super.

def name
  name_trans || super
end

это работает не только по методам getter, но также и по методам getter.

Ответ 4

Переопределение получателя и использование read_attribute не работает для ассоциаций, но вместо этого вы можете использовать alias_method_chain.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

Ответ 5

Если вы используете атрибуты хранилища, такие как

store :settings, accessors: [:volume_adjustment] 

или используя драгоценные камни hstore_accessor ссылка gem

Итак, вы закончили использование метода store на модели, затем переопределите этот метод, который вы не можете использовать self.read_attribute, вместо этого вы должны использовать super:

def partner_percentage
  super.to_i || 10
end

Ответ 6

Если кто-то хочет обновить значение после name_trans в методе getter, вы можете использовать self [: name] =.

def name
  self[:name] = name_trans || self[:name]
  # don't do this, it will cause endless loop
  # update(name: name_trans)
end

Ответ 7

Вы можете использовать метод Rails read_attribute. Rails docs