2020年7月4日土曜日

Ruby で prepend を使ってモンキーパッチを当てる方法を考える

概要

前回はオープンクラスを使った方法を紹介しました
今回は prepend を使って実現する方法を考えます

環境

  • macOS 10.15.5
  • Ruby 2.7.1p83

サンプル1: クラスに prepend してしまう

シンプルにやるならこれで OK
ただ範囲が全体に及ぶのでオブジェクトからクラスをオープンして特異クラスに prepend して上げたほうがいいかもしれない

require 'net/https'

module MonkeyUser
  def hello
    "monkeyuser,99"
  end
end

class User
  prepend MonkeyUser

  def initialize(name, age)
    @name = name
    @age = age
  end

  def hello
    "#{@name},#{@age}"
  end

  def access
    uri = URI.parse 'https://kaka-request-dumper.herokuapp.com/'
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    req = Net::HTTP::Get.new uri.request_uri
    res = http.request req
    res.body
  end
end

u1 = User.new("hawksnowlog", 10)
p u1.hello

サンプル2: オブジェクトからクラスをオープンして prepend する

こっちのほうがスコープ的にはキレイに書けている
ただ正直なところパッと見て何をやっているかは Ruby のメタプログラミングを理解している人でないとわからないかもしれない

require 'net/https'

module MonkeyUser
  def hello
    "monkeyuser,99"
  end
end

class User
  def initialize(name, age)
    @name = name
    @age = age
  end

  def hello
    "#{@name},#{@age}"
  end
end

u1 = User.new("hawksnowlog", 10)
u2 = User.new("hawksnowlog", 10)
p u1.hello
class << u2
  prepend MonkeyUser
end
p u2.hello
p u1.hello

0 件のコメント:

コメントを投稿