microCMSをrailsで使う

2023/01/15

microCMS
Rails

こんにちは。

今年もよろしくお願いします。

あるプロジェクトで、記事系コンテンツを組み込みたいという話が上がり、microCMSを触ってみたのでその方法を今回はご紹介します。
Contentfulも触ったので、比較記事もそのうち書きたいなーと思っております。

microCMSとは

microCMSは、headless CMSの一つです。
海外のサービスであれば、ContentfulやPrismicなどが有名ですが、国内サービスの中ではmicroCMSが最もメジャーではないでしょうか。

microCMSのHP

headless CMSとは、記事系コンテンツなどの編集画面と、それを配信するAPIからなるCMSのことです。

このようなheadless CMSを組み込むことで、記事系コンテンツを簡単に実装できるようになります。

RailsでCMSをつくるのは結構大変

ここまで読んでいる方には、RailsでCMS機能自体を実装してしまえばいいじゃん!と考える方もいるかもしれません。

もちろん、CMS機能を実装することも可能ですが、Railsで理想的なCMSを実装するのは結構大変です。

とくに大変な部分としては、コンテンツの入力機能の部分になるでしょうか。

画像を挿入するときに画像を入力できるエディタが必要になりますし、画像のアップロード機能も必要になります。

このあたりを考慮し、今回はmicroCMSを使ってみました。

やっていくぞ

では、実際にmicroCMSを使ってみましょう。

microCMSのアカウントを作成する

まずは、microCMSのHPからアカウントを作成します。

アカウントを作成すると、以下のような画面が表示されます。

microCMSの画面

Permissions > Api Key からAPIキーを発行します。
僕の場合はすでにdefaultのAPIキーが発行されていたので、それを使います。

APIキーの発行

コピーしたら、環境変数に保存しておきます。

EDITOR="code --wait" bin/rails credentials:edit

config/credentials.yml
microcms:
  api_key: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

次に、対象のContentsのAPI Settingsから、APIのURLを確認します。

APIのURL

このURLも環境変数に保存しておきます。

config/credentials.yml
microcms:
  api_key: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  xxxxx_url: "https://xxxxx.microcms.io/api/v1/xxxxx" # 対象のContent名のURLとしています

Articleモデルを作成する

それでは次にArticleモデルを作成しましょう。

今回とってくるカラムは、デフォルトで用意されている以下の6つとします。

  • id
  • title
  • content
  • published_at
  • eyecatch
  • category

microCMSのAPIドキュメントはこちらで確認できます。

RubyのSDKもありましたが、そんなに難しいことをするわけではないので今回はHTTPクライアントを使って実装します。

一覧を取得するpageメソッドとidをもとに1件取得するfindメソッドをクラスソッドとして実装します。

kaminari gemのように、返り値にoffsetやtotal_countが含まれた状態で返ってくるのでそこに注意が必要です。

app/models/article.rb
class Article
  attr_accessor :id, :title, :content, :published_at, :eyecatch, :category

  def initialize(id:, title:, content:, published_at:, eyecatch:, category:) # rubocop:disable Metrics/ParameterLists
    @id = id
    @title = title
    @content = content
    @published_at = published_at
    @eyecatch = eyecatch
    @category = category
  end

  def self.page(offset: 0, limit: 10)
    uri = URI.parse("#{Rails.application.credentials.dig(:microcms, :articles_url)}?offset=#{offset}&limit=#{limit}")
    header = { 'X-MICROCMS-API-KEY': Rails.application.credentials.dig(:microcms, :api_key) }
    res = Net::HTTP.get_response(uri, header)

    raise ActiveRecord::RecordNotFound if res.code.to_i == 404
    raise StandardError unless res.code.to_i == 200

    body = JSON.parse(res.body, symbolize_names: true)

    articles = body[:contents].map do |content|
      new(
        id: content[:id],
        title: content[:title],
        content: content[:content],
        published_at: content[:publishedAt],
        eyecatch: content[:eyecatch],
        category: content[:category]
      )
    end
    [articles, body[:totalCount], body[:offset], body[:limit]]
  end

  def self.find(id)
    uri = URI.parse("#{Rails.application.credentials.dig(:microcms, :articles_url)}/#{id}")
    header = { 'X-MICROCMS-API-KEY': Rails.application.credentials.dig(:microcms, :api_key) }
    res = Net::HTTP.get_response(uri, header)

    raise ActiveRecord::RecordNotFound if res.code.to_i == 404
    raise StandardError unless res.code.to_i == 200

    body = JSON.parse(res.body, symbolize_names: true)

    new(
      id: body[:id],
      title: body[:title],
      content: body[:content],
      published_at: body[:publishedAt],
      eyecatch: body[:eyecatch],
      category: body[:category]
    )
  end
end

特に変わったところはないつもりですが、注意点としてはNet::HTTP.get_responseの第2引数にヘッダーを渡す必要があるところでしょうか。

X-MICROCMS-API-KEYというkeyでAPIキーを渡す必要があるのですが、古い記事だX-API-KEYというkeyで渡している記事が多いので注意が必要です。

このように実装できたら、次はrouteとコントローラーを作成します。

config/routes.rb
Rails.application.routes.draw do
  resources :articles, only: %i[index show]
end

app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def index
    offset = params[:offset] || 0
    limit = params[:limit] || 10
    @articles, @total_count, @offset, @limit = Article.page(offset:, limit:)
  end

  def show
    @article = Article.find(params[:id])
  end
end

最後に、シンプルなViewを作成しましょう。

app/views/articles/index.html.haml

- @articles.each do |article|
  = link_to article.title, article_path(article.id)

app/views/articles/show.html.haml
= @article.title
= @article.content.html_safe

これで、microCMSから記事を取得することができました。

今回はこのあたりで。

Related Posts

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

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