Action Mailerを使って、アプリに登録されている全ユーザにメールを送信するという実装をしたのですが、メールが飛ばないというような事がありました。
実際のコードがこちらです!
@posts = Post.yesterday_liked_ranking_top_ten
mail(to: User.pluck(:email).delete(''), subject: default_i18n_subject)
# emailを登録していないユーザもいるので、空であれば削除する
emailを登録していないユーザもいるので、pluckして取得した値のうち、空文字は削除するといった実装です。
この時点で既にお気づきの方もいらっしゃると思いますが、この記述だとmailのto引数には空を渡してしまうのです。
実際にコンソールで挙動を確認してみましょう!
>> emails = User.pluck(:email)
User Pluck (1.0ms) SELECT "users"."email" FROM "users"
=> ["", "", "hattsuan@example.com"]
>> emails.delete('') # deleteメソッドの戻り値は空
=> ""
>> emails # 配列からはちゃんと空文字は削除されている
=> ["hattsuan@example.com"]
deleteのリファレンスです。
https://docs.ruby-lang.org/ja/latest/method/Array/i/delete.html
コンソールでdeleteメソッドを実際に使って問題なかったので、メールが飛ばない原因に気付くまでかなり時間を要しました。
今回の反省点は2つあり、1つ目は、メール作成後のテストをプレビュー使って問題ないことを確認しただけだったことで、送信できるかどうかのテストが出来ていなかったことです。mailのspecを書くことも習慣化したいと思います。
2つ目は、コンソールで試した内容と、実際プロジェクトのコードに記述した内容がイコールになっていなかったことです。
学びがあって良かったと思います!
ちなみにですが、pluckとwhereを組み合わせられるみたいなので、pluckする前にwhereすると、Active Recordのメソッドだけで完結できるので、より読みやすいと思います。
>> User.where.not(email: '').pluck(:email)
User Pluck (0.3ms) SELECT "users"."email" FROM "users" WHERE "users"."email" != $1 [["email", ""]]
=> ["hattsuan@example.com"]
コードの行数も減り、こっちの方が良いですね。
以上です。読んでいただきありがとうございました。
-追記-
delete_ifだと、戻り値は削除した後の配列の値でした。
https://docs.ruby-lang.org/ja/latest/method/Array/i/delete.html
>> emails.delete_if{|email| email==''}
=> ["hattsuan@example.com"]