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

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

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

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

Q&A

3回答

2986閲覧

【rails 】whereメソッドについて

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails

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

0グッド

1クリップ

投稿2016/03/17 06:21

編集2016/03/17 08:50

whereメソッドについて、利用の仕方がいまいち理解できないので、ご教授頂ければ幸いです。

いま、questionモデル,answerモデル, groupモデルがあり、以下の様な関係になっています。

answer.rb

lang

1belongs_to :question

question.rb

lang:question.rb

1has_many :answers 2belongs_to :group

group.rb

lang:group.rb

1has_many :questions

questionsテーブルにはgroup_idがあり、answersテーブルにはquestion_idがあります。

今、例えばgroup_idが1のanswersレコードを取得するとき、
@answers = Answer.includes(:question).where(questions:{group_id:1})
と記述できるとのことですが、ここでのwhereメソッドの使い方がよくわかりません。

どなたか教えて頂ければ幸いです。
また、参考になるサイトなどがあれば、シェアしていただきたいです。

よろしくお願い致します。

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

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

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

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

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

rifuch

2016/03/17 07:37

Answerクラスは、belongs_to :questionではないですか? 大事な前提なので、確認したいです。
退会済みユーザー

退会済みユーザー

2016/03/17 08:50

ご指摘ありがとうございます! 修正致しました。
guest

回答3

0

今、例えばgroup_idが1のanswersレコードを取得するとき、
@answers = Answer.includes(:question).where(questions:{group_id:1})
と記述できるとのことですが、ここでのwhereメソッドの使い方がよくわかりません。

whereメソッドの使い方がよくわからないとの事ですので

Answer.includes(:question).where(questions:{group_id:1})

の部分の解説をさせていただきます。


通常 Answer.where とすると Answer モデル内のカラムのみが where の検索対象になります。

今回は Answer モデルではなく Questionモデル のgroup_id カラムを検索対象にしたいので
includes(:question) を付けてあげます。

すると Answer.includes(:question).whereですね。 includes の引数である :question
Answer モデル の belongs_to :question:question です。


そして最後に where の引数です。 includes の引数は関連名で指定しましたが where の引数は多少やっかいで、自分(Answer)以外のモデルを検索する時はテーブル名で指定します。

今回は Questionモデル のgroup_id カラム が 1 である物を探したいので
questions テーブルのgroup_id カラム が 1
という指定の仕方をする必要があります。


よって where の引数は questions:{group_id:1} になり
Answer.includes(:question).where(questions:{group_id:1})
が完成します。


おしりに .to_sql をつけると実際に発行されるSQL文を得る事ができます。
SQL文がわかるのであれば .to_sql で確認しながら where の引数を指定するといいかもしれません。

Answer.includes(:question).where(questions:{group_id:1}).to_sql

テーブル名(questions)で指定

SQL

1SELECT "answers"."id" AS t0_r0, "answers"."question_id" AS t0_r1, "answers"."created_at" AS t0_r2, "answers"."updated_at" AS t0_r3, "questions"."id" AS t1_r0, "questions"."group_id" AS t1_r1, "questions"."created_at" AS t1_r2, "questions"."updated_at" AS t1_r3 2 FROM "answers" 3 LEFT OUTER JOIN "questions" ON "questions"."id" = "answers"."question_id" 4 WHERE "questions"."group_id" = 1

Answer.includes(:question).where(question:{group_id:1}).to_sql

関連名(question)で指定

SQL

1SELECT "answers"."id" AS t0_r0, "answers"."question_id" AS t0_r1, "answers"."created_at" AS t0_r2, "answers"."updated_at" AS t0_r3, "questions"."id" AS t1_r0, "questions"."group_id" AS t1_r1, "questions"."created_at" AS t1_r2, "questions"."updated_at" AS t1_r3 2 FROM "answers" 3 LEFT OUTER JOIN "questions" ON "questions"."id" = "answers"."question_id" 4 WHERE "question"."group_id" = 1

投稿2016/10/17 01:07

hana-da

総合スコア1728

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

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

0

group_idが1のanswersレコードを取得するなら
@answers = Grout.find(1).answers
でも可能だとおもいます。

参考ページとして次を紹介します。

質問文のものとモデル名は異なりますが、類似も構造での検索例を示します。
Client -> Order で 1対多となっている場合の検索例です。

[1] pry(main)> Order.includes(:client).where(orders:{client_id:1}) Order Load (24.5ms) SELECT "orders".* FROM "orders" WHERE "orders"."client_id" = 1 ORDER BY ordered_at DESC Client Load (0.4ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" IN (1) +----+-----------+----------+-------+-------------------------+-------------------------+-------------------------+ | id | client_id | status | price | ordered_at | created_at | updated_at | +----+-----------+----------+-------+-------------------------+-------------------------+-------------------------+ | 2 | 1 | active | 200 | 2000-01-01 04:58:33 UTC | 2016-03-12 09:58:33 UTC | 2016-03-12 09:58:33 UTC | | 1 | 1 | received | 100 | 2000-01-01 09:58:33 UTC | 2016-03-12 09:58:33 UTC | 2016-03-12 09:58:33 UTC | | 3 | 1 | payed | 400 | 2000-01-01 09:58:33 UTC | 2016-03-12 09:58:33 UTC | 2016-03-12 09:58:33 UTC | +----+-----------+----------+-------+-------------------------+-------------------------+-------------------------+ 3 rows in set [2] pry(main)> Client.find(1).orders Client Load (0.2ms) SELECT "clients".* FROM "clients" WHERE "clients"."id" = ? LIMIT 1 [["id", 1]] Order Load (0.3ms) SELECT "orders".* FROM "orders" WHERE "orders"."client_id" = ? ORDER BY ordered_at DESC [["client_id", 1]] +----+-----------+----------+-------+-------------------------+-------------------------+-------------------------+ | id | client_id | status | price | ordered_at | created_at | updated_at | +----+-----------+----------+-------+-------------------------+-------------------------+-------------------------+ | 2 | 1 | active | 200 | 2000-01-01 04:58:33 UTC | 2016-03-12 09:58:33 UTC | 2016-03-12 09:58:33 UTC | | 1 | 1 | received | 100 | 2000-01-01 09:58:33 UTC | 2016-03-12 09:58:33 UTC | 2016-03-12 09:58:33 UTC | | 3 | 1 | payed | 400 | 2000-01-01 09:58:33 UTC | 2016-03-12 09:58:33 UTC | 2016-03-12 09:58:33 UTC | +----+-----------+----------+-------+-------------------------+-------------------------+-------------------------+ 3 rows in set

検索結果は同じですが、発行される SQR 文は異なっています。

投稿2016/03/17 11:55

katoy

総合スコア22324

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

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

退会済みユーザー

退会済みユーザー

2016/03/17 12:24

別の記述方法も記載して頂き、ありがとうございます! ちなみに、whereメソッドの引数についてなのですが、 where(questions:{group_id:1}) の questionsは、何のことを言っているのか、教えて頂ければ幸いです。questionsテーブルの全てのレコードでしょうか?
guest

0

うまい事Arelを使ってあげると良いかと思います。
基本的に、リレーションで取得してくるテーブルの名前はincludeでもそのまま使えるので、
その方法で指定してあげるという使い方になるかと。

Ruby

1q_table = Question.arel_table 2@answers = Answer.includes(:question).where(q_table[:group_id].eq(1))

ただ、Arelを使ったコードがControllerに出てくると、なんだか気持ち悪いので、
コントローラでやるんなら、私だったらこういう風にするかなあ。

Ruby

1 @group = Group.includes(questions: :answers).where(params[:gourd_id]) 2 3# viewの方で 4<% @group.questions.each do |question| %> 5 <% question.answers.each do |answer| %> 6 <!-- 何か表示 --> 7 <% end %> 8<% end %>

投稿2016/03/17 10:40

rifuch

総合スコア1901

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問