質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

3回答

5536閲覧

Ransackを使った多対多テーブルのANDでの絞込がうまく動作しない

mizui

総合スコア4

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2017/09/12 13:02

Ruby on Railsで商品を登録、一覧表示できるシステムを作っています。

Ransackを使って商品の絞込をしたいのですが、多対多の関係にある商品(Item)とタグ(Tag)について、タグでANDでの絞込をしたいのですが、正しく動作しません。

##テーブル構成

itemsテーブル

  • id
  • name

tagsテーブル

  • id
  • name

item_tagsテーブル(中間テーブル)

  • id
  • item_id
  • tag_id

##該当のソースコード

/app/view/items/index.html.slim

= search_form_for @q, url: items_path do |f| - Tag.all.each do |t| .form-check.form-check-inline.mb-0 label.form-check-label = f.check_box :tags_id_eq_all, {multiple: true, class: 'form-check-input'}, t.id, nil = t.name button.btn.btn-primary.btn-block.btn-lg i.zmdi.zmdi-search.zmdi-hc-lg.pr-1 | 絞り込む

/app/controllers/items_controllers.rb

class ItemsController < ApplicationController def index @q = Item.search(params[:q]) @items = @q.result(distinct: true).includes(:item_tags, :tags) end end

###試したこと

チェックボックスを:tags_id_eq_anyに変更してOR検索にした場合、正しい挙動になります。:tags_id_eq_allの場合、エラーなどは発生しないのですが、該当する商品が検索結果に表示されない状況です。

###補足情報

  • rails 5.1.2
  • ransack 1.8.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

これで解決したのか教えて欲しいです。

投稿2020/09/19 08:28

su_da221

総合スコア59

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こちらが分かりやすいですね
http://qiita.com/EastResident/items/54047e6e85dda0418dad

投稿2017/09/13 06:38

mtdsnsk

総合スコア789

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずはコンソール画面で実際に発行されているSQL文を確認してみるといいと思います。
あと、includesで参照されている情報をもとに絞り込みを行う時の注意事項があります。
Ransackを使った場合どのように記述するかわかりませんが、とりあえず

ruby

1@q.result(distinct: true).includes(:item_tags, :tags).references(:item_tags, :tags)

こんな感じだと意図した挙動になりませんか?

参考サイト

投稿2017/09/13 04:31

mtdsnsk

総合スコア789

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mizui

2017/09/13 04:53

ありがとうございます! SQLを確認してみましたが、下記が発行されているようです。 ``` SELECT DISTINCT `items`.* FROM `items` LEFT OUTER JOIN `item_tags` ON `item_tags`.`item_id` = `items`.`id` LEFT OUTER JOIN `tags` ON `tags`.`id` = `item_tags`.`tag_id` WHERE `items`.`publish` = 1 AND (`tags`.`id` = 1 AND `tags`.`id` = 2) LIMIT 20 OFFSET 0 ``` なお`.references(:item_tags, :tags)`を追加しても結果は同じ形でした・・・。
mtdsnsk

2017/09/13 05:03

`tags`.`id` = 1 AND `tags`.`id` = 2 は `tags`.`id` = 1 OR `tags`.`id` = 2 が意図した挙動だと思いますがどうでしょうか? tags.idが1または2のものが検索したいのですよね? ANDだと、tags.idが1かつ2のものとなるので、ヒットしないのでは?
mtdsnsk

2017/09/13 05:04

該当する商品が検索結果に表示されないのではなく、`該当がないので検索結果が空`なのでは
mtdsnsk

2017/09/13 05:07

SQLにおけるOR条件とAND条件がわかっていないのでは、と思いました。 SQL的には`A AND B` は `A と B` ではないですよ。
mizui

2017/09/13 05:40 編集

ありがとうございます。検索したいのはタグIDが1かつ2(1 AND 2)のものです。 item_tagsテーブルには下記のデータが入っています。OR(eq_any)の場合はid1とid2が表示される=正しく動いているのですが、AND(eq_all)の場合になぜかうまくいかないです。。 id: 1, item_id: 1, tag_id: 1 id: 2, item_id: 1, tag_id: 2
mtdsnsk

2017/09/13 06:20

やりたいことはわかりました その場合は ❶tag_id: 1でひとまず絞り込んでitem_idを取得 ❷取得したitem_idで絞り込む ❸更にtag_id: 2で絞り込む とすると実現できますね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問