Rails でパラメータを別モデルにして、バリデーションできるようにする

ブログをサボりすぎているので、備忘録でも書くようにしておく。

やったこと

ちょっと詳細書くのが難しいんだけど、処理自体を抽象化して扱おうとしたら、こうなった。

module Task
  class Base
    attr_reader :args

    def self.arguments(&block)
      klass = Class.new.include(ActiveModel::Model)
      klass.class_eval(&block)
      const_set :Arguments, klass
    end

    def initialize(attrs = {})
      @args = self.class.const_get(:Arguments).new(attrs)
    end

    def name
      self.class.name.demodulize.underscore
    end
  end
  
  class SlackPosting < Base
    arguments do
      attr_accessor :channel, :text
      validates :channel, presence: true
      validates :text, presence: true
    end

    def run
      return false unless args.valid?

      # Slack に投稿する処理
      # args.channel, args.text が使える
    end
  end
end

このクラスを使うのはこんな感じ。

task = Task::SlackPosting.new(channel: 'general', text: 'Hello')
task.run