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

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

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

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

Ruby

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

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

1回答

1000閲覧

Herokuにデプロイ後、本番環境でのみ UndefinedColumn: ERROR が発生する。

punchan36

総合スコア105

Ruby on Rails 5

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

Ruby

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

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

0クリップ

投稿2021/10/14 07:43

前提・実現したいこと

RailsアプリをHerokuにデプロイし、heroku run rails db:migrate まで済ませました。
ほとんどの機能はローカル環境と変わらずステージング環境でも動くのですが、ユーザー検索機能の一部が動きません。

ユーザー検索機能ではユーザー名や性別などに加え、「ユーザーが話せる言語」でも絞り込みが出来るのですが、この言語を選択して検索をかけた際に以下のエラーが出ます。
言語を選択せず、ユーザー名や性別のみで絞り込みをかけた場合は上手く動きます。

2021-10-14T06:29:13.492195+00:00 heroku[router]: at=info method=GET path="/user_images/1.jpg" host=hoge.herokuapp.com request_id=813c0af3-daab-4eed-b6c3-1d4dcedddff4 fwd="223.219.73.25" dyno=web.1 connect=0ms service=2ms status=304 bytes=112 protocol=https 2021-10-14T06:29:51.885420+00:00 heroku[router]: at=info method=GET path="/users?utf8=%E2%9C%93&name=&language_ids%5B%5D=1&introduction=&commit=search" host=hoge.herokuapp.com request_id=c34415d4-b2c4-43f3-bf38-ae0b5c7681ad fwd="223.219.73.25" dyno=web.1 connect=0ms service=9ms status=500 bytes=1891 protocol=https 2021-10-14T06:29:51.875852+00:00 app[web.1]: I, [2021-10-14T06:29:51.875781 #4] INFO -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] Started GET "/users?utf8=%E2%9C%93&name=&language_ids%5B%5D=1&introduction=&commit=search" for 223.219.73.25 at 2021-10-14 06:29:51 +0000 2021-10-14T06:29:51.876497+00:00 app[web.1]: I, [2021-10-14T06:29:51.876443 #4] INFO -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] Processing by UsersController#index as HTML 2021-10-14T06:29:51.876538+00:00 app[web.1]: I, [2021-10-14T06:29:51.876515 #4] INFO -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] Parameters: {"utf8"=>"✓", "name"=>"", "language_ids"=>["1"], "introduction"=>"", "commit"=>"search"} 2021-10-14T06:29:51.879517+00:00 app[web.1]: D, [2021-10-14T06:29:51.879455 #4] DEBUG -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] User Load (1.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 4], ["LIMIT", 1]] 2021-10-14T06:29:51.882166+00:00 app[web.1]: D, [2021-10-14T06:29:51.882127 #4] DEBUG -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] User Load (1.4ms) SELECT users.*, COUNT(*) AS languages_count FROM "users" INNER JOIN "user_languages" ON "user_languages"."user_id" = "users"."id" WHERE "user_languages"."language_id" = $1 GROUP BY user_languages.user_id HAVING (languages_count = 1) ORDER BY "users"."created_at" DESC LIMIT $2 OFFSET $3 [["language_id", 1], ["LIMIT", 20], ["OFFSET", 0]] 2021-10-14T06:29:51.882279+00:00 app[web.1]: I, [2021-10-14T06:29:51.882254 #4] INFO -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] Completed 500 Internal Server Error in 6ms (ActiveRecord: 2.5ms) 2021-10-14T06:29:51.882673+00:00 app[web.1]: F, [2021-10-14T06:29:51.882648 #4] FATAL -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] 2021-10-14T06:29:51.882696+00:00 app[web.1]: F, [2021-10-14T06:29:51.882676 #4] FATAL -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column "languages_count" does not exist 2021-10-14T06:29:51.882696+00:00 app[web.1]: LINE 1: ..._id" = $1 GROUP BY user_languages.user_id HAVING (languages_... 2021-10-14T06:29:51.882697+00:00 app[web.1]: ^ 2021-10-14T06:29:51.882698+00:00 app[web.1]: : SELECT users.*, COUNT(*) AS languages_count FROM "users" INNER JOIN "user_languages" ON "user_languages"."user_id" = "users"."id" WHERE "user_languages"."language_id" = $1 GROUP BY user_languages.user_id HAVING (languages_count = 1) ORDER BY "users"."created_at" DESC LIMIT $2 OFFSET $3): 2021-10-14T06:29:51.882714+00:00 app[web.1]: F, [2021-10-14T06:29:51.882695 #4] FATAL -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] 2021-10-14T06:29:51.882738+00:00 app[web.1]: F, [2021-10-14T06:29:51.882718 #4] FATAL -- : [c34415d4-b2c4-43f3-bf38-ae0b5c7681ad] app/controllers/users_controller.rb:42:in `index'

column "languages_count" does not exist と言われていますが、実際にlanguages_countと言うカラムを参照している訳ではなく、以下の様に joinsを使いparams[:language_ids]と「ユーザーが登録している言語」を比較する方法を取っています。

users_controller.rb

def index @users = User.all.order(created_at: :desc).page(params[:page]).per(20) if params[:language_ids].present? @users = @users.select("users.*, COUNT(*) AS languages_count") .joins(:user_languages) .where(user_languages: { language_id: params[:language_ids] }) .group("user_languages.user_id") .having("languages_count = #{params[:language_ids]&.length}") end if params[:name].present? || params[:gender].present? || params[:introduction].present? @users = @users.where(['name LIKE ? AND gender LIKE ? AND introduction LIKE ?', "%#{params[:name]}%", "#{params[:gender]}%", "%#{params[:introduction]}%"]) end if @users == [] # 該当のユーザーが存在しなかった場合。 flash[:notice] = "No such user" @users = User.all.order(created_at: :desc).page(params[:page]).per(20) end end

users/index.html.erb

<%= form_with url: users_path, method: :get, local: true do |f| %> <p>User name</p> <%= f.search_field :name, :value => params[:name] %> <p>Gender</p> <%= f.radio_button :gender, "Male", :checked => params[:gender] == ("Male") %>Male<br> <%= f.radio_button :gender, "Female", :checked => params[:gender] == ("Female") %>Female<br> <%= f.radio_button :gender, "Other", :checked => params[:gender] == ("Other") %>Other <p>Languages</p> <label class="each-language"><%= f.check_box :language_ids, {multiple: true, :checked => params[:language_ids]&.include?("1")}, "1", false %>Japanese</label> <label class="each-language"><%= f.check_box :language_ids, {multiple: true, :checked => params[:language_ids]&.include?("2")}, "2", false %>English</label> <label class="each-language"><%= f.check_box :language_ids, {multiple: true, :checked => params[:language_ids]&.include?("3")}, "3", false %>Chinese</label> <p>Keyword</p> <%= f.search_field :introduction, :value => params[:introduction] %> <%= f.submit :search, :class => "btn-square-little-rich" %> <% end %>

「ユーザー」と「言語」が多対多の関係になっており、モデルとテーブル情報は以下になります。

モデル・テーブル情報

user.rb

has_many :user_languages, dependent: :destroy has_many :languages, through: :user_languages

language.rb

has_many :user_language has_many :users, through: :user_language

user_language.rb

belongs_to :user belongs_to :language

schema.rb

create_table "languages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "description" t.boolean "done" t.bigint "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["user_id"], name: "index_languages_on_user_id" end create_table "user_languages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.bigint "user_id" t.bigint "language_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["language_id", "user_id"], name: "index_user_languages_on_language_id_and_user_id", unique: true t.index ["language_id"], name: "index_user_languages_on_language_id" t.index ["user_id"], name: "index_user_languages_on_user_id" end create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t| t.string "name" t.string "email" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "image_name" t.string "password_digest" t.string "cover_image_name" t.string "gender" t.string "country" t.string "language" t.text "introduction" end add_foreign_key "languages", "users" add_foreign_key "user_languages", "languages" add_foreign_key "user_languages", "users"

試したこと

  1. heroku run rails db:migrate を済ませた際に rails aborted! は表示されませんでした。
  2. bundle exec heroku run rake db:migrate:status でもすべてのマイグレーションファイルのステータスが up になっておりますので、こちらはローカル環境と状況は同じかと思います。
  3. ローカル環境では問題なく動く部分ですので、config/environmentsフォルダ内で何かの設定が邪魔しているのかもと当たりをつけましたが、怪しい部分が分かりませんでした。
  4. ステージング環境のデータベースにも、ローカル環境と同様に以下の様に Language のテーブル情報は手動で作成致しました。
Language.create!(id: 1, description: 'Japanese') Language.create!(id: 2, description: 'English') Language.create!(id: 3, description: 'Chinese')

ですのでlanguage_idsが空であると言ったエラーはなく、ユーザーがプロフィール編集(users/edit.html.erb)で言語を追加するアクション等は問題なく動きます。

尚、ユーザー検索機能を実装するにあたり過去に質問させて頂いた事があります。
どなたかご助言を頂けますと有難いです。

補足情報(FW/ツールのバージョンなど)

ruby 2.6.4p104
RubyGems 3.0.3
Rails 5.2.3

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

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

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

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

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

guest

回答1

0

ベストアンサー

MySQL では動作したはずですが、PostgreSQLでは動作しないのですね。

たぶん SQL の実行順序の問題で、SELECT より前に HAVING が評価されてしまうので
SELECT句の languages_count が実在するカラムと解釈されてしまうんだと思います。

以下のように having に COUNT(*) を指定してみてください。
select はいらなくなります。

ruby

1@users 2 .joins(:user_languages) 3 .where(user_languages: { language_id: params[:language_ids] }) 4 .group("user_languages.user_id") 5 .having("COUNT(*) = #{params[:language_ids].length}")

MySQL で動くのはなぜなんだろう・・・

投稿2021/10/14 10:08

neko_daisuki

総合スコア2090

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

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

punchan36

2021/10/14 11:20

有難うございます! データベース毎の読み込み方の違いと言うのは盲点でした…。 頂いたコードですと、ローカル環境(MySQL)では動いたもののステージング環境(postgreSQL)では再度エラーが出てきました。 ActiveRecord::StatementInvalid (PG::GroupingError: ERROR: column "users.id" must appear in the GROUP BY clause or be used in an aggregate function 「usersテーブルのidは、GROUP BY節に現れるか集計関数で使われなければならない(?)」との事で、ここも postgreSQL 用に書かないといけないようです。。 こちらの .group 周りの事でしょうか…? @users = @users .joins(:user_languages) .where(user_languages: { language_id: params[:language_ids] }) .group("user_languages.user_id") .having("COUNT(*) = #{params[:language_ids].length}") 関連してそうなQiita記事を参考にしてみましたが、いまいち何が起こっているのかイメージし辛いです。。 https://qiita.com/YusukeHigaki/items/6c1330867ba788a210c8
neko_daisuki

2021/10/14 12:24

group に users.id をくわえてみてください。 .group("user_languages.user_id, users.id") PostgreSQL は標準の SQL に近いみたいで Rails が発行する SQL に含まれる SELECT "users".* があると GROUP BY に主キーを?含めないと駄目みたいです。
punchan36

2021/10/14 15:04

有難うございます! ", users.id" を加える事で、MySQL、PostgreSQLの両方でコードが機能する様になりました。 慣れるまで難しそうですが、今後はデータベースの違いによる原因も頭に入れておこうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問