0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【ruby on rails】質問一覧を回答数順に表示させた際に「Column ‘[カラム名]’ in order clause is ambiguous」エラー発生

Last updated at Posted at 2021-12-09

各ユーザーがログイン、質問投稿、投稿に対する回答ができるアプリがある。

質問一覧画面の表示を回答数順に並び替えさせる。

※本筋とは関係ありませんがページネーション機能として
gemfile にkaminari を導入しております

1.モデル

ユーザーを表すmemberモデル、投稿した質問に関するpostモデル、
質問に対する回答を表すanswerモデルがそれぞれある。
各モデルの関係は以下

app/models/answer.rb
class Answer < ApplicationRecord
  belongs_to :member
  belongs_to :post
end
app/models/post.rb
class Post < ApplicationRecord
  has_many :answers, dependent: :destroy
  belongs_to :member
end
app/models/member.rb
class Member < ApplicationRecord
  has_many :answers, dependent: :destroy
  has_many :posts, dependent: :destroy
end

2. コントローラーファイル

postコントローラーについては以下

質問一覧を見れるpost.index画面では更新日時順やid順等、
色んな並べ替えのパターンを用意。ここに回答数順も表示させたい。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

  def index # 質問一覧を表示する画面 
    @posts = Post.all
    @range = params[:range] # 並べ替え選択時のページネーションを場合分け
    case @range
    when "投稿Noが新しい順に"
      @posts = Post.all.order(id: 'DESC').page(params[:page]).per(10)
    when "投稿Noが古い順に"
      @posts = Post.all.order(id: 'ASC').page(params[:page]).per(10)
    when "更新日時が新しい順に"
      @posts = Post.all.order(updated_at: 'DESC').page(params[:page]).per(10)
    when "更新日時が古い順に"
      @posts = Post.all.order(updated_at: 'ASC').page(params[:page]).per(10)
    when "回答数の多い順に"
      @posts = Post.joins(:answers).order('count(member_id) desc').group(:post_id).page(params[:page]).per(10)
    when "回答数の少ない順に"
      @posts = Post.joins(:answers).order('count(member_id) asc').group(:post_id).page(params[:page]).per(10)
    ...
    end
  end

  def show # 投稿内容を見れる画面
    @post = Post.find(params[:id])
  end
  .....

更新日時順等はpostモデルのカラムをorderで並び替えるだけなので楽。
回答数順の並べ変えは表示方法として
中間テーブル(answer)をjoinさせる、post_idでグルーピング、member_idの数で並び替える
方法を使用する。以下記事を参考とさせていただきました。

3.viewファイル

 以下については割愛
・posts/show.html.erb(質問投稿詳細画面)

postのindex画面を記載する

app/views/posts/index.html.erb
# 並べ替え方法をプルダウンで選択
<%= form_with url: posts_path, local: true, method: :get do |f| %>
 <%= f.select :range, options_for_select([['投稿Noが新しい順に'],['投稿Noが古い順に'],['更新日時が新しい順に'],['更新日時が古い順に'],["回答数の多い順に"],["回答数の少ない順に"]]) %>
 <%= f.submit "回答並べ替え", data: {"turbolinks"=>false} %>
<% end %>

<%= paginate @posts %>

# 質問一覧を表示させる
(~省略~)
<% @posts.each do |post| %>
 <%= post.updated_at.to_s(:datetime_jp) %>
 <%= post.answers.count %>
  (~省略~)
<% end %>

4.エラー発生

この時点で開発環境では回答数順に並べ替えさせて表示させることには成功した。
しかし、本番環境(インフラはAws/DBはmysqlを使用)
では上手く行かず以下エラーが発生してしまった。

 ActionView::Template::Error (Mysql2::Error: Column 'member_id' in order clause is ambiguous: SELECT  `posts`.* FROM `posts` INNER JOIN `answers` ON `answers`.`post_id` = `posts`.`id` GROUP BY `post_id` ORDER BY count(member_id) desc LIMIT 10 OFFSET 0):

member_idがどのテーブルのものか不明瞭であることが原因と思われる
ゆえにコントローラーファイルの記述を

「count(member_id)」→「count(answers.member_id)」

に変更する

するとエラーが発生せず回答数順に表示させることができた。

5. 余談

・参考記事そのままで成功しなかったのは、当方ではmemberモデルとpostモデルでも
1対多の関係があったためと考えます。

・この並べ替え方法では回答数0のものを表示させることができません。
→回答数0ものはpostモデルとmemberモデルがanswerモデルに紐づいていないため

回答数0の一覧を表示させるには以下記事を参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?