メタプログラミングRubyメモ
Object#extend
module MyModule def my_method; 'hello'; end end
を使いたいときに
class MyClass class << self include MyModule …. end end
↓
class MyClass extend MyModule …. end
これでもMyClassの特異メソッドとしてmy_methodを呼べる。
( MyClass.my_method #=> 'hello' )
falseの時なにか決まったものを返すとき、三項演算子じゃなくていいよ!的な
class MyClass def initialize @hoge = false end def hoge? @hoge || false end end irb(main):009:0> MyClass.new => #<MyClass:0x007ff499890fe0 @hoge=false> irb(main):010:0> a = MyClass.new => #<MyClass:0x007ff49987a8d0 @hoge=false> irb(main):011:0> a.hoge? => false
って感じでいける。or演算子やから当たり前やけど、こう書けてなかったな、、っていう自分のレベルの低さを感じたのでメモ
alias :m(新しいメソッド名) :my_method(古いメソッド名)
★アラウンドエイリアス
module Kernel alias gem_original_require require def require(path) gem_original_require path rescue LoadError => load_error if load_error.message =~ /#{Regexp.escape path}\z/ and spec = Gem.searcher.find(path) then Gem.activate(spec.name, "= #{spec.version}") gem_original_require path else raise load_error end end end
エイリアスは元のメソッドを変更するのではなく、新しいメソッドを定義して元のメソッドの名前をつける。
なので元のものをラップして新しいのに飛ばすようなことができてアラウンドエイリアスと呼ぶ。
クラスマクロ
クラスマクロはクラス定義の中で使えるクラスメソッド
class Book def self.deprecate(old_method, new_method) .. end deprecate :GetTitle, :title end
attr_accessorとかがそう。
module CheckedAttributes def self.included(base) base.extend ClassMethods # baseにはincludeしたクラスが入ってくるのでそれにたいしてClassMethodsを渡してる。 # こうすることで渡ってきたクラスのクラスメソッドにClassMethodsを設定できる end module ClassMethods def attr_checked(attribute, &validation) define_method "#{attribute}=" do |value| raise 'Invalid attribute' unless validation.call(value) instance_variable_set("@#{attribute}", value) end define_method attribute do instance_variable_get "@#{attribute}" end end end end
これで
class Person include CheckedAttributes attr_checked :age do |v| v >= 18 end end
とかできるようになるわけ。