質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1334閲覧

ある既存モデルに関連付けられる新規モデルのレコードを一気に作成する方法

azuno_mix

総合スコア71

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2017/05/25 05:19

編集2017/05/25 06:03

現在行っていること

現在、既存サービスにユーザーが任意に通知のあり・なしを管理できる機能を実装しています。
以下のようなモデルの作成を行いました。

テーブル設計

UserNotify.rb

1create_table "user_notifies", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" do |t| 2 t.integer "user_id", null: false 3 t.boolean "a_notify", default: true, null: false 4 t.boolean "b_notify", default: true, null: false 5 t.boolean "c_notify", default: true, null: false 6 t.datetime "created_at", null: false 7 t.datetime "updated_at", null: false 8 t.index ["user_id"], name: "index_user_notifies_on_user_id", using: :btree 9end

モデル

User.rb

1class User < ApplicationRecord 2 has_one :user_notify, dependent: :destroy, class_name: UserNotify 3 after_create :create_user_notify, unless: proc { |user| user.user_notify } 4end

UserNotify.rb

1class UserNotify < ApplicationRecord 2 belongs_to :user, class_name: User 3end

問題となっていること

このような実装で、デプロイしてみたところ、設定画面で404が表示されるようになりました。

log

1Processing by NotifySettingsController#edit as HTML 2 User Load (6.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 5 ORDER BY `users`.`id` ASC LIMIT 1 3 UserNotify Load (5.9ms) SELECT `user_notifies`.* FROM `user_notifies` WHERE `user_notifies`.`user_id` = 5 LIMIT 1 4 5Completed 404 Not Found in 38ms (ActiveRecord: 12.6ms) 6ActiveRecord::RecordNotFound (Couldn't find UserNotify)

原因としては、この実装以前に作成されたUserはUserNotifyのレコードを持っていないので、インスタンス取得が失敗し404となっているのかと思います。

notify_settings_controller.rb

1def set_instance 2 @user_notify = UserNotify.find_by!(user_id: current_user.id) 3end

この問題自体は、以下のようにレコードがなければ作成するといったことで回避することはできると思います。

notify_settings_controller.rb

1def set_instance 2 @user_notify = UserNotify.find_or_create_by!(user_id: current_user.id) 3end

実際、デバッグしてみたところ、うまくいきました。

log

1Processing by NotifySettingsController#edit as HTML 2 User Load (15.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 5 ORDER BY `users`.`id` ASC LIMIT 1 3 UserNotify Load (2.2ms) SELECT `user_notifies`.* FROM `user_notifies` WHERE `user_notifies`.`user_id` = 5 LIMIT 1 4 (2.8ms) BEGIN 5 User Load (1.3ms) SELECT `\users`.* FROM `users` WHERE `users`.`id` = 5 LIMIT 1 6 SQL (14.6ms) INSERT INTO `user_notifies` (`user_id`, `created_at`, `updated_at`) VALUES (5, '2017-05-25 05:06:53', '2017-05-25 05:06:53') 7 (30.3ms) COMMIT 8 9... 10 11Completed 200 OK in 1745ms (Views: 1393.2ms | ActiveRecord: 140.3ms)

解決したいこと

一方で通知設定を用いてメールを送信するか判断しているMailer側の実装は以下のようになっています。

class NotificationMailer < ApplicationMailer def aaa_notify(user) users = User.joins(:user_notify).where(user_notifies: { aaa_notify: true }) return if users.empty? mail bcc: users.pluck(:email) end end

このメイラーの実装だと、UserNotifyモデルを含んだ実装後に新規登録したユーザであればレコード作成時(after_create)でUserNotifyにも通知設定レコードが作成されますが、既存ユーザの場合、この通知設定のページにアクセスしない限り、UserNotifyにレコードが存在しないため、無条件で通知されない(whereでの絞込に該当しない)問題があるかと思います。

こういった場合、「既存ユーザのUserNotifyを何らかのクエリを叩くことでレコードを一気に作成するか」「Mailerの実装を工夫する(UserNotifyで通知をfalseにしている人を通知対象から除外する方向での実装)」など、色々と考えていますが、知見を持っている方に一度意見を伺いたく質問させていただきました。

どうぞ、よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

私なら、
「既存ユーザのUserNotifyを何らかのクエリを叩くことでレコードを一気に作成する」
を選びますね。

今後、UserNotifyの存在可否を考慮しながら開発するのは面倒ですし、バグの温床にもなりますしね。。。

クエリ叩かなくても、コンソールから既存ユーザーに対して、create_user_notifyを実行(privateならuser.sendで)すればいいだけの話ですし。

投稿2017/05/25 07:59

h_daido

総合スコア824

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

azuno_mix

2017/05/25 10:34

h_daidoさん ご意見、ありがとうございます! > UserNotifyの存在可否を考慮しながら開発するのは面倒ですし、バグの温床にもなります 確かにその通りだと感じます。今後の開発を考えていくと一発コンソールなどでUserNotifyを作成した方がコストもリスクも低いかもしれません! ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問