質問編集履歴
4
「最終的に解決したコード」を追記致しました。
title
CHANGED
File without changes
|
body
CHANGED
@@ -236,4 +236,30 @@
|
|
236
236
|
- キーワード:hoge
|
237
237
|
|
238
238
|
例えば上記の条件で検索した場合:
|
239
|
-
男性で、かつ日本語・中国語をともに話せ(それ以上話せても可)、かつ自己紹介欄に「hoge」の文言を含むユーザーをヒットさせたいです(名前は問わない。[]と言う名前と言う訳ではない)。
|
239
|
+
男性で、かつ日本語・中国語をともに話せ(それ以上話せても可)、かつ自己紹介欄に「hoge」の文言を含むユーザーをヒットさせたいです(名前は問わない。[]と言う名前と言う訳ではない)。
|
240
|
+
|
241
|
+
### 最終的に解決したコード
|
242
|
+
|
243
|
+
**users_controller.rb**
|
244
|
+
```ruby
|
245
|
+
@users = User.all.order(created_at: :desc).page(params[:page]).per(20)
|
246
|
+
|
247
|
+
if params[:language_ids].present?
|
248
|
+
@users = @users.select("users.*, COUNT(*) AS languages_count")
|
249
|
+
.joins(:user_languages)
|
250
|
+
.where(user_languages: { language_id: params[:language_ids] })
|
251
|
+
.group("user_languages.user_id")
|
252
|
+
.having("languages_count = #{params[:language_ids]&.length}")
|
253
|
+
end
|
254
|
+
|
255
|
+
if params[:name].present? || params[:gender].present? || params[:introduction].present?
|
256
|
+
@users = @users.where(['name LIKE ? AND gender LIKE ? AND introduction LIKE ?',
|
257
|
+
"%#{params[:name]}%", "#{params[:gender]}%", "%#{params[:introduction]}%"])
|
258
|
+
end
|
259
|
+
|
260
|
+
if @users == []
|
261
|
+
# 該当のユーザーが存在しなかった場合。
|
262
|
+
flash[:notice] = "User was not found"
|
263
|
+
@users
|
264
|
+
end
|
265
|
+
```
|
3
検索の仕様に関して、追記2を書き加えました。
title
CHANGED
File without changes
|
body
CHANGED
@@ -206,4 +206,34 @@
|
|
206
206
|
(0.8ms) SELECT COUNT(*) FROM `notifications` WHERE `notifications`.`visited_id` = 2 AND `notifications`.`action` != 'message' AND `notifications`.`checked` = FALSE
|
207
207
|
↳ app/helpers/notifications_helper.rb:48
|
208
208
|
Completed 200 OK in 342ms (Views: 304.0ms | ActiveRecord: 5.3ms)
|
209
|
-
```
|
209
|
+
```
|
210
|
+
|
211
|
+
### 追記2
|
212
|
+
|
213
|
+
【検索の仕様に関して】
|
214
|
+
仕様と致しましては、検索された言語(複数可)を「全てを含んだ」ユーザーをヒットさせたいです。
|
215
|
+
|
216
|
+
- ユーザーA: 日本語
|
217
|
+
- ユーザーB: 日本語、英語
|
218
|
+
- ユーザーC: 日本語、英語、中国語
|
219
|
+
|
220
|
+
例えば上記のユーザーがいた場合、
|
221
|
+
①「日本語」で検索 → A, B, C全員をヒットさせたい。
|
222
|
+
②「日本語、英語」で検索 → B, Cをヒットさせたい。
|
223
|
+
③「英語、中国語」で検索 → Cのみをヒットさせたい。
|
224
|
+
|
225
|
+
※完全一致ではない。
|
226
|
+
「日本語」でユーザー検索 → 完全一致ですと「日本語のみ」を話せるユーザーAだけがヒットすると思いますが、実装したいのはこちらの機能ではありません。
|
227
|
+
|
228
|
+
※部分一致でもない。
|
229
|
+
「日本語、英語」でユーザー検索 → 部分一致ですと「日本語または英語のどちらか」を話せるユーザーA, B, Cの全てがヒットすると思いますが、実装したいのはこちらの機能でもありません。
|
230
|
+
|
231
|
+
名前や性別を含んだ検索でも同様に、検索された文言を「全て含んだ」ユーザーをヒットさせたいです。
|
232
|
+
|
233
|
+
- 名前:(指定なし)
|
234
|
+
- 性別:Male
|
235
|
+
- 言語:日本語、中国語
|
236
|
+
- キーワード:hoge
|
237
|
+
|
238
|
+
例えば上記の条件で検索した場合:
|
239
|
+
男性で、かつ日本語・中国語をともに話せ(それ以上話せても可)、かつ自己紹介欄に「hoge」の文言を含むユーザーをヒットさせたいです(名前は問わない。[]と言う名前と言う訳ではない)。
|
2
【追記】から下を書き加えました。また sex の部分は gender に置き換えました。
title
CHANGED
File without changes
|
body
CHANGED
@@ -25,8 +25,8 @@
|
|
25
25
|
<%= f.search_field :introduction, :value => params[:introduction] %>
|
26
26
|
|
27
27
|
<p>Gender</p>
|
28
|
-
<%= f.radio_button :
|
28
|
+
<%= f.radio_button :gender, "Male", :checked => params[:gender] == ("Male") %>Male
|
29
|
-
<%= f.radio_button :
|
29
|
+
<%= f.radio_button :gender, "Female", :checked => params[:gender] == ("Female") %>Female
|
30
30
|
|
31
31
|
<p>Languages</p>
|
32
32
|
<%= f.check_box :language_ids, {multiple: true, :checked => params[:language_ids]&.include?("1")}, "1", false %>Japanese
|
@@ -37,12 +37,12 @@
|
|
37
37
|
<% end %>
|
38
38
|
```
|
39
39
|
|
40
|
-
**
|
40
|
+
**users_controller.rb**
|
41
41
|
```ここに言語名を入力
|
42
42
|
def index
|
43
|
-
if params[:name].present? || params[:introduction].present? || params[:
|
43
|
+
if params[:name].present? || params[:introduction].present? || params[:gender].present? || params[:language_ids].present?
|
44
|
-
@users = User.where(['name LIKE ? AND introduction LIKE ? AND
|
44
|
+
@users = User.where(['name LIKE ? AND introduction LIKE ? AND gender LIKE ? AND language LIKE ?',
|
45
|
-
"%#{params[:name]}%", "%#{params[:introduction]}%", "#{params[:
|
45
|
+
"%#{params[:name]}%", "%#{params[:introduction]}%", "#{params[:gender]}%", "%#{params[:language_ids]}%"])
|
46
46
|
.page(params[:page]).per(20)
|
47
47
|
else
|
48
48
|
# ユーザーが何も入力しなかった場合。
|
@@ -89,4 +89,121 @@
|
|
89
89
|
|
90
90
|
ruby 2.6.4p104
|
91
91
|
RubyGems 3.0.3
|
92
|
-
Rails 5.2.3
|
92
|
+
Rails 5.2.3
|
93
|
+
|
94
|
+
### 【追記】
|
95
|
+
|
96
|
+
#### モデル関連
|
97
|
+
|
98
|
+
**user.rb**
|
99
|
+
```
|
100
|
+
class User < ApplicationRecord
|
101
|
+
has_many :user_languages, dependent: :destroy
|
102
|
+
has_many :languages, through: :user_languages
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
**language.rb**
|
107
|
+
```
|
108
|
+
class Language < ApplicationRecord
|
109
|
+
has_many :user_language
|
110
|
+
has_many :users, through: :user_language
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
**user_language.rb**
|
115
|
+
```
|
116
|
+
class UserLanguage < ApplicationRecord
|
117
|
+
belongs_to :user
|
118
|
+
belongs_to :language
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
#### テーブル情報
|
123
|
+
|
124
|
+
**schema.rb**
|
125
|
+
```ruby
|
126
|
+
ActiveRecord::Schema.define(version: 2021_03_11_063016) do
|
127
|
+
create_table "languages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
|
128
|
+
t.string "description"
|
129
|
+
t.boolean "done"
|
130
|
+
t.bigint "user_id"
|
131
|
+
t.datetime "created_at", null: false
|
132
|
+
t.datetime "updated_at", null: false
|
133
|
+
t.index ["user_id"], name: "index_languages_on_user_id"
|
134
|
+
end
|
135
|
+
|
136
|
+
create_table "user_languages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
|
137
|
+
t.bigint "user_id"
|
138
|
+
t.bigint "language_id"
|
139
|
+
t.datetime "created_at", null: false
|
140
|
+
t.datetime "updated_at", null: false
|
141
|
+
t.index ["language_id", "user_id"], name: "index_user_languages_on_language_id_and_user_id", unique: true
|
142
|
+
t.index ["language_id"], name: "index_user_languages_on_language_id"
|
143
|
+
t.index ["user_id"], name: "index_user_languages_on_user_id"
|
144
|
+
end
|
145
|
+
|
146
|
+
create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
|
147
|
+
t.string "name"
|
148
|
+
t.datetime "created_at", null: false
|
149
|
+
t.datetime "updated_at", null: false
|
150
|
+
t.string "gender" # "sex" から "gender" に変更しました。
|
151
|
+
t.string "language"
|
152
|
+
t.text "introduction"
|
153
|
+
end
|
154
|
+
|
155
|
+
add_foreign_key "languages", "users"
|
156
|
+
add_foreign_key "user_languages", "languages"
|
157
|
+
add_foreign_key "user_languages", "users"
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
#### ログ関連
|
162
|
+
|
163
|
+
以下の言語を話せるユーザーに関する `language` 情報を確認したログを追記致しました。
|
164
|
+
|
165
|
+
- ユーザーA(`id: 1`): 日本語
|
166
|
+
- ユーザーB(`id: 2`): 日本語、英語
|
167
|
+
- ユーザーC(`id: 3`): 日本語、英語、中国語
|
168
|
+
|
169
|
+
```
|
170
|
+
[36] pry(main)> User.find(1).language
|
171
|
+
User Load (33.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
|
172
|
+
=> "[\"1\"]"
|
173
|
+
|
174
|
+
[37] pry(main)> User.find(2).language
|
175
|
+
User Load (1.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
|
176
|
+
=> "[\"1\", \"2\"]"
|
177
|
+
|
178
|
+
[38] pry(main)> User.find(3).language
|
179
|
+
User Load (20.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
|
180
|
+
=> "[\"1\", \"2\", \"3\"]"
|
181
|
+
```
|
182
|
+
`/` (コマンド上では `¥`) が表示されていました。ここに問題があったのでしょうか…。
|
183
|
+
|
184
|
+
#### winterboumさまにご提示頂いたコードで検索した際のログ
|
185
|
+
|
186
|
+
以下のユーザーしか存在しない中で「英語」のみで検索した所、誰もヒットしませんでした。
|
187
|
+
|
188
|
+
- ユーザーA(`id: 1`): 日本語
|
189
|
+
- ユーザーB(`id: 2`): 日本語、英語
|
190
|
+
- ユーザーC(`id: 3`): 日本語、英語、中国語
|
191
|
+
|
192
|
+
```
|
193
|
+
Parameters: {"utf8"=>"✓", "name"=>"", "language_ids"=>["2], "introduction"=>"", "commit"=>"search"}
|
194
|
+
User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
|
195
|
+
↳ app/controllers/application_controller.rb:9
|
196
|
+
User Load (0.8ms) SELECT `users`.* FROM `users` WHERE (name LIKE '%%' AND introduction LIKE '%%' AND gender LIKE '%') AND `users`.`language` = '2' LIMIT 20 OFFSET 0
|
197
|
+
↳ app/controllers/users_controller.rb:34
|
198
|
+
Rendering users/index.html.erb within layouts/application
|
199
|
+
User Load (2.4ms) SELECT `users`.* FROM `users` ORDER BY `users`.`created_at` DESC LIMIT 20 OFFSET 0
|
200
|
+
↳ app/views/users/index.html.erb:40
|
201
|
+
Rendered users/index.html.erb within layouts/application (38.4ms)
|
202
|
+
CACHE User Load (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 [["id", 2], ["LIMIT", 1]]
|
203
|
+
↳ app/views/layouts/application.html.erb:48
|
204
|
+
(0.7ms) SELECT COUNT(*) FROM `notifications` WHERE `notifications`.`visited_id` = 2 AND `notifications`.`checked` = FALSE AND `notifications`.`action` = 'message'
|
205
|
+
↳ app/helpers/notifications_helper.rb:54
|
206
|
+
(0.8ms) SELECT COUNT(*) FROM `notifications` WHERE `notifications`.`visited_id` = 2 AND `notifications`.`action` != 'message' AND `notifications`.`checked` = FALSE
|
207
|
+
↳ app/helpers/notifications_helper.rb:48
|
208
|
+
Completed 200 OK in 342ms (Views: 304.0ms | ActiveRecord: 5.3ms)
|
209
|
+
```
|
1
各ユーザーの言語情報を rails c の内容を元に編集致しました。
title
CHANGED
File without changes
|
body
CHANGED
@@ -64,12 +64,25 @@
|
|
64
64
|
```
|
65
65
|
Parameters: {"utf8"=>"✓", "name"=>"", "introduction"=>"", "language_ids"=>["2", "3"], "commit"=>"search"}
|
66
66
|
```
|
67
|
-
各ユーザーの言語情報は以下の様に保存されて
|
67
|
+
各ユーザーの言語情報は以下の様に保存されておりましたので、なぜこれでユーザーCがヒットにならないのかが分かりません…。
|
68
68
|
|
69
|
-
|
69
|
+
```
|
70
|
-
|
70
|
+
[27] pry(main)> User.find(1).language_ids
|
71
|
-
|
71
|
+
User Load (4.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
|
72
|
+
(4.9ms) SELECT `languages`.`id` FROM `languages` INNER JOIN `user_languages` ON `languages`.`id` = `user_languages`.`language_id` WHERE `user_languages`.`user_id` = 1
|
73
|
+
=> [1]
|
72
74
|
|
75
|
+
[28] pry(main)> User.find(2).language_ids
|
76
|
+
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
|
77
|
+
(0.8ms) SELECT `languages`.`id` FROM `languages` INNER JOIN `user_languages` ON `languages`.`id` = `user_languages`.`language_id` WHERE `user_languages`.`user_id` = 2
|
78
|
+
=> [1, 2]
|
79
|
+
|
80
|
+
[29] pry(main)> User.find(3).language_ids
|
81
|
+
User Load (2.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
|
82
|
+
(2.3ms) SELECT `languages`.`id` FROM `languages` INNER JOIN `user_languages` ON `languages`.`id` = `user_languages`.`language_id` WHERE `user_languages`.`user_id` = 3
|
83
|
+
=> [1, 2, 3]
|
84
|
+
```
|
85
|
+
|
73
86
|
どなたかご助言を頂けますと有難いです。
|
74
87
|
|
75
88
|
### 補足情報(FW/ツールのバージョンなど)
|