0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[メタプログラミングRuby] アトリビュート生成時にバリデーションを実行するクラスマクロを実装してみました

Last updated at Posted at 2022-02-12

実装したいこと

  • メタプログラミングRubyのP145〜146あたりの問題を実装してみました
  • ざっくりとした用件は以下になります
    • attr_accessor のようなアトリビュートのセッター/ゲッターを提供するメソッドに、妥当性を検査する処理を記述した任意のブロックを渡せるようにする。
    • 影響範囲を限定するため、モジュールに実装してincludeしたクラスのみに適用するようにする

モジュールの実装

module CheckedAttributes
    # モジュールをincludeしたクラスに、attr_checkedをクラスメソッドとして定義する
    def self.included(klass)
        klass.extend(SingletonMethods)
    end
    
    module SingletonMethods
        def attr_checked(name, &blk)
            define_method "#{name}" do
                instance_variable_get("@#{name}")
            end
            define_method "#{name}=" do |val|
                # この辺りはもう少しシュッと出来そう
                if block_given? && !blk.call(val)
                    raise "validation error"
                end
                instance_variable_set("@#{name}", val)
            end            
        end
    end
end

includeして利用する側

class Sample
    include CheckedAttributes
    attr_checked :age do |val|
        val > 30
    end
end

# 確認するコード
obj = Sample.new
puts obj.age=(31)
=> 31
puts obj.inspect
=> #<Sample:0x0000000001c50480 @age=31>

puts obj.age=(30)
# paiza.io のMain.rbで実行しています
=> Main.rb:15:in `block in attr_checked': validation error (RuntimeError)
	from Main.rb:44:in `<main>'

まとめ的なもの

  • クラスマクロの中で、define_method を使った方法で実装してみました
    • 前章までに登場していた、instance_variable_XXXdefine_methodなどの理解度を確認できるいい感じの問題だなぁと感じました
  • 業務でクラスマクロを作るシーンが今のところあまり思いついていないですが、Railsのコードを理解するのに役に立ちそうな予感がしています
  • 本では class_eval を使って実装している方法など別の方法もいくつか掲載されていたようで、キャッチアップしていこうと
    思います
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?