LoginSignup
4
4

More than 5 years have passed since last update.

Ruby メタプログミングめも

Last updated at Posted at 2014-02-13

define_method

動的にメソッドを追加する。
ポイントは1つのメソッドで複数のメソッドを定義できる所にある。


# 1から1000までのxの倍数を返す。
def multiple_method(x)
  (1..1000).each_with_object([]) do |number, array|
    if number % x == 0
      array << number
    end
  end
end

(2..5).each do |x|
  define_method("multiple_of_#{x}") do
    multiple_method(x)
  end
end

print multiple_of_2
print multiple_of_3
print multiple_of_4
print multiple_of_5

## 下記改良版
def multiple_method(multiple, range=1000)
  block_method = proc { |argument|
    (1..range).each_with_object([]) do |number, array|
    if number % argument == 0
      array << number
    end
  end
  }
  (1..multiple).each do |x|
    define_method("multiple_of_#{x}") do
      block_method.call(x)
    end
  end
end

send

レシーバの持っているメソッドを引数にして呼び出す。

["upcase", "downcase", "capitalize"].each do |method_name|
 puts "toKYo".send("#{method_name}")
end

class_eval

classの外からでもメソッドを定義できる。


class MyClass
  def sum_value_1
    puts "a" * 100
  end
end

MyClass.class_eval do
  def sum_value_2
    puts "i" * 100
  end
end

instance_eval

ブロック内で変数を利用する


class MyClass
  attr_accessor :tokyo, :osaka

  def initialize(tokyo="tokyo", osaka="osaka")
    @tokyo = tokyo
    @osaka = osaka
  end
end



aaa = MyClass.new
aaa.tokyo

aaa.instance_eval do
  puts "#{@tokyo}#{@osaka}は大都市です。"
end


Procオブジェクト

ブロックをオブジェクトに格納する。

array = ["asakusa", "ginza", "shibuya", "ikebukuro", "sinjyuku", "ueno"]
aaa = proc { |b|
  b.detect{ |a| a =~ /^asa/}
}

bbb = Proc.new{ |b|
  b.detect{ |a| a =~ /^gin/}
}

ccc = lambda{ |b|
  b.detect{ |a| a =~ /^ue/}
}

puts aaa.call(array)
puts bbb.call(array)
puts ccc.call(array)

4
4
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
4
4