Ruby
Rails
初心者

【Rails】find_or_initialize_byメソッドを使ってインスタンスを作成する時のポイント

現在、amazonAPIを利用した口コミの共有サービスを作成中です。

その中で、「商品を検索し表示させる」という処理があるのですが、その際に役立ったfind_or_initialize_byメソッドについて簡単に整理します。


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を使用しています。


products_controller.rb

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



_products.html.erb

<!--商品登録削除ボタン-->

<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を利用して情報取得→整形しインスタンス作成」のようなケースで役立つことがわかりました。