LoginSignup
8
3

More than 5 years have passed since last update.

rubyでクラスマクロを作った

Last updated at Posted at 2018-05-05

rubyでクラスマクロを作った

環境

ruby 2.4.1

概要

また、メタプログラミングです。
attr_accessorのようなクラスマクロをメタプログラミングRuby 第2版を見ながらrubyで組んだので、それの備忘録です。

クラスマクロとは

attr_accsessorのようなキーワードに見えるクラスメソッドの事です。
下に使用例を書きました。

class MyClass
  attr_accessor :test1
end

obj = MyClass.new
obj.test1 = "hoge"
puts obj.test1
出力
hoge

今回作成したクラスマクロ

attr_accessorはC言語でコーディングされていますが、今回はrubyで書いて
それに、ランダム性を持たせたattr_randomというクラスマクロを作成しました。

メタプログラミングの復習に良かったです。

ソースコード

module RandomAttributes
  def self.included(klass)
    klass.extend ClassMethods
  end

  module ClassMethods
   def attr_random(attribute)
       define_method "#{attribute}=" do |value|
         return false  if value.nil?
         return false  unless value.kind_of?(String)

         rand_val = value.split("").sort_by!{rand}
         instance_variable_set("@#{attribute}", rand_val.join)
       end

       define_method "#{attribute}" do
          instance_variable_get "@#{attribute}"
       end
    end
  end
end

class MyClass
  include RandomAttributes
  attr_random :test1
  attr_random :test2
  attr_random :test3
end

def check_attr_random
  obj = MyClass.new
  name = ["Tarou", "Saburou", "Kotarou"]
  obj.methods.grep(/test.*=/).each_with_index do |t, i|
    obj.send(t, name[i])
  end

  obj.methods.grep(/test[1-3]$/).each_with_index do |t, i|
    puts obj.send(t)
  end
end

check_attr_random
出力
Troua
oaruubS
uaKroto

※ ランダムなので出力は実行ごとに変わるので注意してください。

最後に

個人的に復習できたポイントについてまとめます。

  • self.includedによるフック処理
  • obj.sendによる動的メソッド実行
  • メソッドを定義するメソッドの書き方
  • クラスマクロの作成の仕方
8
3
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
8
3