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

質問編集履歴

3

解決時のソースと検証結果を追記

2020/05/16 01:49

投稿

_Taturon_
_Taturon_

スコア17

title CHANGED
File without changes
body CHANGED
@@ -149,7 +149,7 @@
149
149
 
150
150
  初歩的な質問ですが、どなたかご回答の程、お願い申し上げます。
151
151
 
152
- ### 追記1:sourceモデルに既出のデータがあってもそれと紐付けられません
152
+ ### 追記1sourceモデルに既出のデータがあってもそれと紐付けられません
153
153
  次のように実装することで、関連付けたデータの保存はできるようになりました。ありがとうございます。
154
154
  ```erb
155
155
  <!--フォームパーシャル-->
@@ -235,4 +235,78 @@
235
235
  #<SourceMap id: 1, memo_id: 1, source_id: 1, created_at: "2020-05-15 22:31:03", updated_at: "2020-05-15 22:31:03">,
236
236
  #<SourceMap id: 2, memo_id: 2, source_id: 2, created_at: "2020-05-15 22:31:11", updated_at: "2020-05-15 22:31:11">]>
237
237
  ```
238
- おそらく```@memo.sources.find_or_initialize_by```としているので、sourceモデル全体から```find_by```しているのではなく、関連付けられたsourceから```find_by```してしまっているのが原因と思うのですが、解決方法が分かりません。何かアドバイスを頂けないでしょうか?
238
+ おそらく```@memo.sources.find_or_initialize_by```としているので、sourceモデル全体から```find_by```しているのではなく、関連付けられたsourceから```find_by```してしまっているのが原因と思うのですが、解決方法が分かりません。何かアドバイスを頂けないでしょうか?
239
+
240
+ ### 追記2:解決しました
241
+ winterboumさんのアドバイス通り、下記のように実装することで、重複しているurlはそのままに新規のみ保存できるようになりました。
242
+ ありがとうございました!
243
+ ```rb
244
+ #memosコントローラー
245
+ class MemosController < ApplicationController
246
+
247
+  ・
248
+  ・
249
+  ・
250
+
251
+ def new
252
+ @memo = Memo.new
253
+ @source = @memo.sources.build
254
+ end
255
+
256
+ def create
257
+ @memo = Memo.new(memo_params.slice(:word, :content, :synonym, :tag_list))
258
+ if @memo.save
259
+ @source = Source.find_or_create_by(url: memo_params[:url])
260
+ @memo.sources << @source
261
+ flash[:notice] = "新しいMemoを作成しました!"
262
+ redirect_to root_url
263
+ else
264
+ flash.now[:alert] = "無効な送信です"
265
+ render :new
266
+ end
267
+ end
268
+
269
+  ・
270
+  ・
271
+  ・
272
+
273
+ private
274
+
275
+ def memo_params
276
+ params.require(:memo).permit(
277
+ :word,
278
+ :content,
279
+ :synonym,
280
+ :tag_list,
281
+ :url
282
+ )
283
+ end
284
+
285
+ end
286
+ ```
287
+ ```console
288
+ 異なるmemoに同じurlを関連付けて保存した場合
289
+ > SourceMap.all
290
+ SourceMap Load (0.5ms) SELECT "source_maps".* FROM "source_maps" LIMIT ? [["LIMIT", 11]]
291
+ => #<ActiveRecord::Relation [
292
+ #<SourceMap id: 1, memo_id: 1, source_id: 1, created_at: "2020-05-16 01:35:29", updated_at: "2020-05-16 01:35:29">,
293
+ #<SourceMap id: 2, memo_id: 2, source_id: 1, created_at: "2020-05-16 01:35:38", updated_at: "2020-05-16 01:35:38">]>
294
+ > Source.all
295
+ (1.0ms) SELECT sqlite_version(*)
296
+ Source Load (0.4ms) SELECT "sources".* FROM "sources" LIMIT ? [["LIMIT", 11]]
297
+ => #<ActiveRecord::Relation [
298
+ #<Source id: 1, url: "https://rails.densan-labs.net/form/relation_regist...", created_at: "2020-05-16 01:35:29", updated_at: "2020-05-16 01:35:29">]>
299
+
300
+ 続けて異なるmemoを異なるurlで関連付けて保存した場合
301
+ > SourceMap.all
302
+ SourceMap Load (0.2ms) SELECT "source_maps".* FROM "source_maps" LIMIT ? [["LIMIT", 11]]
303
+ => #<ActiveRecord::Relation [
304
+ #<SourceMap id: 1, memo_id: 1, source_id: 1, created_at: "2020-05-16 01:35:29", updated_at: "2020-05-16 01:35:29">,
305
+ #<SourceMap id: 2, memo_id: 2, source_id: 1, created_at: "2020-05-16 01:35:38", updated_at: "2020-05-16 01:35:38">,
306
+ #<SourceMap id: 3, memo_id: 3, source_id: 2, created_at: "2020-05-16 01:37:04", updated_at: "2020-05-16 01:37:04">]>
307
+ > Source.all
308
+ Source Load (0.2ms) SELECT "sources".* FROM "sources" LIMIT ? [["LIMIT", 11]]
309
+ => #<ActiveRecord::Relation [
310
+ #<Source id: 1, url: "https://rails.densan-labs.net/form/relation_regist...", created_at: "2020-05-16 01:35:29", updated_at: "2020-05-16 01:35:29">,
311
+ #<Source id: 2, url: "https://teratail.com/questions/261655#", created_at: "2020-05-16 01:37:04", updated_at: "2020-05-16 01:37:04">]>
312
+ ```

2

誤字を修正

2020/05/16 01:49

投稿

_Taturon_
_Taturon_

スコア17

title CHANGED
File without changes
body CHANGED
@@ -215,7 +215,7 @@
215
215
  ```
216
216
  しかし、find_or_initialize_byを使用しても、既出のurlがあってもそれと紐付けられず、同じurlがsourceモデルに新規保存されそちらと紐付けられてしまいます。
217
217
  ```console
218
- 以下フォームから同じ異なるmemoに対し同じurlを登録した場合のモデル内データ
218
+ 以下フォームから異なるmemoに対し同じurlを登録した場合のモデル内データ
219
219
 
220
220
  同じurlであってもfind_byされずに新規登録されてしまう
221
221
  > Source.all
@@ -235,4 +235,4 @@
235
235
  #<SourceMap id: 1, memo_id: 1, source_id: 1, created_at: "2020-05-15 22:31:03", updated_at: "2020-05-15 22:31:03">,
236
236
  #<SourceMap id: 2, memo_id: 2, source_id: 2, created_at: "2020-05-15 22:31:11", updated_at: "2020-05-15 22:31:11">]>
237
237
  ```
238
- おそらく```@memo.sources.find_or_initialize_by```としているので、sourceモデル全体から```find_by```しているのではなく、関連付けられたsourceから```find_by```してしまっているのが原因と思うのですが、解決方法が分かりません。
238
+ おそらく```@memo.sources.find_or_initialize_by```としているので、sourceモデル全体から```find_by```しているのではなく、関連付けられたsourceから```find_by```してしまっているのが原因と思うのですが、解決方法が分かりません。何かアドバイスを頂けないでしょうか?

1

関連付けに関して追記しました

2020/05/15 23:04

投稿

_Taturon_
_Taturon_

スコア17

title CHANGED
File without changes
body CHANGED
@@ -147,4 +147,92 @@
147
147
 
148
148
  他にも色々試しましたが、どうも上手くsourceモデルとsource_mapモデルにデータが保存されません。
149
149
 
150
- 初歩的な質問ですが、どなたかご回答の程、お願い申し上げます。
150
+ 初歩的な質問ですが、どなたかご回答の程、お願い申し上げます。
151
+
152
+ ### 追記1:sourceモデルに既出のデータがあってもそれと紐付けられません
153
+ 次のように実装することで、関連付けたデータの保存はできるようになりました。ありがとうございます。
154
+ ```erb
155
+ <!--フォームパーシャル-->
156
+ <%= form_with model: @memo, local: true do |f| %>
157
+
158
+  ・
159
+  ・
160
+  ・
161
+
162
+ <div class="form-group">
163
+ <%= f.label :url, "出典(URL)" %>
164
+ <%= f.url_field :url, class: "form-control",
165
+ placeholder: "出典元のURLを記入して下さい" %>
166
+ </div>
167
+ <div class="form-group">
168
+ <%= f.submit yield(:btn_message), class: "btn btn-success btn-lg btn-block" %>
169
+ </div>
170
+ <% end %>
171
+ ```
172
+ ```rb
173
+ #memosコントローラー
174
+ class MemosController < ApplicationController
175
+
176
+  ・
177
+  ・
178
+  ・
179
+
180
+ def new
181
+ @memo = Memo.new
182
+ @source = @memo.sources.build
183
+ end
184
+
185
+ def create
186
+ @memo = Memo.new(memo_params.slice(:word, :content, :synonym, :tag_list))
187
+ if @memo.save
188
+ @source = @memo.sources.find_or_initialize_by(url: memo_params[:url])
189
+ @memo.sources << @source
190
+ flash[:notice] = "新しいMemoを作成しました!"
191
+ redirect_to root_url
192
+ else
193
+ flash.now[:alert] = "無効な送信です"
194
+ render :new
195
+ end
196
+ end
197
+
198
+  ・
199
+  ・
200
+  ・
201
+
202
+ private
203
+
204
+ def memo_params
205
+ params.require(:memo).permit(
206
+ :word,
207
+ :content,
208
+ :synonym,
209
+ :tag_list,
210
+ :url
211
+ )
212
+ end
213
+
214
+ end
215
+ ```
216
+ しかし、find_or_initialize_byを使用しても、既出のurlがあってもそれと紐付けられず、同じurlがsourceモデルに新規保存されそちらと紐付けられてしまいます。
217
+ ```console
218
+ 以下フォームから同じ異なるmemoに対し同じurlを登録した場合のモデル内データ
219
+
220
+ 同じurlであってもfind_byされずに新規登録されてしまう
221
+ > Source.all
222
+ (0.8ms) SELECT sqlite_version(*)
223
+ Source Load (0.5ms) SELECT "sources".* FROM "sources" LIMIT ? [["LIMIT", 11]]
224
+ => #<ActiveRecord::Relation [
225
+ #<Source id: 1, url: "https://rails.densan-labs.net/form/relation_regist...", created_at: "2020-05-15 22:31:03", updated_at: "2020-05-15 22:31:03">,
226
+ #<Source id: 2, url: "https://rails.densan-labs.net/form/relation_regist...", created_at: "2020-05-15 22:31:11", updated_at: "2020-05-15 22:31:11">]>
227
+
228
+ 関連付けも、本来なら
229
+ SourceMap id: 1, memo_id: 1, source_id: 1
230
+ SourceMap id: 1, memo_id: 2, source_id: 1
231
+ となって欲しいが、新規登録されたsource_id: 2と関連付けられてしまう
232
+ > SourceMap.all
233
+ SourceMap Load (0.2ms) SELECT "source_maps".* FROM "source_maps" LIMIT ? [["LIMIT", 11]]
234
+ => #<ActiveRecord::Relation [
235
+ #<SourceMap id: 1, memo_id: 1, source_id: 1, created_at: "2020-05-15 22:31:03", updated_at: "2020-05-15 22:31:03">,
236
+ #<SourceMap id: 2, memo_id: 2, source_id: 2, created_at: "2020-05-15 22:31:11", updated_at: "2020-05-15 22:31:11">]>
237
+ ```
238
+ おそらく```@memo.sources.find_or_initialize_by```としているので、sourceモデル全体から```find_by```しているのではなく、関連付けられたsourceから```find_by```してしまっているのが原因と思うのですが、解決方法が分かりません。