1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

deleteメソッドの戻り値は、最後に削除した要素の値である

Last updated at Posted at 2024-07-18

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"]
1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?