Як я можу замінити метод getter у моделі ActiveRecord?


98

Я намагаюся замінити метод getter для моделі ActiveRecord. У мене є атрибут, який називається nameв моделі Category, і я хотів би мати можливість зробити щось подібне:

def name
  name_trans || name
end

Якщо name_transатрибут не є нульовим, поверніть його, інакше поверніть nameатрибут. Як би я це зробив?

Потім це слід називати так:

@category.name

Відповіді:


123

Style Guide Rails рекомендує використовувати self[:attr]більш read_attribute(:attr).

Ви можете використовувати його так:

def name
  name_trans || self[:name]
end

Чому краще? Не просто посилайтеся на інші сайти, включіть сюди відповідні біти. Посилання можуть стати недійсними
JamesT

2
Трохи більше контексту див. Тут: github.com/bbatsov/rails-style-guide/isissue/155
mimsugara

98

Оновлення: кращим методом згідно Посібника зі стилю Rails є використання self[:name]замість read_attributeта write_attribute. Я б закликав вас пропустити мою відповідь і замість цього віддавати перевагу цій .


Ви можете зробити це саме так, за винятком того, що вам потрібно використати, read_attributeщоб фактично отримати значення атрибута імені та уникнути рекурсивного виклику nameметоду:

def name 
  name_trans || read_attribute(:name)
end

2
Будь-яка ідея , чому Rubocop воліє self[:name]більш read_attribute[:name]?
Зак Сю

18

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

def name
  name_trans || super
end

це працює не тільки на методі отримання атрибутів, але і на асоціаціях методів отримання ter теж。


1
Це те, що зараз рекомендують посібники з Rails, для тих, хто набирається та встановлює: api.rubyonrails.org/classes/ActiveRecord/…
sandre89

5

Перевизначення та використання read_attributeне працює для асоціацій, але ви можете використовувати alias_method_chainзамість цього.

def name_with_override
  name_trans || name_without_override
end

alias_method_chain :name, :override

Чи можете ви навести належний приклад ...?
Arup Rakshit

Ну. Я щойно побачив доко . Тепер, якщо я зателефоную nameна об'єкт моделі, який з них буде називатися - name_with_overrideчи name_without_override?
Arup Rakshit

1
nameтепер подзвонить name_with_override. Якщо ви хочете з якоїсь причини викликати оригінальний метод, ви можете зателефонувати name_without_override.
Патрік Осіті

О, дивіться .. Дякую за ваші відповіді //
Arup Rakshit

2

Якщо ви використовуєте такі атрибути магазину

store :settings, accessors: [:volume_adjustment] 

або використовуючи дорогоцінні камені, як hstore_accessor дорогоцінне посилання

Таким чином, ви в кінцевому підсумку використовуєте storeметод на моделі, то щоб замінити той метод, який ви не можете використовувати self.read_attribute, замість цього ви повинні використовувати super:

def partner_percentage
  super.to_i || 10
end

0

Якщо хтось хоче оновити значення після 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

0

Можна використовувати метод read_attribute Rails. Рейки док


хоча це посилання може відповісти на запитання, лише відповіді на посилання заборонені в ТА, будь ласка, додайте до своєї відповіді якийсь контекст із того, що стоїть за цим посиланням. Дякую! :)
AJT82
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.