глобальные методы в ruby ​​на рельсовых моделях - PullRequest
6 голосов
/ 14 мая 2009

У меня есть методы во всех моих моделях, которые выглядят так:

def formatted_start_date
  start_date ? start_date.to_s(:date) : nil
end

Мне бы хотелось, чтобы что-то автоматически записывало метод, подобный этому, для каждого поля даты и времени в каждой модели, каков наилучший способ сделать это?

-C

Ответы [ 3 ]

16 голосов
/ 16 мая 2009

Я просто должен был ответить на это, потому что это забавная тренировка по Руби.

Добавление методов в класс может быть выполнено многими способами, но один из самых полезных способов - это использовать некоторые функции отражения и оценки 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

При включении модуль просматривает любые столбцы даты и генерирует для вас методы formatted_.

Узнайте, как работает этот Ruby. Это очень весело.

Тем не менее, вы должны спросить себя, если это необходимо. Я не думаю, что это лично, но опять же, было весело писать.

-b-

11 голосов
/ 14 мая 2009

Для меня это больше похоже на помощника. Попробуйте это в справке вашего приложения:

def formatted_date(date)
   date ? date.to_s(:date) : nil
end

Форматирование не является чем-то, что действительно принадлежит модели (именно по той причине, которую вы обнаружили ... вставлять такой общий код в каждую модель раздражает)

Если вы действительно хотите сделать, как вы говорите, то, что вы могли бы сделать, - это просто установить суперкласс ActiveRecord и добавить туда функцию, которую вы хотите. Затем он будет доступен для всех ваших моделей. Остерегайтесь того, что обезьяноподготовка может привести к непредсказуемому и неопределенному поведению и использовать на свой страх и риск! Это также довольно забавно:)

class ActiveRecord::Base
   def formatted_start_date
      start_date ? start_date.to_s(:date) : nil
   end
end

Просто отметьте это где-то, что будет запущено раньше, чем что-либо еще в вашем приложении, и оно будет динамически добавлять метод в базовый класс ваших моделей, делая его доступным для использования.

Или вы можете создать миксин для всех ваших моделей, но это кажется немного излишним для одного метода.

0 голосов
/ 14 мая 2009

Ответ на ваш комментарий: Вы можете извлечь общий код / ​​функциональность в модули, которые вы включаете в класс (я полагаю, это называется mixin?) Или вы можете перейти на подклассы. Я не думаю, что подкласс - это путь, когда его обычная функциональность, которую вы хотите использовать в своих объектах, а не реальная ситуация наследования.

Посмотрите на это для получения дополнительной информации о модулях и Ruby .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...