ContentfulとmicroCMSをRailsに導入してみた所感

2023/01/25

microCMS
Rails
Contentful

こんにちは。

今回は、前回の記事で書いた通り、ContentfulとmicroCMSをRailsに組み込んだ時の比較をしてみたいと思います。

結論、microCMSの方が個人的には扱いやすいかな?と思いましたので、その理由を3つに分けてお伝えしていきます。

また、microCMSについては前回の記事で詳しく書いているので、そちらも合わせてご覧ください。

前回の記事はこちら

1. Contentfulの値の取得は独自のIDを使ってしまう

Contentfulには、contentful.rbというgemがあります。

contentfulのgem

gemがあるのでこっちの方が便利そうじゃん!と思って使ってみたのですが、独特な書き方になります。

例えば、以下のような形でデータを取得できます。

Gemfile
gem 'contentful'
app/controllers/articles_controller.rb
class ArticlesController < ApplicationController

  def index
    @articles = ContentfulClient.new.fetch_entries
  end

  def show
    @article = ContentfulClient.new.fetch_entry_by_slug(slug: params[:slug])
  end
end
app/models/contentful_client.rb
class ContentfulClient
  DEFAULT_CONTENT_TYPE = 'articles'.freeze
  DEFAULT_SELECTS = %w[
    fields.title
    fields.slug
    fields.headerImage
    fields.createdAt
  ].freeze

  ALL_SELECTS = %w[
    fields.title
    fields.slug
    fields.headerImage
    fields.createdAt
    fields.body
  ].freeze

  def initialize
    @client = Contentful::Client.new(
      space: Rails.application.credentials.dig(:contentful, :space),
      access_token: Rails.application.credentials.dig(:contentful, :access_token),
    )
  end

  def fetch_entries(content_type: DEFAULT_CONTENT_TYPE, select: DEFAULT_SELECTS)
    @client.entries(content_type: content_type, select: select)
  end

  def fetch_entry_by_slug(content_type: DEFAULT_CONTENT_TYPE, slug:, select: ALL_SELECTS)
    @client.entries(content_type: content_type, 'fields.slug' => slug, select: select).first
  end

  def fetch_asset_by_id(id:)
    @client.asset(id)
  end
end

特に#fetch_entry_by_slugをみてもらうとわかるのですが、記事の一覧を取得した後にslugを指定して記事を取得するという形になっています。

最後に.firstとしていることから、イメージが伝わりやすいかなと思います

そもそも記事は固有のIDを持っていて、それがランダムで割り振られる値になってしまうため、例えば/articles/compare-microcms-and-contentfulというURLにしたいときはslugというフィールドを作って、そこにcompare-microcms-and-contentfulという値を入れておき、それを使って記事を取得するという形になります。

詳しく内部の処理まで追っているわけではないのですが、記事のうち特定の記事を探してくる時に一旦全部の記事を取得してから、その中から探してくるという形になっていそうなところもイマイチだなというふうに感じてしまいました。

microCMSでは、そもそもIDを変更することができるので、/articles/compare-microcms-and-contentfulというURLにしたいときは、IDをcompare-microcms-and-contentfulという値にしておけば、そのままURLに使うことができるという点が便利だなと感じました。

(microCMSの方は前回の記事に書いているので割愛します)

2. Contentfulの返り値は独自のHashになっている

上記のように記事を取得した次に、記事の中身を表示するときには、rich textのような複雑なデータが入っているので、それを表示するためには、パースをする必要があります。

Contentfulでは、そのパースをするためのgemが用意されているのですが、それがそのまま使用すると画像を埋め込んだ時などにエラーになってしまうので、パーサーをカスタマイズする必要があります。

Gemfile
gem 'rich_text_renderer'
app/views/articles/show.html.haml
= @article.title
%div.w-full
  = render RichText::Component.new(richtext: @article.body)
app/components/rich_text/component.rb
class RichText::Component < ViewComponent::Base
  def initialize(richtext:)
    @richtext = richtext
    @renderer = RichTextRenderer::Renderer.new(
      'embedded-asset-block' => EmbedAssetRenderer,
      'embedded-entry-block' => EmbedEntryRenderer
    )
  end
end
app/renderers/embed_asset_renderer.rb
class EmbedAssetRenderer < RichTextRenderer::BaseNodeRenderer
  def render(node)
    id = node['data']['target']['sys']['id']
    "<img src=#{src(id: id)} />"
  end

  def src(id:)
    "https:#{ContentfulClient.new.fetch_asset_by_id(id: id).url}"
  end
end
app/renderers/embed_entry_renderer.rb
class EmbedEntryRenderer < RichTextRenderer::BaseNodeRenderer
  def render(node)
    # 途中で諦めたので割愛しますw
  end
end

こんな感じで、例えば記事内に別の記事を埋め込みたいときや、画像を埋め込みたいときには、embedded-asset-blockというタイプのノードをパースするためのクラスを作成する必要があります。

この辺りも細かくこだわりたいケースでは有効なのですが、今回は記事はあくまで全体の1コンテンツであるため、そこまで便利だなと感じられるものではありませんでした。

microCMSでは、記事の中身はMarkdownでそのまま返ってくるので、よくあるMarkdownのパーサーを使えばそのまま表示することができそうです。

ただ、例えば別の記事を埋め込む時に特別な表示にしたいなどの場合は、前述の理由からContentfulの方が便利そうです。

3. microCMSの方がドキュメントが読みやすい

microCMSの方は、ドキュメントが非常に読みやすいです。

microCMSのドキュメント

Contentfulの方は、ドキュメントがそもそも不十分だったり、前述したgemの使い方はGitHubのREADMEに書かれていることが多いのでなかなか探すのに苦労しました。

これは僕が日本人だから、というのも大きいかもしれませんが…

まとめ

今回は、microCMSとContentfulの比較をしてみました。

最初に書いた通り、microCMSの方が便利だなと感じています。

現状だとどちらを使用するケースでも無料枠の範囲内で使えそうですが、もし有料になった時もmicroCMSの方が安いので、そこも意思決定に大きく影響すると思います。

今回はこのあたりで。

Related Posts

microCMSをrailsで使う

microCMSをrailsで使う