RoadMovie

write down memos or something I found about tech things

メタプログラミング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

とかできるようになるわけ。