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

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

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

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

Q&A

1回答

4159閲覧

【rails】検索gem ransackの使い方について-selectによってcountが多い順に並べ替えたい

YousukeTanaka

総合スコア79

Ruby on Rails 5

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

0グッド

0クリップ

投稿2018/11/25 09:45

編集2018/11/25 11:05

現在、ransackというgemを使って、検索機能を作成しています。

やりたいこと

サイトは、Q&Aサイトで、Questionに複数のAnswerがつき、そのanswerの数が多い順に検索結果を表示したいと考えています。

その中で、selectボックスを使い、以下のような表示をさせています。
イメージ説明

現在のコード

ただし、以下のように設定していますが、うまく機能しません。どこが間違っているのかのご指摘と、修正点を教えていただけないでしょうか?

特に、述語(predicate) の使い方がわかりません。この場合どの述語を使えば良いのでしょうか?
特に、_gtの部分が適切かどうか、ご助言をお願いします。

他の資料を見ると、「関連先のモデル名(複数)_関連先のカラム名_述語」という書き方をしなければならないとあり、それに従っていますが、これでいいのかもわかりません。

question_controller.rb

def search # 検索オブジェクト @search = Question.ransack(params[:q]) # 検索結果 @result = @search.result(distinct: true).order(created_at: :desc) @answer_count = Question.joins(:answers).group("question_id").order('count(question_id) desc') end

_search_form.html.erb

<%= search_form_for(@search, url: search_questions_path, method: :get) do |f| %> <div class="field"> <div class="control"> <%= fa_icon "angle-right", class: "searchicon" %> <%= f.label :answers_question_id_in, "回答数", class: "question-search-category" %><br> <div class="select is-fullwidth"> <%= f.select :answers_question_id_gt, [['回答数', @answer_count]], include_blank: "全てを選択" %> </div> </div> </div> <% end %>

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

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

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

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

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

guest

回答1

0

■ 動かない理由

一覧抽出対象で count とかしていませんがどうやって並べるつもりでしょうか
理屈的には少なくとも一覧でも count すべきではないでしょうか

@result = @search.result(distinct: true).select('count(answers.id) AS answers_count').joins(:answers).group("question_id").order(created_at: :desc)

ただしこれで動くのかとか Ransack が 実在していないカラムに対してソートができるかは怪しいです

■ 改善案

ソートのタイミングで集計を行うのはパフォーマンス的には遅いです
実在するカラムに件数を保存してしまえば Ransack も動くでしょう

ruby

1# questions.answers_count カラムを追加する 2class Question < ApplicationRecord 3 has_many :answers 4end 5# counter_cache オプションで保存時に questions.answers_count を更新してくれる 6class Answer < ApplicationRecord 7 belongs_to :question, counter_cache: true 8end

ruby

1f.select :answers_count_gt

■ 運用レベルの注意点

回答がある度に Questions.answers_count を更新するので、回答処理は僅かに遅くなります
また、複数回答が同時に登録された時に deadlock という現象が発生することがあります

それを解消する場合は counter_cache ではなく、この gem が使えますが
保存件数と実際の件数の不一致の可能性も出てくるので夜間再計算など検討も必要です

gem counter_culture

投稿2018/11/26 00:53

Ighrs

総合スコア656

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問