簡體   English   中英

class_eval塊參數和class_eval字符串參數的區別

[英]class_eval block argument and class_eval string argument differences

為了簡化我的情況,當我的Rails應用程序初始化時,我有一個模塊加載到Mongoid :: Document中:

Mongoid::Document.send(:include, ActiveRecordBridge)

該模塊定義了一種方法:

def has_many_records(*records)
  options = records.extract_options!
  if options[:polymorphic]
    class_eval <<-EOS
      def #{ record }
        @#{ record } ||= #{ record.to_s.singularize.classify.constantize }.where( document_id: String(id), document_type: self.class.name)
      end
    EOS
  end
end

現在,我的Mongoid類可以使用它:

class Something
  include Mongoid::Document
  has_many_records :something_else, polymorphic: true
end

這很好用,但是后來另一個開發人員將sync gem添加到我的系統中,並在SomethingElse類中使用了它:

class SomethingElse < ActiveRecord::Base
  sync :all
end

一旦啟動Rails應用程序,就會遇到以下異常:

Uncaught exception: undefined method `sync' for #<Class:0x007fb7910530c0>
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activerecord-4.1.5/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
    /Users/donato/projects/core revisions/core/app/models/something_else.rb:73:in `<class:Task>'
    /Users/donato/projects/core revisions/core/app/models/something_else.rb:19:in `<top (required)>'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:443:in `load'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:443:in `block in load_file'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:633:in `new_constants_in'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:442:in `load_file'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:342:in `require_or_load'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:480:in `load_missing_constant'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/dependencies.rb:180:in `const_missing'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/inflector/methods.rb:238:in `const_get'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/inflector/methods.rb:238:in `block in constantize'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/inflector/methods.rb:236:in `each'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/inflector/methods.rb:236:in `inject'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/inflector/methods.rb:236:in `constantize'
    /Users/donato/.rvm/gems/ruby-2.1.2@core/gems/activesupport-4.1.5/lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
    /Users/donato/projects/core revisions/core/lib/active_record_bridge.rb:55:in `block in has_many_records'

這是有趣的部分。 當我用一個塊替換class_eval的字符串參數時,錯誤消失了:

      class_eval do
          def something_elses
            @something_elses ||= SomethingElse.where(document_id: String(id), document_type: self.class.name)
          end
        end

盡管這行得通,但這不是我想要的,因為現在我顯式地編寫了something_else而不是使用字符串插值。

我的問題:會導致此錯誤的字符串參數呢,而block參數卻不會呢?

當您傳遞字符串參數時,您將插值record.to_s.singularize.classify.constantize 最后一個constantize調用試圖找到常數SomethingElse 通常將開發中的Rails應用程序設置為延遲加載其類,因此僅在這一點上,該應用程序才嘗試加載包含SomethingElse的文件,並且由於該文件包含錯誤,因此在加載時會遇到錯誤。

在第二種情況下,只有在您實際調用something_elses ,才能到達對SomethingElse的引用, something_elses意味着僅在該點才會加載文件並遇到錯誤。 您可以嘗試啟動控制台並調用該方法,或者只是鍵入SomethingElse兩者都應引發錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM