Domanda

Per generare becchetti per Omniauth, ho aggiunto questo metodo a 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

Quindi chiamo nello stesso file:

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

Ma ottengo:

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

Soluzione

class_evale module_eval (che sono equivalenti) vengono utilizzati per valutare ed eseguire immediatamente le stringhe come codice Ruby. Pertanto, possono essere utilizzati come struttura di meta-programmazione per creare metodi dinamicamente. Un esempio è

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

Creerà due metodi foo e bar che stampano i rispettivi valori. Come puoi vedere, creo una stringa contenente il codice sorgente effettivo della funzione e la trasmetto in class_eval.

Sebbene si tratti di uno strumento molto capace di eseguire il codice creato dinamicamente, deve essere utilizzato con grande cura. Se fai errori qui, succederanno cose brutte ™. EG Se si utilizza i valori forniti dall'utente quando si genera codice, fai veramente Sicuramente le variabili contengono solo valori che ti aspetti. La funzione basata su Eval dovrebbe essere generalmente utilizzata come ultima risorsa.

Una variante più pulita e generalmente preferita è usare define_method così:

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

(Si noti che la risonanza magnetica è un po 'più veloce con la variante di Eval. Ma non importa la maggior parte del tempo rispetto alla sicurezza e alla chiarezza aggiunte.)

Ora nel tuo codice dato, scrivi efficacemente il codice in una stringa che può essere eseguita direttamente. Usando class_eval Qui porta alla stringa eseguita nel contesto dell'oggetto più alto (Kernel in questo caso). Poiché si tratta di un oggetto singleton speciale che non può essere installato (simile a Nil, True e False), si ottiene questo errore.

Tuttavia, man mano che si crea un codice eseguibile direttamente, non è necessario utilizzare class_eval (o qualsiasi forma di Eval). Basta eseguire il tuo codice in un ciclo così com'è. E ricorda sempre: le varianti di meta-programmazione (di cui i metodi di valutazione sono tra i più cattivi) dovrebbero essere usate solo come ultima risorsa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top