Метапрограммирование Ruby / Rails: создание вспомогательных методов на лету - PullRequest
2 голосов
/ 08 июня 2011

Я пытаюсь динамически сгенерировать несколько методов подсчета для заданного массива имен моделей, которые затем можно использовать в представлении / помощнике:

  # create dynamic count methods for each model we want                   
  ['model', 'other_model', 'next_model'].each do |name|
     class_eval{
       "def total_#{name.underscore}s_count
          total_#{name.underscore}s_count ||= #{name.camelcase}.all.count
        end"
      }
  end

Однако у меня есть несколько вопросов:

  1. Куда должен идти этот код, если я хочу иметь возможность вызывать эти методы в представлении?
  2. К какому классу будут добавлены эти методы? Например, как бы мне позвонить им, поскольку я не уверен, принадлежат ли они классу User и т. Д., Поскольку они предназначены для нескольких моделей.
  3. Есть ли лучший способ сделать это?

Ответы [ 2 ]

3 голосов
/ 08 июня 2011

Вы должны использовать миксин и включить его в соответствующие классы моделей. http://juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby/

Методы будут доступны для экземпляров модели в ваших представлениях.

1 голос
/ 08 июня 2011

Проблема, которую вы пытаетесь решить (не допуская попадания в свои методы в моделях), не решается путем делегирования той же логики помощнику представления. Вы должны делать это в своих контроллерах, если хотите придерживаться соглашения MVC, согласно которому ваши представления не должны запускать запросы SQL.

def index
  models = Foo, Bar, Bat
  @counts = models.inject({}) do |result, model|
    result[model.name.downcase.to_sym] = model.count
    result
  end
end

Затем у вас есть хороший хэш подсчета каждой из пройденных моделей:

@counts #=> { :foo => 3, :bar => 59, :bat => 42 }
...