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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

1回答

1510閲覧

rails includesとwhereを使用した検索について 1対多対1

IRIESS

総合スコア45

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2021/11/25 22:49

編集2021/11/25 22:51

現在rails apiを使用してアプリを作成しています。

userが所持するfree_time達に、hostがhost_requestを送れます。
しかし、host_request作成時に同userが同hostに同期間(start_timeとfinish_timeの差)をすでに作成していた場合は失敗するようvalidateを書いたのですがエラーが発生して実現できていません。

UserUserRequestRecruitmentTimeHost
name :strintuser_id :inthost_id :intname :string
recruitment_time_id :intstart_time :datetime
start_time :datetimefinish_time :datetime
finish_time :datetime
FreeTimeHostRequest
user_id :inthost_id :int
start_time :datetimefree_time_id :int
finish_time :datetimestart_time :datetime
finish_time :datetime

それぞれのリレーションは以下になっています。

ruby

1# user.rb 2 has_many :free_times 3 has_many :user_requests 4 has_many :host_requests, through: :free_times 5 has_many :recruitment_times, through: :user_requests 6 7#host.rb 8 has_many :recruitment_times 9 has_many :host_requests 10 has_many :user_requests, through: :recruitment_times 11 has_many :free_times, through: :host_requests 12 13#free_time.rb 14 belongs_to :user 15 has_many :host_requests 16 17#recruitment_time.rb 18 belongs_to :host 19 has_many :user_requests 20 21#user_request.rb 22 belongs_to :user 23 belongs_to :recruitment_time 24 has_one :host, through: :recruitment_time 25 26#host_request.rb 27 belongs_to :free_time 28 belongs_to :host 29 has_one :user, through: :free_time

以下はvalidateのメソッドです

ruby

1#host_request.rb 2validate :duplication_of_user_request 3 4def duplication_of_user_request 5 free_time = FreeTime.find(free_time_id) 6 user = free_time.user 7 if UserRequest.includes(:host).where('user_id = ? && host.id = ? && user_request.finish_time >= ? && ? >= user_request.start_time ', user.id, host_id, start_time, finish_time).exists? 8 errors.add(:start_time, "同じ時間帯でお相手から申請が来ています。") 9 end 10 end

user_requestに has_one :host, through: :recruitment_timeを記入しているため、
直感的にuser_requestとhostは1対1のような関係になり、上記の書き方で実現できるかと考えていたのですが、、、
書き方に問題はありますでしょうか?

ruby

1 2#host_requests_controller.rb 3 def create 4 host_request = HostRequest.new(host_request_params) 5 if host_request.save 6 render json: host_request, status: 201 7 else 8 render json: host_request.errors, status: 400 9 end 10 end 11 12 private 13 def host_request_params 14 params.permit(:free_time_id).merge(host_id: current_api_host.id, start_time:Time.zone.parse(params[:start_time]), finish_time: Time.zone.parse(params[:finish_time])) 15 end

ruby

1#エラー 2 ActiveRecord::StatementInvalid: 3 Mysql2::Error: Unknown column 'host.id' in 'where clause

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

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

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

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

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

guest

回答1

0

ベストアンサー

二つ問題が見当たりました。
まず、whereの中で、SQLを直書きしている以上、それはSQL文法にそっていなければなりません。モデルHostのテーブル名は、きっとhostsですよね? 実際のSQL文中では、このような場合は、単にテーブルをJOINしています。だから、where()文中に現れるべきはテーブル名であるhostsであって、hostではありません。同様に、user_requestも複数形でなければなりません。

このようなSQL直書き文をデバッグする時のtipとして、to_sql文をログなどに出力してみて、それがSQL文として正当かどうか、Rails consoleあるいは MySQLを直接使って、検討してみると良いでしょう。

もう一点、Rails APIマニュアルのincludesの項目によれば、

If you want to add string conditions to your included models, you'll have to explicitly reference them.

とされています。端的には、このような場合は、references を使う必要があります。引数はテーブル名です。この場合であれば、def duplication_of_user_request において、

ruby

1if UserRequest.includes(:host).where('user_id = ? && host.id #中略 2 ', user.id, host_id, start_time, finish_time). 3 .references(:hosts, :user_requests).exists?

などとすることは、最低限必要でしょう。

以上、元投稿のコードに誤りの部分が多いこともあり、これだけで動くかどうかはわかりません。たとえば、includes文に :user_requests も必要かもしれません(必要ないかも?)。
しかし、上記の二つのポイントを念頭に試行錯誤すると解決に近づくのでは、と思います。

投稿2021/11/25 23:55

MasaSakano

総合スコア188

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

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

IRIESS

2021/11/26 03:51 編集

回答ありがとうございました!SQL文法等々知識がなさすぎました。 最終的には UserRequest.includes(recruitment_time: :host).where('user_id = ? && hosts.id = ? && user_requests.finish_time >= ? && ? >= user_requests.start_time ', user.id, host_id, start_time, finish_time).references(:hosts, :recruitment_times).exists? で実現できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問