4

私は、複雑なプロジェクトの一連の Rake タスクを使っていくつかのトリックを行っており、一度にチャンクで複雑さの一部を徐々にリファクタリングしています。これにより、以前のプロジェクト メンテナーが残した依存関係の奇妙な網が露出しました。

私ができるようにしたいのは、プロジェクト内の特定requireのパスを検索するパスのリストに追加すること$:です。ただし、特定の 1 つのメソッドのコンテキストでのみそのパスを検索したいと考えています。今、私は次のようなことをしています:

def foo()
  # Look up old paths, add new special path.
  paths = $:
  $: << special_path

  # Do work ...
  bar()
  baz()
  quux()

  # Reset.
  $:.clear
  $: << paths
end

def bar()
  require '...' # If called from within foo(), will also search special_path.
  ...
end

これは明らかに巨大なハックです。より良い方法はありますか?

4

2 に答える 2

3

は配列であるため$:、何をしているのかに注意する必要があります。dup(経由で)コピーを取り、後でそれを取得する必要がありますreplace。ただし、追加したものを単純に削除する方が簡単です。

def foo
  $: << special_path

  # Do work ...
  bar()

ensure
  # Reset.
  $:.delete(special_path)
end

より多くの情報がなければ、より良い方法があるかどうかを知ることは困難です.

于 2010-04-24T20:26:26.767 に答える
0

requireは実際にはメソッドであり、Kernel#require(これは を呼び出しますrb_require_safe) なので、少なくともモンキー パッチを適用したバージョンでハッキングを実行できます。そういうのが好きなら。

  • 元のエイリアスが邪魔にならない必要があります
  • 絶対パスが渡された場合は、元の require メソッドを呼び出します
  • それ以外の場合は、絶対パスを作成し、元の require メソッドを呼び出して、ロード パスを繰り返し処理します。

楽しみのために、私はそれについて簡単にバッシュしました。プロトタイプは以下にあります。これは完全にはテストされていません。私は のセマンティクスをチェックしていません。完全を期すためには、おそらくとrb_require_safeも参照する必要があります。これは、モジュールのモンキー パッチのままです。それはおそらく完全に怪物的ではありませんが、確かにハックです. グローバル変数をいじるよりも良いか悪いかの呼び出し。#load#includeKernel$:

module Kernel

  alias original_require require

  # Just like standard require but takes an
  # optional second argument (a string or an
  # array of strings) for additional directories
  # to search.
  def require(file, more_dirs=[])
    if file =~ /^\// # absolute path
      original_require(file)
    else
      ($: + [ more_dirs ].flatten).each do |dir|
        path = File.join(dir, file)
        begin
          return original_require(path)
        rescue LoadError
        end
      end
      raise LoadError,
        "no such file to load -- #{file}"
    end
  end

end

例:

require 'mymod'
require 'mymod', '/home/me/lib'
require 'mymod', [ '/home/me/lib', '/home/you/lib' ]
于 2010-04-25T09:31:18.230 に答える