質問編集履歴

4

「最終的に解決したコード」を追記致しました。

2021/03/18 03:23

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -475,3 +475,55 @@
475
475
  例えば上記の条件で検索した場合:
476
476
 
477
477
  男性で、かつ日本語・中国語をともに話せ(それ以上話せても可)、かつ自己紹介欄に「hoge」の文言を含むユーザーをヒットさせたいです(名前は問わない。[]と言う名前と言う訳ではない)。
478
+
479
+
480
+
481
+ ### 最終的に解決したコード
482
+
483
+
484
+
485
+ **users_controller.rb**
486
+
487
+ ```ruby
488
+
489
+ @users = User.all.order(created_at: :desc).page(params[:page]).per(20)
490
+
491
+
492
+
493
+ if params[:language_ids].present?
494
+
495
+ @users = @users.select("users.*, COUNT(*) AS languages_count")
496
+
497
+ .joins(:user_languages)
498
+
499
+ .where(user_languages: { language_id: params[:language_ids] })
500
+
501
+ .group("user_languages.user_id")
502
+
503
+ .having("languages_count = #{params[:language_ids]&.length}")
504
+
505
+ end
506
+
507
+
508
+
509
+ if params[:name].present? || params[:gender].present? || params[:introduction].present?
510
+
511
+ @users = @users.where(['name LIKE ? AND gender LIKE ? AND introduction LIKE ?',
512
+
513
+ "%#{params[:name]}%", "#{params[:gender]}%", "%#{params[:introduction]}%"])
514
+
515
+ end
516
+
517
+
518
+
519
+ if @users == []
520
+
521
+ # 該当のユーザーが存在しなかった場合。
522
+
523
+ flash[:notice] = "User was not found"
524
+
525
+ @users
526
+
527
+ end
528
+
529
+ ```

3

検索の仕様に関して、追記2を書き加えました。

2021/03/18 03:23

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -415,3 +415,63 @@
415
415
  Completed 200 OK in 342ms (Views: 304.0ms | ActiveRecord: 5.3ms)
416
416
 
417
417
  ```
418
+
419
+
420
+
421
+ ### 追記2
422
+
423
+
424
+
425
+ 【検索の仕様に関して】
426
+
427
+ 仕様と致しましては、検索された言語(複数可)を「全てを含んだ」ユーザーをヒットさせたいです。
428
+
429
+
430
+
431
+ - ユーザーA: 日本語
432
+
433
+ - ユーザーB: 日本語、英語
434
+
435
+ - ユーザーC: 日本語、英語、中国語
436
+
437
+
438
+
439
+ 例えば上記のユーザーがいた場合、
440
+
441
+ ①「日本語」で検索 → A, B, C全員をヒットさせたい。
442
+
443
+ ②「日本語、英語」で検索 → B, Cをヒットさせたい。
444
+
445
+ ③「英語、中国語」で検索 → Cのみをヒットさせたい。
446
+
447
+
448
+
449
+ ※完全一致ではない。
450
+
451
+ 「日本語」でユーザー検索 → 完全一致ですと「日本語のみ」を話せるユーザーAだけがヒットすると思いますが、実装したいのはこちらの機能ではありません。
452
+
453
+
454
+
455
+ ※部分一致でもない。
456
+
457
+ 「日本語、英語」でユーザー検索 → 部分一致ですと「日本語または英語のどちらか」を話せるユーザーA, B, Cの全てがヒットすると思いますが、実装したいのはこちらの機能でもありません。
458
+
459
+
460
+
461
+ 名前や性別を含んだ検索でも同様に、検索された文言を「全て含んだ」ユーザーをヒットさせたいです。
462
+
463
+
464
+
465
+ - 名前:(指定なし)
466
+
467
+ - 性別:Male
468
+
469
+ - 言語:日本語、中国語
470
+
471
+ - キーワード:hoge
472
+
473
+
474
+
475
+ 例えば上記の条件で検索した場合:
476
+
477
+ 男性で、かつ日本語・中国語をともに話せ(それ以上話せても可)、かつ自己紹介欄に「hoge」の文言を含むユーザーをヒットさせたいです(名前は問わない。[]と言う名前と言う訳ではない)。

2

【追記】から下を書き加えました。また sex の部分は gender に置き換えました。

2021/03/12 08:56

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -52,9 +52,9 @@
52
52
 
53
53
  <p>Gender</p>
54
54
 
55
- <%= f.radio_button :sex, "Male", :checked => params[:sex] == ("Male") %>Male
55
+ <%= f.radio_button :gender, "Male", :checked => params[:gender] == ("Male") %>Male
56
-
56
+
57
- <%= f.radio_button :sex, "Female", :checked => params[:sex] == ("Female") %>Female
57
+ <%= f.radio_button :gender, "Female", :checked => params[:gender] == ("Female") %>Female
58
58
 
59
59
 
60
60
 
@@ -76,17 +76,17 @@
76
76
 
77
77
 
78
78
 
79
- **users_index.html.erb**
79
+ **users_controller.rb**
80
80
 
81
81
  ```ここに言語名を入力
82
82
 
83
83
  def index
84
84
 
85
- if params[:name].present? || params[:introduction].present? || params[:sex].present? || params[:language_ids].present?
85
+ if params[:name].present? || params[:introduction].present? || params[:gender].present? || params[:language_ids].present?
86
-
86
+
87
- @users = User.where(['name LIKE ? AND introduction LIKE ? AND sex LIKE ? AND language LIKE ?',
87
+ @users = User.where(['name LIKE ? AND introduction LIKE ? AND gender LIKE ? AND language LIKE ?',
88
-
88
+
89
- "%#{params[:name]}%", "%#{params[:introduction]}%", "#{params[:sex]}%", "%#{params[:language_ids]}%"])
89
+ "%#{params[:name]}%", "%#{params[:introduction]}%", "#{params[:gender]}%", "%#{params[:language_ids]}%"])
90
90
 
91
91
  .page(params[:page]).per(20)
92
92
 
@@ -181,3 +181,237 @@
181
181
  RubyGems 3.0.3
182
182
 
183
183
  Rails 5.2.3
184
+
185
+
186
+
187
+ ### 【追記】
188
+
189
+
190
+
191
+ #### モデル関連
192
+
193
+
194
+
195
+ **user.rb**
196
+
197
+ ```
198
+
199
+ class User < ApplicationRecord
200
+
201
+ has_many :user_languages, dependent: :destroy
202
+
203
+ has_many :languages, through: :user_languages
204
+
205
+ end
206
+
207
+ ```
208
+
209
+
210
+
211
+ **language.rb**
212
+
213
+ ```
214
+
215
+ class Language < ApplicationRecord
216
+
217
+ has_many :user_language
218
+
219
+ has_many :users, through: :user_language
220
+
221
+ end
222
+
223
+ ```
224
+
225
+
226
+
227
+ **user_language.rb**
228
+
229
+ ```
230
+
231
+ class UserLanguage < ApplicationRecord
232
+
233
+ belongs_to :user
234
+
235
+ belongs_to :language
236
+
237
+ end
238
+
239
+ ```
240
+
241
+
242
+
243
+ #### テーブル情報
244
+
245
+
246
+
247
+ **schema.rb**
248
+
249
+ ```ruby
250
+
251
+ ActiveRecord::Schema.define(version: 2021_03_11_063016) do
252
+
253
+ create_table "languages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
254
+
255
+ t.string "description"
256
+
257
+ t.boolean "done"
258
+
259
+ t.bigint "user_id"
260
+
261
+ t.datetime "created_at", null: false
262
+
263
+ t.datetime "updated_at", null: false
264
+
265
+ t.index ["user_id"], name: "index_languages_on_user_id"
266
+
267
+ end
268
+
269
+
270
+
271
+ create_table "user_languages", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
272
+
273
+ t.bigint "user_id"
274
+
275
+ t.bigint "language_id"
276
+
277
+ t.datetime "created_at", null: false
278
+
279
+ t.datetime "updated_at", null: false
280
+
281
+ t.index ["language_id", "user_id"], name: "index_user_languages_on_language_id_and_user_id", unique: true
282
+
283
+ t.index ["language_id"], name: "index_user_languages_on_language_id"
284
+
285
+ t.index ["user_id"], name: "index_user_languages_on_user_id"
286
+
287
+ end
288
+
289
+
290
+
291
+ create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
292
+
293
+ t.string "name"
294
+
295
+ t.datetime "created_at", null: false
296
+
297
+ t.datetime "updated_at", null: false
298
+
299
+ t.string "gender" # "sex" から "gender" に変更しました。
300
+
301
+ t.string "language"
302
+
303
+ t.text "introduction"
304
+
305
+ end
306
+
307
+
308
+
309
+ add_foreign_key "languages", "users"
310
+
311
+ add_foreign_key "user_languages", "languages"
312
+
313
+ add_foreign_key "user_languages", "users"
314
+
315
+ end
316
+
317
+ ```
318
+
319
+
320
+
321
+ #### ログ関連
322
+
323
+
324
+
325
+ 以下の言語を話せるユーザーに関する `language` 情報を確認したログを追記致しました。
326
+
327
+
328
+
329
+ - ユーザーA(`id: 1`): 日本語
330
+
331
+ - ユーザーB(`id: 2`): 日本語、英語
332
+
333
+ - ユーザーC(`id: 3`): 日本語、英語、中国語
334
+
335
+
336
+
337
+ ```
338
+
339
+ [36] pry(main)> User.find(1).language
340
+
341
+ User Load (33.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
342
+
343
+ => "[\"1\"]"
344
+
345
+
346
+
347
+ [37] pry(main)> User.find(2).language
348
+
349
+ User Load (1.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
350
+
351
+ => "[\"1\", \"2\"]"
352
+
353
+
354
+
355
+ [38] pry(main)> User.find(3).language
356
+
357
+ User Load (20.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
358
+
359
+ => "[\"1\", \"2\", \"3\"]"
360
+
361
+ ```
362
+
363
+ `/` (コマンド上では `¥`) が表示されていました。ここに問題があったのでしょうか…。
364
+
365
+
366
+
367
+ #### winterboumさまにご提示頂いたコードで検索した際のログ
368
+
369
+
370
+
371
+ 以下のユーザーしか存在しない中で「英語」のみで検索した所、誰もヒットしませんでした。
372
+
373
+
374
+
375
+ - ユーザーA(`id: 1`): 日本語
376
+
377
+ - ユーザーB(`id: 2`): 日本語、英語
378
+
379
+ - ユーザーC(`id: 3`): 日本語、英語、中国語
380
+
381
+
382
+
383
+ ```
384
+
385
+ Parameters: {"utf8"=>"✓", "name"=>"", "language_ids"=>["2], "introduction"=>"", "commit"=>"search"}
386
+
387
+ User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
388
+
389
+ ↳ app/controllers/application_controller.rb:9
390
+
391
+ 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
392
+
393
+ ↳ app/controllers/users_controller.rb:34
394
+
395
+ Rendering users/index.html.erb within layouts/application
396
+
397
+ User Load (2.4ms) SELECT `users`.* FROM `users` ORDER BY `users`.`created_at` DESC LIMIT 20 OFFSET 0
398
+
399
+ ↳ app/views/users/index.html.erb:40
400
+
401
+ Rendered users/index.html.erb within layouts/application (38.4ms)
402
+
403
+ CACHE User Load (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 [["id", 2], ["LIMIT", 1]]
404
+
405
+ ↳ app/views/layouts/application.html.erb:48
406
+
407
+ (0.7ms) SELECT COUNT(*) FROM `notifications` WHERE `notifications`.`visited_id` = 2 AND `notifications`.`checked` = FALSE AND `notifications`.`action` = 'message'
408
+
409
+ ↳ app/helpers/notifications_helper.rb:54
410
+
411
+ (0.8ms) SELECT COUNT(*) FROM `notifications` WHERE `notifications`.`visited_id` = 2 AND `notifications`.`action` != 'message' AND `notifications`.`checked` = FALSE
412
+
413
+ ↳ app/helpers/notifications_helper.rb:48
414
+
415
+ Completed 200 OK in 342ms (Views: 304.0ms | ActiveRecord: 5.3ms)
416
+
417
+ ```

1

各ユーザーの言語情報を rails c の内容を元に編集致しました。

2021/03/11 07:55

投稿

punchan36
punchan36

スコア105

test CHANGED
File without changes
test CHANGED
@@ -130,15 +130,41 @@
130
130
 
131
131
  ```
132
132
 
133
- 各ユーザーの言語情報は以下の様に保存されていると思いので、なぜこれでユーザーCがヒットにならないのかが分かりません…。
133
+ 各ユーザーの言語情報は以下の様に保存されておりしたので、なぜこれでユーザーCがヒットにならないのかが分かりません…。
134
134
 
135
135
 
136
136
 
137
- - ユーザーA: ["1"]
137
+ ```
138
138
 
139
- - ユーザーB: ["1", "2"]
139
+ [27] pry(main)> User.find(1).language_ids
140
140
 
141
+ User Load (4.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
142
+
143
+ (4.9ms) SELECT `languages`.`id` FROM `languages` INNER JOIN `user_languages` ON `languages`.`id` = `user_languages`.`language_id` WHERE `user_languages`.`user_id` = 1
144
+
145
+ => [1]
146
+
147
+
148
+
141
- - ユーザーC: ["1", "2", "3"]
149
+ [28] pry(main)> User.find(2).language_ids
150
+
151
+ User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
152
+
153
+ (0.8ms) SELECT `languages`.`id` FROM `languages` INNER JOIN `user_languages` ON `languages`.`id` = `user_languages`.`language_id` WHERE `user_languages`.`user_id` = 2
154
+
155
+ => [1, 2]
156
+
157
+
158
+
159
+ [29] pry(main)> User.find(3).language_ids
160
+
161
+ User Load (2.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 3 LIMIT 1
162
+
163
+ (2.3ms) SELECT `languages`.`id` FROM `languages` INNER JOIN `user_languages` ON `languages`.`id` = `user_languages`.`language_id` WHERE `user_languages`.`user_id` = 3
164
+
165
+ => [1, 2, 3]
166
+
167
+ ```
142
168
 
143
169
 
144
170