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

質問編集履歴

4

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

2021/03/18 03:23

投稿

punchan36
punchan36

スコア105

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を書き加えました。

2021/03/18 03:23

投稿

punchan36
punchan36

スコア105

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 に置き換えました。

2021/03/12 08:56

投稿

punchan36
punchan36

スコア105

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 :sex, "Male", :checked => params[:sex] == ("Male") %>Male
28
+ <%= f.radio_button :gender, "Male", :checked => params[:gender] == ("Male") %>Male
29
- <%= f.radio_button :sex, "Female", :checked => params[:sex] == ("Female") %>Female
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
- **users_index.html.erb**
40
+ **users_controller.rb**
41
41
  ```ここに言語名を入力
42
42
  def index
43
- if params[:name].present? || params[:introduction].present? || params[:sex].present? || params[:language_ids].present?
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 sex LIKE ? AND language LIKE ?',
44
+ @users = User.where(['name LIKE ? AND introduction LIKE ? AND gender LIKE ? AND language LIKE ?',
45
- "%#{params[:name]}%", "%#{params[:introduction]}%", "#{params[:sex]}%", "%#{params[:language_ids]}%"])
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 の内容を元に編集致しました。

2021/03/11 07:55

投稿

punchan36
punchan36

スコア105

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
- 各ユーザーの言語情報は以下の様に保存されていると思いので、なぜこれでユーザーCがヒットにならないのかが分かりません…。
67
+ 各ユーザーの言語情報は以下の様に保存されておりしたので、なぜこれでユーザーCがヒットにならないのかが分かりません…。
68
68
 
69
- - ユーザーA: ["1"]
69
+ ```
70
- - ユーザーB: ["1", "2"]
70
+ [27] pry(main)> User.find(1).language_ids
71
- - ユーザーC: ["1", "2", "3"]
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/ツールのバージョンなど)