Переопределение «найти» в ActiveRecord СУХОЙ способ - PullRequest
5 голосов
/ 17 сентября 2008

У меня есть несколько моделей, для которых необходимо настроить условия поиска. Например, если у меня есть модель контакта, каждый раз, когда вызывается Contact.find, я хочу ограничить возвращенные контакты, принадлежащие только используемой учетной записи.

Я нашел это через Google (который я немного настроил):

def self.find(*args)
  with_scope(:find => { :conditions =>  "account_id = #{$account.id}" }) do
    super(*args)
  end
end

Это прекрасно работает, за исключением нескольких случаев, когда account_id является неоднозначным, поэтому я адаптировал его к:

def self.find(*args)
  with_scope(:find => { :conditions =>  "#{self.to_s.downcase.pluralize}.account_id = #{$account.id}" }) do
    super(*args)
  end
end

Это также прекрасно работает, однако я хочу, чтобы это было СУХОЙ. Теперь у меня есть несколько разных моделей, которые я хочу использовать для этой функции. Каков наилучший способ сделать это?

Когда вы отвечаете, пожалуйста, включите код, который поможет нашему уму понять метапрограммирование Ruby-fu.

(я использую Rails v2.1)

Ответы [ 3 ]

8 голосов
/ 17 сентября 2008

Вы не сообщаете нам, какую версию рельсов вы используете [править - это на рельсах 2.1, поэтому, следуя совету, полностью работоспособен], но я бы порекомендовал вам использовать следующую форму вместо перегрузки, найдите себя:

account.contacts.find(...) 

это автоматически обернет поиск в область, в которую входит предложение пользователя (поскольку у вас есть account_id, я предполагаю, что у вас есть аккаунт где-то рядом)

Предлагаю вам проверить следующие ресурсы в областях

5 голосов
/ 17 сентября 2008

Джин совет здоров. Предполагая, что ваши модели выглядят так:

class Contact < ActiveRecord::Base
  belongs_to :account
end

class Account < ActiveRecord::Base
  has_many :contacts
end

Вы должны использовать ассоциацию contacts текущей учетной записи, чтобы обеспечить получение только Contact записей в этой учетной записи, например:

@account.contacts

Если вы хотите добавить дополнительные условия к вашему запросу контактов, вы можете указать их, используя find:

@account.contacts.find(:conditions => { :activated => true })

И если вы обнаружите, что постоянно запрашиваете активированных пользователей, вы можете преобразовать его в именованную область:

class Contact < ActiveRecord::Base
  belongs_to :account
  named_scope :activated, :conditions => { :activated => true }
end

Что бы вы потом использовали следующим образом:

@account.contacts.activated
0 голосов
/ 17 сентября 2008

, чтобы дать конкретный ответ на вашу проблему, я бы предложил перенести вышеупомянутый метод в модуль, который будет включен в рассматриваемые модели; так что у вас будет

class Contact
  include NarrowFind
  ...
end

PS. следите за экранированием sql account_id, вам, вероятно, следует использовать синтаксис :conditions=>[".... =?", $account_id].

...