2016-10-14 4 views
0

Я следил за учебником и создал метод тегов на моем сайте рецептов. У меня есть следующие модели:Rails 4: Фильтр с тегами

class Recipe < ActiveRecord::Base 
    has_many :taggings 
    has_many :tags, through: :taggings 
end 

class Tag < ActiveRecord::Base 
    has_many :taggings 
    has_many :recipes, through: :taggings 
end 

class Tagging < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :recipe 
end 

В моем индексе рецепта я хотел бы создать фильтр, который выбирает для рецептов, которые имеют ВСЕХ тегов, выбранных пользователь.

У меня есть метод вытягивать все рецепты с данным тегом:

def self.tagged_with(name) 
    Tag.find_by_name!(name).recipes 
end 

... и я пытаюсь использовать inject объединить несколько тегов в одном запросе:

def self.new_filter(tags) # tags is an array 
    tags.inject(Recipe.all) { |res, arg| res.tagged_with(arg) } 
end 

Но это не возвращает рецепты со всеми тегами, оно возвращает рецепты с последним тегом в массиве тегов. Как исправить это, чтобы возвращать только рецепты со всеми тегами?

+0

Это довольно похожий вопрос на http://stackoverflow.com/questions/17920505/match-all-in-active-record-relations-in-a-query, у которого есть ответ, который может по крайней мере дать вам указание в в правильном направлении. – Jim

ответ

0

В этой строке tags.inject(Recipe.all) { |res, arg| res.tagged_with(arg) } проблема заключается в том, что вы возвращаете Recipies после того, как она извлекает его с помощью метода tagged_with. Поэтому для каждого элемента массива tagsinject будет выполнять операцию и возвращать результат, но не будет передавать ее для следующей итерации inject операции на tags. В конце вы получите то, что он вернет после выполнения запроса для последнего тега.

вы можете сделать что-то вроде этого:

def self.new_filter(tags) # tags is an array 
    res = Recipe.all; 
    tags.inject({}) { |all_res, arg| all_res[arg] = res.tagged_with(arg); all_res } 
end 

После этого вы получите хэш с ключом в качестве имени тега и рецепты, как ценности, как: my_recipes = {:chinese => *all data returned for chinese*}

ИЛИ вы можете сделать что-то вроде

def self.new_filter(tags) # tags is an array 
Recipe.joins(:tags).where('tags.name IN (?)', tags) 
end 

PS: Я не тестировал какой-либо код, при необходимости необходимо внести необходимые корректировки

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