質問するログイン新規登録

質問編集履歴

6

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

2020/12/30 11:41

投稿

punchan36
punchan36

スコア105

title CHANGED
File without changes
body CHANGED
@@ -105,7 +105,15 @@
105
105
  ```
106
106
  実はこの後で「`message`の中身が存在する`Entry`のみを表示する」と言った記述もしていきたいので、出来ましたら`Entry`と`Message`の両テーブルはリンクさせた上で実装出来れば一番有難いです。
107
107
  どなたかご助言を頂けませんでしょうか。
108
+
108
109
  ### 補足情報(FW/ツールのバージョンなど)
109
110
  ruby 2.6.4p104
110
111
  RubyGems 3.0.3
111
- Rails 5.2.3
112
+ Rails 5.2.3
113
+
114
+ ### 追記
115
+ その後、以下の2点を無事実装する事が出来ました。
116
+ 1. メッセージが送信された時間順でトークルーム一覧を表示する。
117
+ 2. `message`の中身が存在しない`Entry`は表示しない。
118
+
119
+ [こちらの質問](https://teratail.com/questions/313145)をご参考頂ければと思います。

5

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

2020/12/30 11:41

投稿

punchan36
punchan36

スコア105

title CHANGED
@@ -1,1 +1,1 @@
1
- メッセ送信された時間順でトークルーム一覧を表示したい
1
+ ambiguous column nameのエラーが表示される。
body CHANGED
@@ -1,85 +1,111 @@
1
1
  ### 前提・実現したいこと
2
-
3
2
  メッセージの送受信機能を実装しました。
4
- どのユーザーとのトークルームが存在するかを表示する為に、`User`と`Room`の中間テーブルである`Entry`一覧表示するビューがあります(LINE等のように)
3
+ 現段階では`User`と`Room`の中間テーブルである`Entry`に`id`が作成された時間順でメッセージ一覧表示されています。
5
-
6
- メッセージが送信された時間順で一覧を表示したいですが、現状、メッセージの数の分だけ`Entry`が何度も表示されてしまいます
4
+ これを、メッセージが送信された時間順で一覧を表示したいです。
7
-
8
5
  ### リレーション関連
9
-
10
6
  **user.rb**
11
7
  ```ruby
12
8
  class User < ApplicationRecord
13
- has_many :messages, dependent: :destroy
9
+ has_many :messages, dependent: :destroy
14
- has_many :entries, dependent: :destroy
10
+ has_many :entries, dependent: :destroy
15
- has_many :rooms, through: :entries
11
+ has_many :rooms, through: :entries
16
12
  end
17
13
  ```
18
-
19
14
  **room.rb**
20
15
  ```ruby
21
16
  class Room < ApplicationRecord
22
- has_many :messages, dependent: :destroy
17
+ has_many :messages, dependent: :destroy
23
- has_many :entries, dependent: :destroy
18
+ has_many :entries, dependent: :destroy
24
- has_many :users, through: :entries
19
+ has_many :users, through: :entries
25
20
  end
26
21
  ```
27
-
28
22
  **entry.rb**
29
23
  ```ruby
30
24
  class Entry < ApplicationRecord
31
- belongs_to :user
25
+ belongs_to :user
32
- belongs_to :room
26
+ belongs_to :room
33
- has_many :messages, through: :room
34
27
  end
35
28
  ```
36
-
37
29
  **message.rb**
38
30
  ```ruby
39
31
  class Message < ApplicationRecord
40
- belongs_to :user
32
+ belongs_to :user
41
- belongs_to :room
33
+ belongs_to :room
42
- has_one :entry, through: :room
43
34
  end
44
35
  ```
45
- ![ER図](f735b1410ec66f2987e6eed73ad03d86.jpeg)
46
-
47
36
  ### rooms_controller.rb
48
-
37
+ このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
49
38
  ```ruby
50
39
  class RoomsController < ApplicationController
51
- before_action :set_another_entries, only: [:index, :show]
40
+ before_action :set_another_entries, only: [:index, :show]
52
-
53
- private
41
+ private
54
- def set_another_entries
42
+ def set_another_entries
55
-   # ログイン中のユーザーの持つEntryを配列にする。
56
- my_room_ids = @current_user.entries.pluck(:room_id)
43
+ my_room_ids = @current_user.entries.pluck(:room_id) # ログイン中のユーザーの持つEntryを配列にする。
57
- # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
44
+ # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
58
- @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('entries.user_id != ?', @current_user.id)
45
+ @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id).order(created_at: :desc)
59
- # メッセージが作成された順にエントリーを表示する。
60
- @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
61
- end
62
46
  end
47
+ end
63
48
  ```
64
- このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
65
-
66
49
  ### 試したこと
67
-
68
- 「メッセージが作成された順に、数だけ`Entry`を全て表示する」と言う内容になっしまっていると思いますので、「各エントリー内で、最新のメッセージが作成された順に`Entry`を一つずつ表示する」と言内容にべく、以下の定義付けも考えてみました
50
+ まず[過去の質問](https://teratail.com/questions/272305)を参考しました。こちらの質問者さまは場合で言う`Room`を繰り返し表示されているので、`Message`テーブル結合(`join`)する事で解決されたよす。
69
-
51
+ ただ私の場合は`Entry`を繰り返し表示させており、`message`テーブルとのリレーションが出来ていません。
52
+ ![ER図](c9e65e83db330e8df382f6e085003ba6.jpeg)
53
+ ですのでそれを明示しようと考えました。
54
+ **entry.rb**
55
+ ```ruby
56
+ class Entry < ApplicationRecord
57
+ belongs_to :user
58
+ belongs_to :room
59
+ has_many :messages, through: :room #この行を追加。
60
+ end
61
+ ```
62
+ **message.rb**
63
+ ```ruby
64
+ class Message < ApplicationRecord
65
+ belongs_to :user
66
+ belongs_to :room
67
+ has_one :entry, through: :room #この行を追加。
68
+ end
69
+ ```
70
+ その上で`Message`テーブルの結合(`join`)を試みました。
70
71
  **rooms_controller.rb**
71
72
  ```ruby
73
+ class RoomsController < ApplicationController
74
+ before_action :set_another_entries, only: [:index, :show]
75
+ private
72
- # 各エントリー内で、最新のメッセージを取得する。
76
+ def set_another_entries
73
- @last_message = @another_entries.each do |lm|
77
+ my_room_ids = @current_user.entries.pluck(:room_id)
78
+ @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id)
74
- Message.find_by(id: lm.room.message_ids.last)
79
+ @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
75
80
  end
76
81
  ```
77
-
78
- しかしこれを`join`する箇所にどう組み込んでいけば良いか分かりません…。
82
+ しかし以下のエラーが発生しました。
83
+ ```
84
+ ActiveRecord::StatementInvalid in Rooms#index
85
+ Showing C:/hoge/app/views/rooms/index.html.erb where line #12 raised:
86
+ 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
87
+ Extracted source (around line #12):
88
+ 10 <div class="message-items">
89
+ 11
90
+ 12 <% @another_entries.each do |e| %>
91
+ 13 <div class="message-item">
92
+ 14
93
+ 15 <div class="message-left">
94
+ ```
95
+ 恐らくリレーションを与えた事で`Entry`と`Message`の両テーブルに`user_id`が存在する事になり、どちらのテーブルの物かを判別する事が出来ない、と言った内容なのかと思います。
96
+ `scope`を使ってそれを明示する(?)と言った[記事](https://qiita.com/j-sunaga/items/99e576cca995b84a7839)を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
97
+ **room.rb**
98
+ ```ruby
99
+ class Room < ApplicationRecord
100
+ has_many :messages, dependent: :destroy
101
+ has_many :entries, dependent: :destroy
102
+ has_many :users, through: :entries
103
+ scope :select_entry, -> (entry) { where('user_id = ?', entry) } #この行を追加。
104
+ end
105
+ ```
106
+ 実はこの後で「`message`の中身が存在する`Entry`のみを表示する」と言った記述もしていきたいので、出来ましたら`Entry`と`Message`の両テーブルはリンクさせた上で実装出来れば一番有難いです。
79
107
  どなたかご助言を頂けませんでしょうか。
80
-
81
108
  ### 補足情報(FW/ツールのバージョンなど)
82
-
83
109
  ruby 2.6.4p104
84
110
  RubyGems 3.0.3
85
111
  Rails 5.2.3

4

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

2020/12/27 08:00

投稿

punchan36
punchan36

スコア105

title CHANGED
File without changes
body CHANGED
@@ -55,10 +55,10 @@
55
55
    # ログイン中のユーザーの持つEntryを配列にする。
56
56
  my_room_ids = @current_user.entries.pluck(:room_id)
57
57
  # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
58
- @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id).order(created_at: :desc)
58
+ @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('entries.user_id != ?', @current_user.id)
59
- end
60
59
  # メッセージが作成された順にエントリーを表示する。
61
60
  @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
61
+ end
62
62
  end
63
63
  ```
64
64
  このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。

3

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

2020/12/25 01:38

投稿

punchan36
punchan36

スコア105

title CHANGED
@@ -1,1 +1,1 @@
1
- ルをjoinした際に「ambiguous column name」のエラーが出る。
1
+ メッセジが送信された時間順でトークーム一覧表示した
body CHANGED
@@ -1,9 +1,10 @@
1
1
  ### 前提・実現したいこと
2
2
 
3
3
  メッセージの送受信機能を実装しました。
4
- 現段階では`User`と`Room`の中間テーブルである`Entry`に`id`が作成された時間順でメッセージ一覧表示されています。
4
+ どのユーザーとのトークルームが存在するかを表示する為に、`User`と`Room`の中間テーブルである`Entry`一覧表示するビューがあります(LINE等のように)
5
- これを、メッセージが送信された時間順で一覧を表示したいです。
6
5
 
6
+ メッセージが送信された時間順で一覧を表示したいのですが、現状、メッセージの数の分だけ`Entry`が何度も表示されてしまいます。
7
+
7
8
  ### リレーション関連
8
9
 
9
10
  **user.rb**
@@ -28,7 +29,8 @@
28
29
  ```ruby
29
30
  class Entry < ApplicationRecord
30
31
  belongs_to :user
31
- belongs_to :room
32
+ belongs_to :room
33
+ has_many :messages, through: :room
32
34
  end
33
35
  ```
34
36
 
@@ -37,99 +39,43 @@
37
39
  class Message < ApplicationRecord
38
40
  belongs_to :user
39
41
  belongs_to :room
42
+ has_one :entry, through: :room
40
43
  end
41
44
  ```
45
+ ![ER図](f735b1410ec66f2987e6eed73ad03d86.jpeg)
42
46
 
43
47
  ### rooms_controller.rb
44
48
 
45
- このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
46
49
  ```ruby
47
50
  class RoomsController < ApplicationController
48
51
  before_action :set_another_entries, only: [:index, :show]
49
52
 
50
53
  private
51
54
  def set_another_entries
55
+   # ログイン中のユーザーの持つEntryを配列にする。
52
- my_room_ids = @current_user.entries.pluck(:room_id) # ログイン中のユーザーの持つEntryを配列にする。
56
+ my_room_ids = @current_user.entries.pluck(:room_id)
53
57
  # 上で定義した「ログイン中のユーザーの持つEntry」の内、自分以外の相手一覧を表示する。
54
58
  @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id).order(created_at: :desc)
55
59
  end
60
+ # メッセージが作成された順にエントリーを表示する。
61
+ @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
56
62
  end
57
63
  ```
64
+ このコントローラ内で定義した`Entry`をビュー側で繰り返し処理し、表示しています。
58
65
 
59
66
  ### 試したこと
60
67
 
61
- まず[過去の質問](https://teratail.com/questions/272305)を参考にしました。こちらの質問者まは場合で言う`Room`を繰り返し表示されているので、`Message`テブルを結合(`join`)する事解決されたす。
68
+ 「メッセージが作成れた順に数だけ`Entry`を全て表示する」と言う内容になっしまっていると思いますので、「各エントリ、最新のメッセージが作成された順に`Entry`を一つずつ表示する」と言内容にべく、以下の定義付けも考えてみました
62
69
 
63
- ただ私の場合は`Entry`を繰り返し表示させており、`message`テーブルとのリレーションが出来ていません。
64
- ![ER図](c9e65e83db330e8df382f6e085003ba6.jpeg)
65
- ですのでそれを明示しようと考えました。
66
-
67
- **entry.rb**
68
- ```ruby
69
- class Entry < ApplicationRecord
70
- belongs_to :user
71
- belongs_to :room
72
-
73
- has_many :messages, through: :room #この行を追加。
74
- end
75
- ```
76
-
77
- **message.rb**
78
- ```ruby
79
- class Message < ApplicationRecord
80
- belongs_to :user
81
- belongs_to :room
82
-
83
- has_one :entry, through: :room #この行を追加。
84
- end
85
- ```
86
-
87
- その上で`Message`テーブルの結合(`join`)を試みました。
88
-
89
70
  **rooms_controller.rb**
90
71
  ```ruby
91
- class RoomsController < ApplicationController
92
- before_action :set_another_entries, only: [:index, :show]
93
-
94
- private
95
- def set_another_entries
96
- my_room_ids = @current_user.entries.pluck(:room_id)
97
- @another_entries = Entry.includes(:user, :room).where(room_id: my_room_ids).where('user_id != ?', @current_user.id)
98
- @another_entries = @another_entries.joins(:messages).order("messages.created_at DESC")
99
- end
100
- ```
101
-
102
- しかし以下のエラーが発生しました。
103
- ```
104
- ActiveRecord::StatementInvalid in Rooms#index
105
- Showing C:/hoge/app/views/rooms/index.html.erb where line #12 raised:
106
-
107
- 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
108
- Extracted source (around line #12):
109
- 10 <div class="message-items">
110
- 11
111
- 12 <% @another_entries.each do |e| %>
112
- 13 <div class="message-item">
113
- 14
114
- 15 <div class="message-left">
115
- ```
116
-
117
- 恐らくリレーションを与えた事で`Entry`と`Message`の両テーブルに`user_id`が存在する事になり、どちらのテーブルの物かを判別する事が出来ない、と言った内容なのかと思います。
118
-
119
- `scope`を使ってそれを明示する(?)と言った[記事](https://qiita.com/j-sunaga/items/99e576cca995b84a7839)を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
120
-
121
- **room.rb**
122
- ```ruby
123
- class Room < ApplicationRecord
124
- has_many :messages, dependent: :destroy
125
- has_many :entries, dependent: :destroy
126
- has_many :users, through: :entries
127
-
128
- scope :select_entry, -> (entry) { where('user_id = ?', entry) } #この行を追加。
72
+ # 各エントリー内で、最新のメッセージを取得する。
73
+ @last_message = @another_entries.each do |lm|
74
+ Message.find_by(id: lm.room.message_ids.last)
129
75
  end
130
76
  ```
131
77
 
132
- 実はの後で「`message`の中身が存在する`Entry`のを表示する」と言った記述もしてきたので、出来したら`Entry`と`Message`の両テーブルはリンクさた上で実装出来れば一番有難いです
78
+ しかしれを`join`する箇所にどう組込んでけば良か分かりません…
133
79
  どなたかご助言を頂けませんでしょうか。
134
80
 
135
81
  ### 補足情報(FW/ツールのバージョンなど)

2

タイトルを変更。

2020/12/24 06:52

投稿

punchan36
punchan36

スコア105

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

1

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

2020/12/22 02:01

投稿

punchan36
punchan36

スコア105

title CHANGED
File without changes
body CHANGED
@@ -116,7 +116,7 @@
116
116
 
117
117
  恐らくリレーションを与えた事で`Entry`と`Message`の両テーブルに`user_id`が存在する事になり、どちらのテーブルの物かを判別する事が出来ない、と言った内容なのかと思います。
118
118
 
119
- `scope`を使ってそれを明示する(?)と言った記事を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
119
+ `scope`を使ってそれを明示する(?)と言った[記事](https://qiita.com/j-sunaga/items/99e576cca995b84a7839)を見つけたので試してみましたが、また同様に`ambiguous column name`のエラーが表示され上手くいきませんでした。
120
120
 
121
121
  **room.rb**
122
122
  ```ruby