2012-04-24 7 views
0

У меня есть модель Категория, которая has_many Продукты и Продукт, в свою очередь has_many Категории. Когда пользователь ищет категорию, я хотел бы вернуть продукты соответствующих категорий без потери объекта Arel. Вот то, что я до сих пор:Как выбрать только связанные объекты в запросе Rails «where»?

Category.where("upper(title) like ?", search_term.upcase).map {|category| category.products}.flatten 

Это делает трюк возвращения продуктов, но, конечно, что у меня есть массив, а не Арел. Я могу дойти до добавления предложения :includes(:products), поэтому я действительно вернул продукты, но я все еще привязываю их к их категориям. Как настроить свой запрос так, чтобы все, что я вернусь, это Arel, который обращается только к продуктам?

ответ

3

Если это то, что вы хотите, то вам, вероятно, следует начинать с объекта «Продукт» при поиске. Например, вы могли бы сделать это следующим образом:

Product.joins(:categories).where("upper(categories.title) like ?", search_term.upcase) 

Причина я использую joins вместо includes является то, что присоединяется выполнит INNER JOIN вместо LEFT OUTER JOIN, которая является то, что вам нужно возвращать только те продукты, которые являются фактически связанных с найденными категориями.

Чтобы сделать его немного более элегантно можно обернуть все это в рамках вашей модели продукта, как это:

# In Product.rb 
scope :in_categories_like, Proc.new{ |search_term| 
    joins(:categories).where("upper(categories.title) like ?", search_term.upcase) 
} 

# In use 
@products = Product.in_categories_like(params[:search_term]) 
+1

[ «Использование метода класса является предпочтительным способом принимать аргументы для областей»] (http://guides.rubyonrails.org/active_record_querying.html#passing-in-arguments), но это, в основном, nit picking. –

+0

Спасибо, это хороший момент. – DanneManne

+0

Только для записи: 'def self.in_categories_like (search_term); join (: categories) .where ("upper (categories.title) like?", search_term.upcase); end'. –

Смежные вопросы