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

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

ただいまの
回答率

91.02%

  • Ruby

    6356questions

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

  • Ruby on Rails

    6185questions

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

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

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 254

mizui

score 0

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
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

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

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


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

参考サイト

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/13 13: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)`を追加しても結果は同じ形でした・・・。

    キャンセル

  • 2017/09/13 14:03

    `tags`.`id` = 1 AND `tags`.`id` = 2

    `tags`.`id` = 1 OR `tags`.`id` = 2
    が意図した挙動だと思いますがどうでしょうか?
    tags.idが1または2のものが検索したいのですよね?

    ANDだと、tags.idが1かつ2のものとなるので、ヒットしないのでは?

    キャンセル

  • 2017/09/13 14:04

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

    キャンセル

  • 2017/09/13 14:07

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

    キャンセル

  • 2017/09/13 14: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

    キャンセル

  • 2017/09/13 15:20

    やりたいことはわかりました

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

    キャンセル

  • 2017/09/13 15:36

    こちらが参考になりそうです。。。
    サブクエリで何とかするしかなさそうですねー
    http://qiita.com/ishidamakot/items/4e70010c0e11399c3404

    キャンセル

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 91.02%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    6356questions

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

  • Ruby on Rails

    6185questions

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