2016-09-24 82 views
0

我試圖建立一個複選框過濾器,它會減少每個框被選中的結果數量。每個複選框將代表has_many:through關聯。Rails:使用複選框過濾ActiveRecord搜索結果

我有三種模式的應用程序: 書 主題 BookSubject

他們像這樣有關:

class Book < ActiveRecord::Base 
    has_many :book_subjects 
    has_many :subjects, through: :book_subjects 
end 

class Subject < ActiveRecord::Base 
    has_many :book_subjects 
    has_many :books, through: :book_subjects 
end 

class BookSubject < ActiveRecord::Base 
    belongs_to :book 
    belongs_to :subject 
end 

通過書籍控制器,用戶可以運行搜索行動,這使得顯示所有書籍的查看頁面。通過檢查邊欄中的每個框(每個框都標有主題名稱),用戶應該能夠縮小符合他們搜索的書籍的數量。這也是迄今爲止的搜索行動:

def search 
    if params[:name].nil? || params[:name].empty? 
    @all_books = Book.all 
    else 
    @all_books = Book.joins(:subjects).where(subjects: {name: params[:name].split(",")}).distinct 
    end 
    render 'search' 
end 

現在,如果用戶選擇「歷史」和「史詩」,他們得到與歷史的所有書籍爲主題,並與史詩爲主題的所有書籍。我希望他們只拿到既有歷史又有史詩的作品。我試過向查詢添加.group,但到目前爲止它不工作:

def search 
    if params[:name].nil? || params[:name].empty? 
    @all_books = Book.all 
    else 
    @all_books = Book.joins(:subjects) 
     .where(subjects: {name: params[:name].split(",")}) 
     .group("books.id") 
     .having("count(*) >= ?", 1) 
    end 
    end 
end 

我該如何修改我的查詢以使過濾成爲可能?謝謝!!!

回答

1

我認爲你的代碼幾乎沒問題,但爲什麼你有having("count(*) >= ?", 1)
該條件適用於所有必填列表中只有一個主題的圖書。
嘗試改變代碼以下

def search 
    @all_books = if params[:name].blank? 
    Book.all 
    else 
    names = params[:name].split(',') 
    Book.joins(:subjects) 
     .where(subjects: { name: names }) 
     .group(:id) 
     .having('count(*) = ?', names.size) 
    end 
end 
+0

謝謝你的名字=參數[:名字] .split(「」)線 - 這是少了什麼,我搶names.size(爲計數線)。但是,這仍然不是過濾 - 當我檢查'歷史'和'史詩'時,我仍然可以獲得一切歷史和一切史詩,當我只想要歷史史詩時。有什麼想法嗎? –

+0

很奇怪。你能提供它生成的確切的SQL嗎?你可以看到它的服務器日誌。 – Aleksey

+0

當然可以!選中一個框:書籍加載(0.9毫秒)選擇「書籍」*從「書籍」內部加入「book_subjects」ON「book_subjects」。「book_id」=「books」。「id」INNER JOIN「subject」ON「 「。」id「=」book_subjects「。」subject_id「WHERE」subjects「。」name「='史詩/傳奇'GROUP BY books.id HAVING count(*)> = 1 –