1

Omniauth のモックを生成するために、このメソッドをconfig/environments/development.rb

  def provides_mocks_for(*providers)
    providers.each do |provider|
      class_eval %Q{
        OmniAuth.config.add_mock(provider, {
          :uid => '123456',
          :provider => provider,
          :nickname => 'nickname',
          :info => {
            'email' => "#{provider}@webs.com",
            'name' => 'full_name_' + provider
          }
        })
      }
    end
  end

次に、同じファイルを呼び出します。

provides_mocks_for :facebook, :twitter, :github, :meetup

しかし、私は得る:

3.1.3/lib/active_support/core_ext/kernel/singleton_class.rb:11:in `class_eval': can't create instance of singleton class (TypeError)
4

1 に答える 1

2

class_evalmodule_eval(同等のもの) を使用して、文字列を評価し、すぐに Ruby コードとして実行します。そのため、メソッドを動的に作成するためのメタプログラミング機能として使用できます。例は

class Foo
  %w[foo bar].each do |name|
    self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
      def #{name}
        puts '#{name}'
      end
    RUBY
  end
end

2 つのメソッドを作成foobar、それぞれの値を出力します。ご覧のとおり、関数の実際のソース コードを含む文字列を作成し、それを に渡しますclass_eval

これは、動的に作成されたコードを実行するための非常に有能なツールですが、細心の注意を払って使用する必要があります。ここで間違いを犯すと、BAD THINGS WILL HAPPEN™. たとえば、コードを生成するときにユーザー指定の値を使用する場合は、変数に期待する値のみが含まれていることを確認してください。通常、評価ベースの関数は最後の手段として使用する必要があります。

よりクリーンで一般的に好まれるバリアントは、define_method次のように使用することです。

class Foo
  %w[foo bar].each do |name|
    define_method name do
      puts name
    end
  end
end

(MRI は eval バリアントを使用すると少し高速になることに注意してください。ただし、追加された安全性と明確さと比較すると、ほとんどの場合、それは問題ではありません。)

与えられたコードで、直接実行できる文字列にコードを効果的に記述します。ここで使用class_evalすると、最上位のオブジェクトのコンテキストで文字列が実行されます (Kernelこの場合)。これはインスタンス化できない特別なシングルトン オブジェクトであるため (nil、true、false と同様)、このエラーが発生します。

ただし、直接実行可能なコードを作成するため、class_eval(または任意の形式の eval) を使用する必要はまったくありません。コードをそのままループで実行するだけです。そして、常に覚えておいてください: メタプログラミングのバリアント (eval メソッドは最も悪いものの 1 つです) は、最後の手段としてのみ使用する必要があります。

于 2012-01-14T18:07:28.000 に答える