LoginSignup
7
6

More than 5 years have passed since last update.

クラスを別物に置き換える

Last updated at Posted at 2014-07-03

やりたいこと

某gem(この記事では例としてfb_graphを使用)を呼んだときにMockした別のモジュール・クラスを呼びたい。
もう少し言うと、

  • Mockをonにして、FbGraphを呼ぶとMock::FbGraphが呼ばれる
  • Mockをoffにして、FbGraphを呼ぶとFbGraphが呼ばれる

gemのrequireとObjectクラスへの追加

fb_graphをrequireするとObjectクラスにFbGraphが追加されます。
FbGraph = Mock::FbGraphでFbGraphを置き換えれますが、単純にこれをするとwarningが出てしまいます。

Object.constants.include?(:FbGraph)    #=> false

require 'fb_graph'
Object.constants.include?(:FbGraph)    #=> true
FbGraph                                #=> FbGraph

module Mock; module FbGraph; end; end
FbGraph = Mock::FbGraph;               #=> warning: already initialized constant FbGraph

Object.constants.include?(:FbGraph)    #=> true
FbGraph                                #=> Mock::FbGraph

requireで読み込んだgemをundefする

上記warning対策。
さらに、定数(FbGraph)の設定はconst_setを使うようにする。

require 'fb_graph'
Object.constants.include?(:FbGraph)    #=> true 
FbGraph                                #=> FbGraph

Object.send(:remove_const, :FbGraph)
Object.constants.include?(:FbGraph)    #=> false

module Mock; module FbGraph; end; end 
Object.const_set(:FbGraph, Mock::FbGraph)
Object.constants.include?(:FbGraph)    #=> true 
FbGraph                                #=> Mock::FbGraph

Mockのon/offを作ってみる

以上を踏まえてMockにon/off機能を作ってみる

require 'fb_graph'

module Mock
  extend self

  def on
    if ::FbGraph != Mock::FbGraph
      Object.const_set(:SourceFbGraph, ::FbGraph)
      Object.send(:remove_const, :FbGraph) if Object.constants.include?(:FbGraph)
      Object.const_set(:FbGraph, Mock::FbGraph)
    end 
  end 

  def off 
    if ::FbGraph == Mock::FbGraph
      Object.send(:remove_const, :FbGraph) if Object.constants.include?(:FbGraph)
      Object.const_set(:FbGraph, ::SourceFbGraph)
      Object.send(:remove_const, :SourceFbGraph) if Object.constants.include?(:FbGraph)
    end 
  end 

  module FbGraph
  end 
end

p FbGraph  #=> FbGraph
Mock.on
p FbGraph  #=> Mock::FbGraph
Mock.off
p FbGraph  #=> FbGraph

参考

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