現在行っていること
現在、既存サービスにユーザーが任意に通知のあり・なしを管理できる機能を実装しています。
以下のようなモデルの作成を行いました。
テーブル設計
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にしている人を通知対象から除外する方向での実装)」など、色々と考えていますが、知見を持っている方に一度意見を伺いたく質問させていただきました。
どうぞ、よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/05/25 10:34