[英]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.