Progaku-copy / progaku-archive

Progakuのアーカイブ用のアプリ
0 stars 1 forks source link

メモのタグをメモの作成・更新時に登録できるようにする #34

Closed kakeru-one closed 1 month ago

kakeru-one commented 9 months ago

ゴール

設計のヒント

Formクラスの実装イメージ(作成時のユースケースコード)

# frozen_string_literal: true

class Memo
  class BuildForm
    # NOTE: これをincludeすると、errorsやvalidates、valid?とかが使えるようになる。
    include ActiveModel::Validations

    # Ref: https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89
    validate :memo_valid?
    validate :memo_tags_valid?, if: -> { errors.empty? }

    # @param params [Hash]
    def initialize(params:)
      @params = params
    end

    def save
      return false unless valid?

      ApplicationRecord.transaction do
        save_record!(memo)
      end

      errors.empty?
    end

    # @return [Memo]
    def memo
      @memo ||= Memo.new(
        title: params[:title],
        content: params[:content]
      )
    end

    attr_reader :params

    private

    def save_record!(record)
      return true if record.nil? || record.save

      record.errors.each { errors.add(:base, _1.full_message) }
      raise ActiveRecord::Rollback
    end

    # @return [MemoTag::Relation]
    def memo_tags
      @memo_tags ||= resolve_memo_tags
    end

    def memo_valid?
      return if memo.valid?

      memo.errors.each { errors.add(:base, _1.full_message) }
    end

    def memo_tags_valid?
      memo_tags.each do |memo_tag|
        next if memo_tag.valid?

        memo_tag.errors.each { errors.add(:base, _1.full_message) }
      end
    end

    def resolve_memo_tags
      # ここで複数のMemoTag.newをして、その集合を返す処理を書く。
    end
  end
end