現在、amazonAPIを利用した口コミの共有サービスを作成中です。
その中で、「商品を検索し表示させる」という処理があるのですが、その際に役立ったfind_or_initialize_by
メソッドについて簡単に整理します。
- 参考記事 Railsガイド
#find_or_initialize_byメソッドとは
find_or_initialize_byメソッド
とは、条件に合致したインスタンスがデータベースに保存されているかどうかをチェックしています。
この際、
- データベースに保存されている場合は
find
メソッド - データベースに保存されていない場合は'new'メソッド
として、インスタンスの状況によって適用されるメソッドが異なることがポイントです。インスタンスが保存されている場合、findメソッドが適用されるのでインスタンスに保存済みのデータ(idなど)を含めることができます。
インスタンス = persisted?
やインスタンス = new_record?
でデータベースの保存状況を真偽値で取得できます。
#find_or_initialize_byメソッドの使い道
前述の通り、find_or_initialize_by
は条件分岐がポイントとなるので、データベースの保存状況でインスタンスに変化を与えたい場合に有用となります。
例えば私の場合ですと、APIから商品データを取得し一覧表示しています。
その際に、データベース保存済みなら「商品削除ボタン」を表示、データベースに保存していない新規のインスタンスなら「商品登録ボタン」を表示したいケースで、find_or_initialize_by
を使用しています。
def create
@product = Product.find_or_initialize_by(asin: params[:product_asin])
unless @product.persisted?
# @product が保存されていない場合、先に @product を保存する
products = Amazon::Ecs.item_lookup(
params[:product_asin],
response_group: 'Medium',
country: 'jp'
)
products.items.each do |item|
@product = Product.new(
title: item.get('ItemAttributes/Title'),
image_url: item.get('LargeImage/URL'),
url: item.get('DetailPageURL'),
asin: item.get('ASIN'),
brand_amazon_name: item.get('ItemAttributes/Brand'),
price: item.get('OfferSummary/LowestNewPrice/Amount'),
)
@product.save
end
end
end
<!--商品登録削除ボタン-->
<div class="buttons text-center">
<% if product.persisted? %>
<%= form_tag(product_path(product.id), method: :delete) do %>
<%= hidden_field_tag :product_id, product.id %>
<%= submit_tag '削除', class: 'btn btn-danger' %>
<% end %>
<% else %>
<%= form_tag(products_path) do %>
<%= hidden_field_tag :product_asin, product.asin %>
<%= submit_tag '登録', class: 'btn btn-primary' %>
<% end %>
<% end %>
#(+α)find_or_create_byメソッドについて
find_or_create_by
メソッドは、find_or_initialize_by
と似た内容のメソッドなので、今後のために簡単に整理。
条件に合致したインスタンスがデータベースに保存されているかどうかをチェックしている点は、両者とも同じです。
その際に、find_or_create_by
メソッドは、
- データベースに保存されている場合は
find
メソッド - データベースに保存されていない場合は**'create'**メソッド
となることがポイントです。「データベースに保存されていない場合は**'create'**メソッド」となるのですね。
条件に合致した情報をゴリゴリとデータベースに保存していくというケースに適しているのでしょう。
#まとめ
find_or_initialize_byメソッドは、「APIを利用して情報取得→整形しインスタンス作成」のようなケースで役立つことがわかりました。