SolidusでECサイトを作る際の方法と考え方


独自のお作法など、はじめての人にはとっつくにくいフレームワークだと思うので導入の部分をまとめてみました。

なお、ここでご紹介している内容はバージョン1系統のものを前提として解説しています。Solidusは活発な開発が行われている分、バージョンアップに際して大幅な機能改変があることもしばしばです。

個人情報等も含むシステムになるかと思いますので、この記事は参考程度に、コーディングやデプロイに関してはご自身の責任で細心の注意を払って行ってくださいね。

Solidusとは

SolidusはRuby on Rails製のオープンソースECパッケージです。

solidusio/solidus

前身はSpreeというRailsフレームワークです。Solidusはまだ公開されてから間もないこともあり、Spreeの面影を強く残しています。困ったことがあったらSolidusでググるよりSpreeでググったほうがヒントも見つかりやすいかもしれません。

インストールの方法

こちらの記事を参考にどうぞ

Spreeの後継ECシステム、Solidusのインストールメモ

Solidusのインストール直後は空っぽのRailsプロジェクトができあがります。ここに必要なファイルを設置していくことでカスタマイズを進めていくことになります。

インストールするGemはSolidus本体以外に、solidus_auth_devise(DeviseをSolidus向けに調整した認証用Gem)もインストールされます。自分でコードを書いてカスタマイズする他に、既に公開されているエクステンションGemをインストールすることで機能を追加することもできます。devise以外にもたくさんのエクステンションがあるのでGithubを見てみてください。

ただまだSolidusは登場してから日が浅く、Soludusの前身であるSpree用のエクステンションをSolidus向けに調整して使うということになるかもしれません。SolidusはSpreeのフォークなので、Spree用のエクステンションも少しコードをいじるだけで遜色なく使えたりします。

Solidusのディレクトリ構造と仕組み

どうやって動いているか

上でも書いたとおり、インストールした直後のSolidusは空っぽのRailsプロジェクトに過ぎませんが、rails sするとちゃんとECサイトを表示されています。

一度ルートファイルを見てみましょう。

config/route.rb
Rails.application.routes.draw do
  mount Spree::Core::Engine, :at => '/'
end

ルートパスにSoludusのパスをマウントしていますね。ディレクトリに何もファイルがないのにECサイトが表示されるのは、GemとしてインストールしたSoludusが仕事をしてくれているためです。

このRailsディレクトリにそれぞれの機能に対応したコードを配置していくことでカスタマイズしたECサイトを構築することができるわけですね。

しかしそれにはSolidusのディレクトリ構造を事前にしっかり把握しておくことが必須です。ということで次にSolidusのディレクトリ構造を見てゆきましょう。

Solidusディレクトリ構造

Solidusを扱ううえで押さえておくべき3つのディレクトリがありますのでそれぞれご説明します。

/frontend

お客さん向けのページを構成するコードが格納されています。主にはコントローラとビューです。商品詳細ページ、カテゴリ(商品一覧)ページ、チェックアウト画面、トップページなどが格納されています。

例えば商品詳細ページは以下のビューとコントローラから構成されているわけです。

solidus/frontend/app/views/spree/products/show.html.erb

solidus/frontend/app/controllers/spree/products_controller.rb

/backend

管理者向けのページを構成するコードが格納されてます。こちらも主にはコントローラとビューです。

商品や注文を処理する機能のページなので、開くために認証が必要なページたちです。管理者向けページの見た目、挙動をいじりたい場合にはこのディレクトリをチェックしましょう。

例えば注文一覧画面を構成しているのは下記のビューとコントローラです。

solidus/backend/app/views/spree/admin/orders/index.html.erb

solidus/backend/app/controllers/spree/admin/orders_controller.rb

管理者向けページのほとんどはSpree::Admin::BaseControllerを継承しており、このクラスが認証機能を司っているわけですね。

/core

主にはモデルが格納されています。既存のモデルに機能を追加したい場合にはここをチェックします。

例えば商品のモデルはここにあります。

solidus/core/app/models/spree/product.rb

Solidusのモデリング

Solidusに標準で組み込まれているモデルのほとんどはその名前のままの役割を担っていますが、商習慣の違いから直感的に理解しずらいモデリングもいくつか見受けられます。

ざっくりではありますが、Solidusの全体像を理解するうえで重要となりそうなモデルをいくつか解説しておきます。

Spree::Taxonomy / Spree::Taxon

商品カテゴリーは、SolidusではSpree::TaxonomyとSpree::Taxonという2つのモデルの組み合わせによって構成されます。TaxonomyとTaxonは、日本のECサイトを運営するうえではあまり聞き慣れない言葉ですが、「分類」といったような意味です。

直感的にわかりにくいのですが、これらを使うことでカテゴリーに限らずブランドやメーカー、タグなどあらゆる種類の商品分類を作ることができます。

分類の1単位がTaxon、分類が所属するツリー名をTaxonomyとして扱います。具体例をあげると「カテゴリー > 家電 > テレビ」といったようなカテゴリ構造を作る場合、Taxonomyが「カテゴリー」、Taxonが「家電」、「テレビ」の部分です。

ややこしいなと感じるのですが、これを活用すれば「タグ > 40インチ」「タグ > 4Kテレビ」みたいなことも実現できますよね。

Taxonはネストでき、商品とTaxonは多対多のリレーションをとります。(SQLアンチパターンの1つであるナイーブツリーの構造をとっています。木構造が膨大になってくると処理速度に影響を及ぼすかもしれませんのでご注意ください)

Spree::Product

商品です。これは説明不要ですね。なおProductは次に説明するVariantと密接な関係があります。

Spree::Variant

Spree::Variantは商品バリエーションを表しています。商品バリエーションとは、カラーバリエーションや(服の)サイズなど、同一商品ながら複数の販売パターンのことを表しています。ProductとVariantが1対多の関係を持ちます。

なおProductを作成すると必ずマスターとなるVariantが1つ作成されます。マスターのVariantはis_masterのカラムがtrueとなります。カラバリなどを追加していくと、その数だけマスターでないVariantが追加されていくという仕組みになっています。

ちなみにこれらのバリエーションの設定はSpree::OptionTypeSpree::OptionValueで実装されています。

(注) カラバリ有りのProductを注文する場合、line_itemsはマスターでないVariantを参照するためその存在を認識しずらいのですが、カラバリ有りのProductにもマスターVariantは存在しています。存在を忘れていると意外なところでハマるので頭の片隅においておくと良さそうです。

Spree::Order

注文です。注文番号や顧客メールアドレスなどが登録されています。注文者名や注文者住所はSpree::Addressというクラスに保存されるためOrder内には保存されません。

商品がカートに入ると自動でOrderが作成され、stateというカラムで'payment'や'confirm'といった注文ステータスが管理される仕組みになっています。

Spree::LineItem

カートに入っている商品です。商品に対して1対1で対応し、単価や数量などのカラムを持ちます。

なお、ProductでなくVariantに紐付いていることに注意しましょう。

カスタマイズ

Solidusは、インストールしただけでは基本的な機能しか備えていません。カスタマイズをしないのであればわざわざSolidusを使用する価値は全く無いでしょう。ここからはSolidusをカスタマイズする考え方と具体的な方法を書いてゆきます。

カスタマイズの基本的な考え方

Solidusの各機能に対応したソースをRailsプロジェクト内に配置してゆくといった手法となります。

ただ、なにも考えずにファイルをドカドカ配置してゆくとソースが極めて煩雑になり大変メンテナンス性の低いコードが完成するでしょう。またSolidus自身も頻繁にアップデートを繰り返していることから、カスタマイズするためのコードはSoludus本体とは疎結合にしてゆく必要があります。

Solidusはカスタマイズを前提としているプログラムですので、キレイにカスタマイズするための手法が用意されています。次は具体的なカスタマイズ方法について見てゆきます。

ビューのカスタマイズ

ビューのカスタマイズ方法は2通りの方法があります。ビューファイルを丸ごと置き換える方法と、DefaceというGemを使う方法の2つです。

本家ドキュメントも掲載しておきます。

VIEW CUSTOMIZATION - DEVELOPER GUIDE | SPREE COMMERCE

ビューファイルによるカスタマイズ

一番直感的にわかりやすい方法ですね。ビューファイルを丸ごと置き換えてしまう方法です。

例えば商品詳細ページを置き換えたい場合には、solidus/frontend/app/views/spree/products/show.html.erbをコピーしてRailsプロジェクトのapp/views/spree/products/show.html.erbに配置してあげましょう。あとはこのファイルに手を加えていくだけでOKです。

defaceによるカスタマイズ

Defaceとは、「◯◯◯の条件を満たすdomの次に◯◯◯を配置する」という記法のできるGemです。これを使うことでビューファイルを直接編集することなくサイトの見栄えを変更することができます。

DEFACE OVERRIDES - DEVELOPER GUIDE | SPREE COMMERCE

Solidus公式としてはビューの置き換えよりもDefaceによるカスタマイズを推奨しており、その理由はビューを丸ごと置換するよりもSolidus本体のアップデートに強いという理由を挙げています。

しかしながら、見栄えを大幅に変更する場合にはDefaceだけでビューを変更するのは骨の折れる作業です。ある程度Solidusをカスタマイズするつもりなら最初からビューの置き換えで進めてしまっても良いかもしれません。

モデルのカスタマイズ

モデルをカスタマイズする場合には専用のお作法があります。以下のような書式でファイルを配置してあげると機能追加ができます。

ファイル名の最後に_decorator.rbとつけ、ファイル内ではclass_evalを使ってモデルクラスを開きます。この場所でメソッドを定義したり、アソシエーションの宣言等、普通のActiverecordモデルの書式でコードを配置することができます。

app/models/spree/order_decorator.rb
Spree::Order.class_eval do
  has_many :foos

  def hoge
    return "hoge"
  end
...
end

コントローラのカスタマイズ

コントローラのカスタマイズもモデルと同様、decorator.rbclass_evalを使います。この場所で既存のメソッドの上書きや新しいアクションの定義をすることができます。

app/controllers/spree/orders_controller_decorator.rb
Spree::OrdersController.class_eval do
...
end

なおコントローラをカスタマイズする場合、既存のメソッドを丸ごと置き換えてしまうとSolidus本体のアップデートに弱くなったり、コードの見通しが立ちにくくなるのでbefore_action等のフィルタ処理で機能を追加してゆくのがおすすめです。

テストについて

公式ドキュメントの日本語訳です。

[日本語訳] TESTING SPREE APPLICATIONS

またSolidusのファクトリやヘルパーがそのまま使えます。この辺りに入っていますので、興味があれば見てみてください。

spec/rails_helper.rb
require 'spree/testing_support/factories'
require 'spree/testing_support/authorization_helpers'
require 'spree/testing_support/controller_requests'

最後に

以上です。

一度把握してしまえばなんということはないのですが、Solidus独自のお作法に加え、公開されているドキュメントもほとんどが英語で私自身Solidusの全体像を理解するまでにちょっと時間がかかったのでざっくりまとめさせていただきました。

また、Solidusは越境ECを前提に設計されており、例えば関税をはじめとした日本国内ECでは馴染みのない機能もたくさん含まれています。ビジネスによっては冗長な機能やデータベースをたくさん含むアプリケーションとなるでしょう。不要な機能は使わないor無効化していったほうが結果として身軽な設計になる場合もありますので、それも頭の片隅に置いておかないと開発現場に混乱をもたらすことにもなりかねないので注意しておいたほうが良いかもしれません。

もし不備や、これ追加したほうがいいよということがあればご指摘いただけますと幸いです。