глобальные методы в моделях 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.