実装したいこと

<aside> 💡 記事を投稿するアプリの編集画面で、記事のステータスを 「下書き」「公開」「公開待ち」に分類したい。

ステータスと公開日時は編集時に選択可能。 ただし、公開日時によって記事のステータスを 「公開」「公開待ち」に自動で判定して変更する。

ステータスを「下書き」に指定したときは、「下書き」のままにする。

</aside>

前提

enumで記事のステータスを定義しています。

article.rb

enum state: { draft: 0, published: 1, publish_wait: 2 }
# draft: 下書き, published: 公開, publish_wait: 公開待ち

コントローラー

artcles_controller.rb(記事更新用)

 def update
    authorize(@article)

    @article.assign_attributes(article_params) ①
    @article.adjust_state ②
    if @article.save ③
      flash[:notice] = '更新しました'
      redirect_to edit_article_path(@article.uuid)
    else
      render :edit
    end
  end

① assign_attributesメソッドで変更を受け取る

assign_attributes :引数で指定したattributes(属性)を変更するメソッド

② 現在時刻が公開日を過ぎているか、いないかでstateを公開、公開待ち、と振り分ける

③ saveメソッドで保存(DBへの保存はされないので必要。)

published_controller.rb(記事公開用)

  def update
    @article.published_at = Time.current unless @article.published_at?
    @article.state = @article.publishable? ? :published : :publish_wait
    #上記の一文は三項演算子

    if @article.valid?
      Article.transaction do
        @article.save!
      end
      flash[:notice] = @article.message_on_published
      redirect_to edit_admin_article_path(@article.uuid)
    else
      flash.now[:alert] = 'エラーがあります。確認してください。'
      @article.state = @article.state_was if @article.state_changed?
      render 'admin/articles/edit'
    end
  end

@article.publishable?が真偽によって以下を@article.stateに代入します。

真:published