DefaceでSolidusのデザインをカスタマイズ。でも結構面倒。

SolidusのViewはDefaceで書き換える

RailsのEC用オープンソースのSolidusはインストールしたまま使ってもなにも問題はないと思いますが、やはりサイトにはオリジナリティを出したいものです。

過去記事: 【Rails】Spreeの後継SolidusにStripeを使えばカード決済対応のオンラインストアが無料でつくれる

そのためにはViewをカスタマイズしなければなりません。Solidusの公式ではここでDefaceを使うように推奨しています。下記リンクはspreeのものですが、まあ同じなのでオーライとしておきます。いや、しておいてください。

spree: VIEW CUSTOMIZATION

Defaceで書き換えるメリット

Defaceを使うメリット、それは(色んな記事にも書かれていますが)Solidus本体のアップデートの影響を受けにくい。と、いうことです。

Defaceは、Viewファイルの指定された箇所を上書きするだけです。全く違う別のViewファイルを読み込ませる訳ではないので、Solidus側でロジックの変更があった時に挙動がおかしくなることが起こりにくくなります。そしてそうなった場合、Solidus本体の変更に合わせてViewファイルをまた書き換えないといけなくなります。

デメリット

デメリットはたったひとつです。このエントリーのタイトルにも書きましたが、ただただ面倒くさい。これに尽きます。

正直この面倒くささに耐えるぐらいなら、アップデート時の誤作動覚悟で完全に別のViewファイルを用意してもいいかなと思うぐらいです。

Defaceのお作法

GitHub: deface

newメソッドを使用して(下記参照)、上書きしたい場所を指定し、書き換えます。

Deface::Override.new(
  virtual_path: 'Defaceを実行するviewファイルのパス',
  name: 'なんでもよい',
  [Action名]: '書き換えたい要素',
  [Source]: '書き換える内容'
)

これを上書きしたい場所ひとつひとつに指定していきます。(はあ、面倒くさい)

Source

書き換える内容をここに記述します。指定方法は、「text」、「partial」、「template」、「cut」、「copy」です。

なかでもよく使うのは、text, partial、もしくはtemplateでしょうか。意味はRailsのrenderメソッドと同じです。

# text
text: '<h1>ここに書いた内容がActionで指定した部分に反映される</h1>'

# partial
# 部分テンプレートのパスを指定する
partial: 'myapp/shared/partial'

# template
# テンプレートのパスを指定する
template: 'myapp/index'

よく使ったAction(自分調べ)

replace, replace_contents

指定した要素を、指定したSourceで書き換えます。

replace_contentsは、指定した要素の中身を書き換えます。元の内容も使いたい場合は、表示させたい場所で<% render_original %>を記述します。

surround, surround_contents

指定した要素を覆う形で書き換えます。元の内容が消えてしまわないように<% render_original %>を記述してください。

remove

そのままです。指定した要素を取り除きます。

set_attributes, add_to_attributes

指定した要素に属性を追加します。att_to_attributesは追加set_attributesは上書き、となります。

このアクションを指定した場合は、textやpartialでなく、attributesを記述しなければなりません。

# 例
set_attributes: '[data-hook="container"]',
attributes: { class: 'class-name', id: 'id-name' }

例などを少々

理解してもらいやすいように、すこし実践ぽいことをやってみたいと思います。

トップページをいじってみる

spree/home/index.html.erb
home/index.html.erb

GitHub: Solidus – frontend/app/views/spree/home/index.html.erb

Solidusアプリのトップページの表示部分となるviewファイルです。その中では、商品カラムを表示する部分テンプレート「shared/_products.html.erb」を、変数productsを渡して呼び出しています。

上記の7行目から11行目ををdiv要素で囲うとすると、Defaceを下記のように記述します。

# myapp/overrides/home_deface.rb
# ファイルの置き場所はroot以下ならどこでも

Deface::Override.new(
  virtual_path: 'spree/home/index',
  name: 'surround_by_div',
  surround: '[data-hook="homepage_products"]',
  text: '<div class="container"><% render_original %></div>'
)

では次に呼び出されている部分テンプレートを見てみます。

spree/shared/_products.html.erb(見にくいので下のリンクを参照してください汗)
spree/shared/products

GitHub: Solidus – frontend/app/views/spree/shared/_products.html.erb

例題なので適当にやりますが(爆)、ここでは以下のように書き換えたいと思います。

  • 12行目~21行目の商品検索結果表示部分をオリジナルのHTMLに置き換え
  • 25行目の<ul>タグにクラス名を追加

# myapp/overrides/products_deface.rb

Deface::Override.new(
  # ここではファイル名先頭のアンダーバーが必要
  virtual_path: 'spree/shared/_products',
  name: 'replace_by_original_contents',
  replace_contents: '[data-hook="products_search_results_heading"]',
  # myapp/partial/_search_result.html.erbを読み込む
  # partial指定なので、アンダーバーは不要
  partial: 'myapp/partial/search_result'
)

Deface::Override.new(
  virtual_path: 'spree/shared/_products',
  name: 'add_class',
  add_to_attributes: 'ul#products',
  attributes: { class: 'sample-class' }
)

# myapp/shared/_search_result.html.erb

<% if products.empty? %>
  <div>
    <h2><%= Spree.t(:no_products_found) %></h2>
  </div>
<% elsif params.key?(:keywords) %>
  <div>
    <h2><%= Spree.t(:search_results, keywords: h(params[:keywords])) %></h2>
  </div>
<% end %>

このようにその他のページにおいても変更したい部分をDefaceで適宜指定していき、Viewのカスタマイズを完成させます。

個人的には、結構、いや、かなりしんどかったです(疲)。

ガッツリ自分流のViewに変えちゃう

正直全然ありだと思います。下のYouTubeでは、その流れなどを説明してくれています(英語ですが)。ご参考まで。

(Visited 1,876 times, 1 visits today)

“DefaceでSolidusのデザインをカスタマイズ。でも結構面倒。” への1件の返信

コメントは受け付けていません。