注記
この記事の投稿者はRuby on Rails初学者であり、自身の学習の備忘録目的で記事投稿を行なっております。
情報の正確さには最大限注意をしておりますが、もし誤り等がございましたらお知らせいただけますと幸いです。
アクセスしていただきありがとうございます。
Rails初学者です。
学習の一環として記事投稿アプリを作成中です!
躓いたところについてアウトプットしていきたいと思います。
修正やご意見ありましたらどうぞお聞かせください。(何卒)
状況
- Ruby on Railsで記事投稿アプリを作成中。
- ユーザーが記事を投稿する際に、タグを入力し記事に反映させる機能を実装中である。
- タグ同士を , (カンマ)で区切り、複数のタグを保存できる機能を作している。
やりたいこと
登録しようとしているタグが重複している場合、重複して保存されないようにしたい
書いてみたコード
class Post < ApplicationRecord
# ... (中略) ...
# 入力フォームで入力されたタグを連結する
def tag_list
tags.map(&:name).join(', ')
end
# タグを保存する際に重複を削除する
def tag_list=(names)
self.tags = names.split(',').map do |name|
Tag.where(name: name.strip).first_or_create!
end
end
end
Tag.where(name: name.strip).first_or_create!
の部分で、
まずデータベースに対して name.strip
という名前のタグを検索し、
見つからなければ新しく作成する処理。
実行結果
タグの保存自体はできたが、重複したタグはそのまま(複数)登録されてしまった。
修正後コード
class Post < ApplicationRecord
# ... (中略) ...
# 入力フォームで入力されたタグを連結する
def tag_list
tags.map(&:name).join(', ')
end
# タグを保存する際に重複を削除する(変更箇所)
def tag_list=(tags)
unique_tags = tags.split(',').map(&:strip).uniq
self.tags = unique_tags.map { |tag_name| Tag.find_or_create_by(name: tag_name) }
end
実行結果
タグが重複している場合、重複したタグは削除され、同名のタグ一つのみが登録されていることが確認できた。
なぜ最初のコードではうまくいかなかったのか?
修正前のコードでは、最初の呼び出しで作成されたタグがデータベースに反映される前に、2回目以降の呼び出しが行われる可能性があった。(do
ブロックの中)
そのため、同じ名前のタグに対して first_or_create!
メソッドが複数回実行され、結果として同じ名前のタグが複数作成されていたと考えられる。
一方、修正したコードでは、まず最初に与えられたタグを適切に処理してからデータベースの検索や新規作成を行うため、同じ名前のタグに対して重複した処理が発生しないようになっている。
まとめ
ロジック的に正しくても意図した挙動をするのか、実際に動かして検証する必要があると感じた。頑張る!