Динамическое определение атрибутов модели Rails

У меня есть модель (упрощенная версия ниже — в полной версии намного больше полей), по которой я хочу выполнить поиск.

class Media < ActiveRecord::Base

  attr_accessible :subject, :title, :ref_code

  validates :title, :presence => true
  validates :subject, :presence => true

  def self.search(terms_hash)
    return if terms_hash.blank?

    composed_scope = self.scoped

    terms_hash.each_pair do |key, value|
    if self.respond_to? key and not value.is_blank?
      value.split(' ').each do |term|
        term = "%#{term}%"
        composed_scope = composed_scope.where("#{key} LIKE ?", term)
      end
    end
    composed_scope
  end
end

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

/search?utf8=✓&ref_code=111&title=test&subject=code&commit=Search

тогда мой контроллер может просто вызвать Media.search(params), и он вернет область, которая будет искать в соответствующих полях соответствующие значения. Как видите, я пытался использовать respond_to?, но он определен только для экземпляров модели, а не для фактического класса модели, и мне нужно что-то, что игнорирует любые параметры, не связанные с моделью (например, utf8 и commit в таком случае). Если все это работает хорошо, я планирую реорганизовать код, чтобы можно было повторно использовать один и тот же метод для нескольких моделей.

Есть ли метод класса, похожий на respond_to?? Как бы вы поступили с той же задачей?

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


person richard    schedule 15.01.2013    source источник


Ответы (1)


Существует метод columns для классов моделей ActiveRecord. поэтому вы можете легко получить список имен атрибутов:

names = Model.columns.map(&:name)

Вы можете достаточно легко удалить несколько распространенных:

names = Model.columns.map(&:name) - %w[id created_at updated_at]

Также может представлять интерес метод класса accessible_attributes, который расскажет вам, что было передано attr_accessible.

person mu is too short    schedule 15.01.2013
comment
Спасибо. Метод столбцов идеально подходит для моих нужд! Мне всегда очень трудно найти то, что мне нужно в API, из-за того, что все распределено по стольким классам и модулям. - person richard; 15.01.2013
comment
Быстрое обновление: я также наткнулся на columns_hash, который использует имена столбцов в качестве ключей и ту же информацию, что и columns для значений. - person richard; 16.01.2013