глобальные методы в моделях ruby on rails
У меня есть методы во всех моих моделей, которые выглядят так:
def formatted_start_date
start_date ? start_date.to_s(:date) : nil
end
Я хотел бы иметь что-то, что автоматически записывает такой метод для каждого поля datetime в каждой модели, каков наилучший способ сделать это?
- C
3 ответов
Я просто должен был ответить на этот вопрос, потому что это забавная тренировка Ruby.
добавление методов в класс может быть сделано многими способами, но одним из самых аккуратных способов является использование некоторых функций отражения и оценки Ruby.
создайте этот файл в папке lib как lib / date_methods.rb
module DateMethods
def self.included(klass)
# get all dates
# Loop through the class's column names
# then determine if each column is of the :date type.
fields = klass.column_names.select do |k|
klass.columns_hash[k].type == :date
end
# for each of the fields we'll use class_eval to
# define the methods.
fields.each do |field|
klass.class_eval <<-EOF
def formatted_#{field}
#{field} ? #{field}.to_s(:date) : nil
end
EOF
end
end
end
теперь просто включите его в любые модели, которые нуждаются в нем
class CourseSection < ActiveRecord::Base
include DateMethods
end
при включении модуль будет смотреть на любые столбцы даты и генерировать форматированные_ методы для вас.
узнайте, как работает этот рубиновый материал. Это очень весело.
- b -
это больше похоже на что-то для помощника для меня. Попробуйте это в справке по вашему приложению:
def formatted_date(date)
date ? date.to_s(:date) : nil
end
форматирование-это не то, что действительно принадлежит модели (именно по этой причине вы обнаружили... размещение такого общего кода в каждой модели раздражает)
Если вы действительно хотите сделать, как вы говорите, то то, что вы могли бы сделать, это monkeypatch суперкласс ActiveRecord и добавить функцию, которую вы хотите там. Тогда он будет доступен для всех ваших модели. Остерегайтесь, что monkeypatching может привести к непредсказуемому и неопределенному поведению и использовать на свой страх и риск! Это также довольно hacky:)
class ActiveRecord::Base
def formatted_start_date
start_date ? start_date.to_s(:date) : nil
end
end
просто вставьте, что где-то, что будет работать, прежде чем что-либо еще в вашем приложении будет, и он будет динамически добавлять метод в базовый класс ваших моделей, делая его доступным для использования.
или вы можете создать mixin для всех ваших моделей, но это кажется немного излишним для одного метода.
ответ на ваш комментарий: Вы можете извлечь общий код / функциональность в модули, которые вы включаете в класс (я верю, что это называется mixin?), или вы можете пойти на подклассы. Я не думаю, что подкласс-это путь, когда его обычная функциональность, которую вы хотите получить в свои объекты, а не реальная ситуация наследования.
посмотри этого для получения дополнительной информации о модулях и Ruby.