テストの結果

Untitled

RuboCopの指摘を解決するために、build_body メソッドをリファクタリングしましょう。具体的には、メソッドの複雑さを減らし、next を使ってイテレーションをスキップするように修正します。

def build_body(controller)
    result = ''

    article_blocks.each do |article_block|
      next if article_block.blank?

      result << render_article_block(controller, article_block)
    end

    result
  end

  private

  def render_article_block(controller, article_block)
    case article_block.blockable_type
    when 'Sentence'
      render_sentence(article_block.blockable)
    when 'Medium'
      render_medium(controller, article_block.blockable)
    when 'Embed'
      render_embed(controller, article_block.blockable)
    else
      ''
    end
  end

  def render_sentence(sentence)
    sentence&.body || ''
  end

  def render_medium(controller, medium)
    return '' if medium.blank?

    decorated_medium = ActiveDecorator::Decorator.instance.decorate(medium)
    render_media_partial(controller, decorated_medium)
  end

  def render_embed(controller, embed)
    return '' if embed.blank?

    decorated_embed = ActiveDecorator::Decorator.instance.decorate(embed)
    render_embed_partial(controller, decorated_embed)
  end

  def render_media_partial(controller, decorated_medium)
    controller.render_to_string("shared/_media_#{decorated_medium.media_type}", locals: { medium: decorated_medium }, layout: false)
  end

  def render_embed_partial(controller, decorated_embed)
    controller.render_to_string("shared/_embed_#{decorated_embed.embed_type}", locals: { embed: decorated_embed }, layout: false)
  end

この状態でrspecのテストをすると下記のエラーが発生

Untitled

このエラーは、prev_article メソッドが定義されていないことが原因です。prev_article メソッドは Article モデルに定義されているはずですが、エラーメッセージからは prev_article メソッドが呼ばれたコンテキストが不明確です。

この問題を解決するためには、いくつかの点を確認する必要があります。

  1. prev_article メソッドの定義: Article モデルに prev_article メソッドが定義されていることを確認します。prev_article メソッドは、他の記事の中で現在の記事よりも前に公開された記事を取得するためのものです。以下のように定義されるべきです。

    def prev_article
      @prev_article ||= Article.viewable.order(published_at: :desc).find_by('published_at < ?', published_at)
    end
    

    このメソッドが不足している場合は、Article モデルに追加してください。おそらくこれはできているはずです。

  2. コントローラの設定: prev_article メソッドを使うビューがある場合、適切なコントローラで @article が設定されていることを確認してください。例えば、AdminArticlesPreview コントローラ内で @article を設定する必要があります。

    def show
        @category = Category.find_by(slug: params[:category_slug])
        if @category.nil?
          # カテゴリが見つからなかった場合の処理
          render plain: 'Category not found', status: :not_found
          return
        end
    
        @article = @category.articles.find_by(slug: params[:article_slug])
        if @article.nil?
          # 記事が見つからなかった場合の処理
          render plain: 'Article not found', status: :not_found
          return
        end
    
        @medium = @article.image
      end
    

    ここで params[:id] はプレビューしたい記事のIDに置き換えます。

    問題ないでしょう。

  3. テンプレートの確認

.container.article-content
  h1.title = article.title

  section.published-at
    time
      = l(article.published_at? ? article.published_at.to_date : Time.current.to_date, format: '%Y年%-m月%-d日')

  - if article.eye_catch.attached?
    section.eye_catch
      = image_tag article.eye_catch_url(:lg), class: 'img-fluid'

  - if article.category.present?
    section.category
      h4 Category
      = link_to article.category.name, category_path(article.category.slug)

  - if article.tags.present?
    section.tags
      h4 Tags
      ul.list-inline
      - article.tags.each do |tag|
        li.list-inline-item = link_to tag.name, tag_path(tag.slug)

  article.article
    == article.body

  - if article.author.present?
    section.author.my-5
      .card
        .card-body
          .media
            = image_tag article.author.avatar_url(:media), class: 'mr-3', style: 'width: 64px; height: 64px;'
            .media-body
              h5.mt-0 = link_to article.author.name, author_path(article.author.slug)
              = article.author.description

  section.row.next-article.my-5
    .col-sm-6
      **- if article.prev_article.present?**
        .card
          .card-body
            h6.card-title.text-center 古い記事
            h6.card-title
              = link_to article.prev_article.title, article_path(article.prev_article.category_slug, article.prev_article.slug)
    .col-sm-6
      **- if article.next_article.present?**
        .card
          .card-body
            h6.card-title.text-center 新しい記事
            h6.card-title
              = link_to article.next_article.title, article_path(article.next_article.category_slug, article.next_article.slug)

- if article.next_article.present?

の部分でprev_articlenext_articleメソッドが存在しない場合や、記事が存在しない場合にエラーが発生する可能性がある。

respond_to?メソッドを使って該当メソッドが存在するか確認する。

変更前