10
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Spreeに関連商品表示機能を追加する

Last updated at Posted at 2015-11-06

Spreeにリコメンド(関連商品)を表示する機能を追加しましょう。

このエクステンションを使用します。

spree_related_products

エクステンションのインストール

Githubに書いてあるとおりです。まずはGemfileに以下を記載。branchの部分はSpreeのバージョンにあわせて書き換えてください。

gem 'spree_related_products', github: 'spree-contrib/spree_related_products', branch: '3-0-stable'

次にこれらのコマンドを実行。

bundle install
bundle exec rails g spree_related_products:install
bundle exec rake db:migrate

以上です。rails sでサーバーを起動してみましょう。

管理者画面の商品ページに新しく「Related product」タブが登場し、こんな感じで関連商品の設定ができるようになります。

relation.png

ただ他のエクステンション等と異なり、このエクステンションにはデフォルトのビューが作られていません。

管理画面は上の写真のようにインストール後すぐに使えるようになるのですが、エンドユーザー向けのページはコードを書く必要があるので注意してください。

RelationモデルとRelationTypeモデルについて

このエクステンションを使うと、関連する商品だけでなく、その関係性まで一緒に定義できるなど高機能で融通の効く設計となっています。その反面、概念が少々わかりにくいのでちょっとだけ解説しておきます。

このエクステンションで新しく作るモデルは2つ。Spree::RelationTypeSpree::Relationです。

商品同士の関連を定義するのはSpree::Relationで、親商品の外部キー:relatable_idと子商品の外部キー:related_to_idがあります。関係性自体は多対多の自己参照モデルですね。

さらにSpree::Relationは、外部キーrelation_type_idを持ち、Spree::RelationTypeに一対多でbelongs_toします。そしてSpree::RelationTypeは、アクセサリー、類似商品、セット商品など商品同士の関連性を定義しています。

つまり、ひとつの商品がアクセサリーとしての関連商品、類似商品としての関連商品などなど、タイプの異なる複数の関連商品を持つ構造になります。

ビューの作成

とりあえずさくっと表示だけしてみましょう。

partial挿入用のDefaceを作成。

app/overrides/add_relations_to_product.rb
Deface::Override.new(
  virtual_path: 'spree/products/show',
  name: 'add_relations',
  insert_after: '[data-hook="product_properties"]',
  partial: 'spree/shared/relations'
)

partialファイルを作成。

app/views/spree/_shared/_relations.html.erb
<h3 class="product-section-title"><%= Spree.t(:related_products) %></h3>
<ul class="list-group">
  <% @product.relations.each do |r| %>
    <li class="list-group-item"><%= link_to r.related_to.name, r.related_to %></li>
  <% end -%>
</ul>

表示されました!

relate2.png

なお、@product.relationsのメソッド名はRelationTypeのタイプ名をそのまま使用できるみたいです。例えば'Accessories'といったタイプ名にしておくと、@product.accessoriesといったメソッドで表示できちゃうようですね。

日本語化

どのみちビューは自分で作らなければならないので無くても困ることはなさそうですが、一応日本語用のロケールファイルを作りましたので公開しておきます。

そのままconfig/localesに設置するだけで管理画面が翻訳されるかと思います。

spree_related_products_ja.yml

ついでに

なお節々のカラムからわかるように、このエクステンションのRelationはポリモーフィックでSpree::Product以外のモデルも扱えるようになってるみたいです。私も詳しく検証してないのですが、よくわからない場合は気にせず使ってしまって大丈夫そうですね。

ハマった点

原因はわからないのですが、特定の条件下で関連商品設定画面を開こうとするとNoMethodError in Spree::Admin::Products#relatedが発生することがあるようです。

undefined method `empty?' for nil:NilClass
Extracted source (around line #6):       
4 <%= csrf_meta_tag %>
5 
6 <% if @relation_types.empty? %>
7   <div class="alert alert-warning no-objects-found">
8     <%= Spree.t(:no_relation_types) %>
9   </div>

以下のGithub issueを参考に修正しました。

undefined method `empty?' for nil:NilClass #118

Spreeアプリケーション内に下記のファイルを設置すると動きます。

app/controllers/spree/admin/products_controller_decorator.rb
Spree::Admin::ProductsController.class_eval do
  def related
    load_resource
    @relation_types = Spree::Product.relation_types
  end
end
10
13
0

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
10
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?