質問編集履歴

6

その後の進展を「追記」に記述しました。

2020/12/30 11:41

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -212,6 +212,8 @@
212
212
 
213
213
  どなたかご助言を頂けませんでしょうか。
214
214
 
215
+
216
+
215
217
  ### 補足情報(FW/ツールのバージョンなど)
216
218
 
217
219
  ruby 2.6.4p104
@@ -219,3 +221,17 @@
219
221
  RubyGems 3.0.3
220
222
 
221
223
  Rails 5.2.3
224
+
225
+
226
+
227
+ ### 追記
228
+
229
+ その後、以下の2点を無事実装する事が出来ました。
230
+
231
+ 1. メッセージが送信された時間順でトークルーム一覧を表示する。
232
+
233
+ 2. `message`の中身が存在しない`Entry`は表示しない。
234
+
235
+
236
+
237
+ [こちらの質問](https://teratail.com/questions/313145)をご参考頂ければと思います。

5

一つの質問内に収めるには内容が進展し過ぎたため、質問当初のコードに書き換えました。

2020/12/30 11:41

投稿

punchan36
punchan36

スコア105

test CHANGED
@@ -1 +1 @@
1
- メッセ送信された時間順でトークルーム一覧を表示したい
1
+ ambiguous column nameのエラーが表示される。
test CHANGED
@@ -1,38 +1,28 @@
1
1
  ### 前提・実現したいこと
2
2
 
3
-
4
-
5
3
  メッセージの送受信機能を実装しました。
6
4
 
7
- どのユーザーとのトークルームが存在するかを表示する為に、`User`と`Room`の中間テーブルである`Entry`一覧表示するビューがあります(LINE等のように)
5
+ 現段階では`User`と`Room`の中間テーブルである`Entry`に`id`が作成された時間順でメッセージ一覧表示されています。
8
-
9
-
10
-
6
+
11
- メッセージが送信された時間順で一覧を表示したいですが、現状、メッセージの数の分だけ`Entry`が何度も表示されてしまいます
7
+ これを、メッセージが送信された時間順で一覧を表示したいです。
12
-
13
-
14
8
 
15
9
  ### リレーション関連
16
10
 
17
-
18
-
19
11
  **user.rb**
20
12
 
21
13
  ```ruby
22
14
 
23
15
  class User < ApplicationRecord
24
16
 
25
- has_many :messages, dependent: :destroy
17
+ has_many :messages, dependent: :destroy
26
-
18
+
27
- has_many :entries, dependent: :destroy
19
+ has_many :entries, dependent: :destroy
28
-
20
+
29
- has_many :rooms, through: :entries
21
+ has_many :rooms, through: :entries
30
-
22
+
31
- end
23
+ end
32
-
24
+
33
- ```
25
+ ```
34
-
35
-
36
26
 
37
27
  **room.rb**
38
28
 
@@ -40,17 +30,15 @@
40
30
 
41
31
  class Room < ApplicationRecord
42
32
 
43
- has_many :messages, dependent: :destroy
33
+ has_many :messages, dependent: :destroy
44
-
34
+
45
- has_many :entries, dependent: :destroy
35
+ has_many :entries, dependent: :destroy
46
-
36
+
47
- has_many :users, through: :entries
37
+ has_many :users, through: :entries
48
-
38
+
49
- end
39
+ end
50
-
40
+
51
- ```
41
+ ```
52
-
53
-
54
42
 
55
43
  **entry.rb**
56
44
 
@@ -58,17 +46,13 @@
58
46
 
59
47
  class Entry < ApplicationRecord
60
48
 
61
- belongs_to :user
49
+ belongs_to :user
62
-
50
+
63
- belongs_to :room
51
+ belongs_to :room
64
-
65
- has_many :messages, through: :room
52
+
66
-
67
- end
53
+ end
68
-
54
+
69
- ```
55
+ ```
70
-
71
-
72
56
 
73
57
  **message.rb**
74
58
 
@@ -76,92 +60,160 @@
76
60
 
77
61
  class Message < ApplicationRecord
78
62
 
79
- belongs_to :user
63
+ belongs_to :user
80
-
64
+
81
- belongs_to :room
65
+ belongs_to :room
82
-
83
- has_one :entry, through: :room
66
+
84
-
85
- end
67
+ end
86
-
68
+
87
- ```
69
+ ```
88
-
89
- ![ER図](f735b1410ec66f2987e6eed73ad03d86.jpeg)
90
-
91
-
92
70
 
93
71
  ### rooms_controller.rb
94
72
 
95
-
73
+ このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
96
74
 
97
75
  ```ruby
98
76
 
99
77
  class RoomsController < ApplicationController
100
78
 
101
- before_action :set_another_entries, only: [:index, :show]
79
+ before_action :set_another_entries, only: [:index, :show]
102
-
103
-
104
-
80
+
105
- private
81
+ private
106
-
82
+
107
- def set_another_entries
83
+ def set_another_entries
108
-
109
-   # ログイン中のユーザーの持つEntryを配列にする。
84
+
110
-
111
- my_room_ids = @current_user.entries.pluck(:room_id)
85
+ my_room_ids = @current_user.entries.pluck(:room_id) # ログイン中のユーザーの持つEntryを配列にする。
112
-
86
+
113
- # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
87
+ # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
114
-
88
+
115
- @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('entries.user_id != ?', @current_user.id)
89
+ @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id).order(created_at: :desc)
116
-
117
- # メッセージが作成された順にエントリーを表示する。
90
+
118
-
119
- @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
120
-
121
- end
91
+ end
122
-
92
+
123
- end
93
+ end
124
-
94
+
125
- ```
95
+ ```
126
-
127
- このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
128
-
129
-
130
96
 
131
97
  ### 試したこと
132
98
 
133
-
134
-
135
- 「メッセージが作成れた順に数だけ`Entry`を全て表示する」と言う内容になっしまっていると思いますので、「各エントリ内で、最新のメッセージが作成された順に`Entry`を一つずつ表示する」と言内容にべく、以下の定義付けも考えてみました
99
+ まず[過去の質問](https://teratail.com/questions/272305)を参考にしました。こちらの質問者まは場合で言う`Room`を繰り返し表示されているので、`Message`テブルを結合(`join`)する事で解決されたよす。
100
+
136
-
101
+ ただ私の場合は`Entry`を繰り返し表示させており、`message`テーブルとのリレーションが出来ていません。
102
+
137
-
103
+ ![ER図](c9e65e83db330e8df382f6e085003ba6.jpeg)
104
+
105
+ ですのでそれを明示しようと考えました。
106
+
107
+ **entry.rb**
108
+
109
+ ```ruby
110
+
111
+ class Entry < ApplicationRecord
112
+
113
+ belongs_to :user
114
+
115
+ belongs_to :room
116
+
117
+ has_many :messages, through: :room #この行を追加。
118
+
119
+ end
120
+
121
+ ```
122
+
123
+ **message.rb**
124
+
125
+ ```ruby
126
+
127
+ class Message < ApplicationRecord
128
+
129
+ belongs_to :user
130
+
131
+ belongs_to :room
132
+
133
+ has_one :entry, through: :room #この行を追加。
134
+
135
+ end
136
+
137
+ ```
138
+
139
+ その上で`Message`テーブルの結合(`join`)を試みました。
138
140
 
139
141
  **rooms_controller.rb**
140
142
 
141
143
  ```ruby
142
144
 
143
- # 各エントリー内で、最新のメッセージを取得する。
144
-
145
- @last_message = @another_entries.each do |lm|
146
-
147
- Message.find_by(id: lm.room.message_ids.last)
148
-
149
- end
150
-
151
- ```
152
-
153
-
154
-
155
- しかしこれを`join`する箇所にどう組み込んでいけば良いか分かりません…。
145
+ class RoomsController < ApplicationController
146
+
147
+ before_action :set_another_entries, only: [:index, :show]
148
+
149
+ private
150
+
151
+ def set_another_entries
152
+
153
+ my_room_ids = @current_user.entries.pluck(:room_id)
154
+
155
+ @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id)
156
+
157
+ @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
158
+
159
+ end
160
+
161
+ ```
162
+
163
+ しかし以下のエラーが発生しました。
164
+
165
+ ```
166
+
167
+ ActiveRecord::StatementInvalid in Rooms#index
168
+
169
+ Showing C:/hoge/app/views/rooms/index.html.erb where line #12 raised:
170
+
171
+ SQLite3::SQLException: ambiguous column name: user_id: SELECT "entries".* FROM "entries" INNER JOIN "rooms" ON "rooms"."id" = "entries"."room_id" INNER JOIN "messages" ON "messages"."room_id" = "rooms"."id" WHERE "entries"."room_id" IN (?, ?, ?, ?) AND (user_id != 20) ORDER BY messages.created_at DESC
172
+
173
+ Extracted source (around line #12):
174
+
175
+ 10 <div class="message-items">
176
+
177
+ 11
178
+
179
+ 12 <% @another_entries.each do |e| %>
180
+
181
+ 13 <div class="message-item">
182
+
183
+ 14
184
+
185
+ 15 <div class="message-left">
186
+
187
+ ```
188
+
189
+ 恐らくリレーションを与えた事で`Entry`と`Message`の両テーブルに`user_id`が存在する事になり、どちらのテーブルの物かを判別する事が出来ない、と言った内容なのかと思います。
190
+
191
+ `scope`を使ってそれを明示する(?)と言った[記事](https://qiita.com/j-sunaga/items/99e576cca995b84a7839)を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
192
+
193
+ **room.rb**
194
+
195
+ ```ruby
196
+
197
+ class Room < ApplicationRecord
198
+
199
+ has_many :messages, dependent: :destroy
200
+
201
+ has_many :entries, dependent: :destroy
202
+
203
+ has_many :users, through: :entries
204
+
205
+ scope :select_entry, -> (entry) { where('user_id = ?', entry) } #この行を追加。
206
+
207
+ end
208
+
209
+ ```
210
+
211
+ 実はこの後で「`message`の中身が存在する`Entry`のみを表示する」と言った記述もしていきたいので、出来ましたら`Entry`と`Message`の両テーブルはリンクさせた上で実装出来れば一番有難いです。
156
212
 
157
213
  どなたかご助言を頂けませんでしょうか。
158
214
 
159
-
160
-
161
215
  ### 補足情報(FW/ツールのバージョンなど)
162
216
 
163
-
164
-
165
217
  ruby 2.6.4p104
166
218
 
167
219
  RubyGems 3.0.3

4

Rooms_controller内の@another_entriesに関する記述に誤りがあったため、編集。

2020/12/27 08:00

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -112,13 +112,13 @@
112
112
 
113
113
  # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
114
114
 
115
- @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id).order(created_at: :desc)
115
+ @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('entries.user_id != ?', @current_user.id)
116
-
117
- end
118
116
 
119
117
  # メッセージが作成された順にエントリーを表示する。
120
118
 
121
119
  @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
120
+
121
+ end
122
122
 
123
123
  end
124
124
 

3

ご回答があってからコードが大幅に変わったため、質問文の内容を現状のコードに一新しました。

2020/12/25 01:38

投稿

punchan36
punchan36

スコア105

test CHANGED
@@ -1 +1 @@
1
- ルをjoinした際に「ambiguous column name」のエラーが出る。
1
+ メッセジが送信された時間順でトークーム一覧表示した
test CHANGED
@@ -4,9 +4,11 @@
4
4
 
5
5
  メッセージの送受信機能を実装しました。
6
6
 
7
- 現段階では`User`と`Room`の中間テーブルである`Entry`に`id`が作成された時間順でメッセージ一覧表示されています。
7
+ どのユーザーとのトークルームが存在するかを表示する為に、`User`と`Room`の中間テーブルである`Entry`一覧表示するビューがあります(LINE等のように)
8
8
 
9
+
10
+
9
- これを、メッセージが送信された時間順で一覧を表示したいです。
11
+ メッセージが送信された時間順で一覧を表示したいですが、現状、メッセージの数の分だけ`Entry`が何度も表示されてしまいます
10
12
 
11
13
 
12
14
 
@@ -58,7 +60,9 @@
58
60
 
59
61
  belongs_to :user
60
62
 
61
- belongs_to :room
63
+ belongs_to :room
64
+
65
+ has_many :messages, through: :room
62
66
 
63
67
  end
64
68
 
@@ -76,17 +80,19 @@
76
80
 
77
81
  belongs_to :room
78
82
 
83
+ has_one :entry, through: :room
84
+
79
85
  end
80
86
 
81
87
  ```
88
+
89
+ ![ER図](f735b1410ec66f2987e6eed73ad03d86.jpeg)
82
90
 
83
91
 
84
92
 
85
93
  ### rooms_controller.rb
86
94
 
87
95
 
88
-
89
- このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
90
96
 
91
97
  ```ruby
92
98
 
@@ -100,7 +106,9 @@
100
106
 
101
107
  def set_another_entries
102
108
 
109
+   # ログイン中のユーザーの持つEntryを配列にする。
110
+
103
- my_room_ids = @current_user.entries.pluck(:room_id) # ログイン中のユーザーの持つEntryを配列にする。
111
+ my_room_ids = @current_user.entries.pluck(:room_id)
104
112
 
105
113
  # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
106
114
 
@@ -108,9 +116,15 @@
108
116
 
109
117
  end
110
118
 
119
+ # メッセージが作成された順にエントリーを表示する。
120
+
121
+ @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
122
+
111
123
  end
112
124
 
113
125
  ```
126
+
127
+ このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
114
128
 
115
129
 
116
130
 
@@ -118,31 +132,19 @@
118
132
 
119
133
 
120
134
 
121
- まず[過去の質問](https://teratail.com/questions/272305)を参考しました。こちらの質問者さまは場合で言う`Room`を繰り返し表示されているので、`Message`テブルを結合(`join`)する事で解決されたよす。
135
+ 「メッセージが作成された順に、数だけ`Entry`を全て表示する」と言う内容になっしまっていると思いますので、「各エントリ内で、最新のメッセージが作成された順に`Entry`を一つずつ表示する」と言内容にべく、以下の定義付けも考えてみました
122
136
 
123
137
 
124
138
 
125
- ただ私の場合は`Entry`を繰り返し表示させており、`message`テーブルとのリレーションが出来ていません。
126
-
127
- ![ER図](c9e65e83db330e8df382f6e085003ba6.jpeg)
128
-
129
- ですのでそれを明示しようと考えました。
130
-
131
-
132
-
133
- **entry.rb**
139
+ **rooms_controller.rb**
134
140
 
135
141
  ```ruby
136
142
 
137
- class Entry < ApplicationRecord
143
+ # 各エントリー内で、最新のメッセージを取得する。
138
144
 
139
- belongs_to :user
145
+ @last_message = @another_entries.each do |lm|
140
146
 
141
- belongs_to :room
142
-
143
-
144
-
145
- has_many :messages, through: :room #この行を追加。
147
+ Message.find_by(id: lm.room.message_ids.last)
146
148
 
147
149
  end
148
150
 
@@ -150,117 +152,7 @@
150
152
 
151
153
 
152
154
 
153
- **message.rb**
154
-
155
- ```ruby
156
-
157
- class Message < ApplicationRecord
158
-
159
- belongs_to :user
160
-
161
- belongs_to :room
162
-
163
-
164
-
165
- has_one :entry, through: :room #この行を追加。
166
-
167
- end
168
-
169
- ```
170
-
171
-
172
-
173
- その上で`Message`テーブルの結合(`join`)を試みました。
174
-
175
-
176
-
177
- **rooms_controller.rb**
178
-
179
- ```ruby
180
-
181
- class RoomsController < ApplicationController
182
-
183
- before_action :set_another_entries, only: [:index, :show]
184
-
185
-
186
-
187
- private
188
-
189
- def set_another_entries
190
-
191
- my_room_ids = @current_user.entries.pluck(:room_id)
192
-
193
- @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id)
194
-
195
- @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
196
-
197
- end
198
-
199
- ```
200
-
201
-
202
-
203
- しかし以下のエラーが発生しました。
204
-
205
- ```
206
-
207
- ActiveRecord::StatementInvalid in Rooms#index
208
-
209
- Showing C:/hoge/app/views/rooms/index.html.erb where line #12 raised:
210
-
211
-
212
-
213
- SQLite3::SQLException: ambiguous column name: user_id: SELECT "entries".* FROM "entries" INNER JOIN "rooms" ON "rooms"."id" = "entries"."room_id" INNER JOIN "messages" ON "messages"."room_id" = "rooms"."id" WHERE "entries"."room_id" IN (?, ?, ?, ?) AND (user_id != 20) ORDER BY messages.created_at DESC
214
-
215
- Extracted source (around line #12):
216
-
217
- 10 <div class="message-items">
218
-
219
- 11
220
-
221
- 12 <% @another_entries.each do |e| %>
222
-
223
- 13 <div class="message-item">
224
-
225
- 14
226
-
227
- 15 <div class="message-left">
228
-
229
- ```
230
-
231
-
232
-
233
- 恐らくリレーションを与えた事で`Entry`と`Message`の両テーブルに`user_id`が存在する事になり、どちらのテーブルの物かを判別する事が出来ない、と言った内容なのかと思います。
234
-
235
-
236
-
237
- `scope`を使ってそれを明示する(?)と言った[記事](https://qiita.com/j-sunaga/items/99e576cca995b84a7839)を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
238
-
239
-
240
-
241
- **room.rb**
242
-
243
- ```ruby
244
-
245
- class Room < ApplicationRecord
246
-
247
- has_many :messages, dependent: :destroy
248
-
249
- has_many :entries, dependent: :destroy
250
-
251
- has_many :users, through: :entries
252
-
253
-
254
-
255
- scope :select_entry, -> (entry) { where('user_id = ?', entry) } #この行を追加。
256
-
257
- end
258
-
259
- ```
260
-
261
-
262
-
263
- 実はこの後で「`message`の中身が存在する`Entry`のみを表示する」と言った記述もしていきたいので、出来ましたら`Entry`と`Message`の両テーブルはリンクさせた上で実装出来れば一番有難いです。
155
+ しかしこれを`join`する箇所にどう組み込んでいけば良いか分かりません…。
264
156
 
265
157
  どなたかご助言を頂けませんでしょうか。
266
158
 

2

タイトルを変更。

2020/12/24 06:52

投稿

punchan36
punchan36

スコア105

test CHANGED
@@ -1 +1 @@
1
- メッセジが送信された時間順で、メッセージ一覧表示した
1
+ ブルjoinした際に「ambiguous column name」のエラーが出る
test CHANGED
File without changes

1

scopeに関して参考にした記事のリンクを追記。

2020/12/22 02:01

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -234,7 +234,7 @@
234
234
 
235
235
 
236
236
 
237
- `scope`を使ってそれを明示する(?)と言った記事を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
237
+ `scope`を使ってそれを明示する(?)と言った[記事](https://qiita.com/j-sunaga/items/99e576cca995b84a7839)を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
238
238
 
239
239
 
240
240