2012-12-06 28 views
9

我在我的Rails應用程序中實現了類似於功能的紙道。爲了做到這一點,我在YAML中序列化對象。我有item_at_version方法,其基本上做YAML::load(cached_object) - 這工作相當不錯,但是,我不知道爲什麼,有時它返回undefined class/module _class name_。 它與事件,對話,注意等模型一起工作,但沒有任何理由,它似乎拋出像數據集,評論,學生模型的錯誤(我試圖找到任何模式,沒有任何運氣)。YAML :: load引發了未定義的類/模塊錯誤

我使用的鐵軌3.2.8,紅寶石1.9.3p327,迷幻如YAML引擎(精極度緊張::版本1.3.4返回)。

Ps。當我在該文件的頂部添加require'model_name'時,它就像一個魅力一樣。

我應該怎麼改/任何想法加入到得到這個工作?

編輯: 有沒有太多的代碼,我可以分享:

def item_at_version 
    YAML::load(cached_object) 
end 

但也許回溯會很有趣:

~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:312:in `path2class' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:312:in `resolve_class' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:219:in `visit_Psych_Nodes_Mapping' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/visitor.rb:15:in `visit' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/visitor.rb:5:in `accept' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:20:in `accept' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:238:in `visit_Psych_Nodes_Document' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/visitor.rb:15:in `visit' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/visitor.rb:5:in `accept' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:20:in `accept' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/nodes/node.rb:35:in `to_ruby' 
~/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych.rb:128:in `load' 
app/models/history_version.rb:7:in `item_at_version' 
app/controllers/history_controller.rb:8:in `show' 
actionpack (3.2.8) lib/action_controller/metal/implicit_render.rb:4:in `send_action' 
actionpack (3.2.8) lib/abstract_controller/base.rb:167:in `process_action' 
actionpack (3.2.8) lib/action_controller/metal/rendering.rb:10:in `process_action' 
actionpack (3.2.8) lib/abstract_controller/callbacks.rb:18:in `block in process_action' 
activesupport (3.2.8) lib/active_support/callbacks.rb:502:in `_run__1697733322876708236__process_action__1122943786273335015__callbacks' 
activesupport (3.2.8) lib/active_support/callbacks.rb:405:in `__run_callback' 
activesupport (3.2.8) lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks' 
activesupport (3.2.8) lib/active_support/callbacks.rb:81:in `run_callbacks' 
actionpack (3.2.8) lib/abstract_controller/callbacks.rb:17:in `process_action' 
actionpack (3.2.8) lib/action_controller/metal/rescue.rb:29:in `process_action' 
actionpack (3.2.8) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action' 
activesupport (3.2.8) lib/active_support/notifications.rb:123:in `block in instrument' 
activesupport (3.2.8) lib/active_support/notifications/instrumenter.rb:20:in `instrument' 
activesupport (3.2.8) lib/active_support/notifications.rb:123:in `instrument' 
actionpack (3.2.8) lib/action_controller/metal/instrumentation.rb:29:in `process_action' 
actionpack (3.2.8) lib/action_controller/metal/params_wrapper.rb:207:in `process_action' 
activerecord (3.2.8) lib/active_record/railties/controller_runtime.rb:18:in `process_action' 
actionpack (3.2.8) lib/abstract_controller/base.rb:121:in `process' 
actionpack (3.2.8) lib/abstract_controller/rendering.rb:45:in `process' 
actionpack (3.2.8) lib/action_controller/metal.rb:203:in `dispatch' 
actionpack (3.2.8) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch' 
actionpack (3.2.8) lib/action_controller/metal.rb:246:in `block in action' 
actionpack (3.2.8) lib/action_dispatch/routing/route_set.rb:73:in `call' 
actionpack (3.2.8) lib/action_dispatch/routing/route_set.rb:73:in `dispatch' 
actionpack (3.2.8) lib/action_dispatch/routing/route_set.rb:36:in `call' 
journey (1.0.4) lib/journey/router.rb:68:in `block in call' 
journey (1.0.4) lib/journey/router.rb:56:in `each' 
journey (1.0.4) lib/journey/router.rb:56:in `call' 
actionpack (3.2.8) lib/action_dispatch/routing/route_set.rb:600:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call' 
rack (1.4.1) lib/rack/etag.rb:23:in `call' 
rack (1.4.1) lib/rack/conditionalget.rb:25:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/head.rb:14:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/params_parser.rb:21:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/flash.rb:242:in `call' 
rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context' 
rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/cookies.rb:339:in `call' 
activerecord (3.2.8) lib/active_record/query_cache.rb:64:in `call' 
activerecord (3.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:473:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call' 
activesupport (3.2.8) lib/active_support/callbacks.rb:405:in `_run__2589517259026276185__call__1369641113040304056__callbacks' 
activesupport (3.2.8) lib/active_support/callbacks.rb:405:in `__run_callback' 
activesupport (3.2.8) lib/active_support/callbacks.rb:385:in `_run_call_callbacks' 
activesupport (3.2.8) lib/active_support/callbacks.rb:81:in `run_callbacks' 
actionpack (3.2.8) lib/action_dispatch/middleware/callbacks.rb:27:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/reloader.rb:65:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/remote_ip.rb:31:in `call' 
bugsnag (1.2.5) lib/bugsnag/rack.rb:35:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call' 
railties (3.2.8) lib/rails/rack/logger.rb:26:in `call_app' 
railties (3.2.8) lib/rails/rack/logger.rb:16:in `call' 
quiet_assets (1.0.1) lib/quiet_assets.rb:20:in `call_with_quiet_assets' 
actionpack (3.2.8) lib/action_dispatch/middleware/request_id.rb:22:in `call' 
rack (1.4.1) lib/rack/methodoverride.rb:21:in `call' 
rack (1.4.1) lib/rack/runtime.rb:17:in `call' 
activesupport (3.2.8) lib/active_support/cache/strategy/local_cache.rb:72:in `call' 
rack (1.4.1) lib/rack/lock.rb:15:in `call' 
actionpack (3.2.8) lib/action_dispatch/middleware/static.rb:62:in `call' 
railties (3.2.8) lib/rails/engine.rb:479:in `call' 
railties (3.2.8) lib/rails/application.rb:223:in `call' 
railties (3.2.8) lib/rails/railtie/configurable.rb:30:in `method_missing' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:147:in `handle' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:99:in `rescue in block (2 levels) in start' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:96:in `block (2 levels) in start' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:86:in `each' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:86:in `block in start' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:66:in `loop' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:66:in `start' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/lib/nack/server.rb:13:in `run' 
~/Library/Application Support/Pow/Versions/0.4.0/node_modules/nack/bin/nack_worker:4:in `<main>' 
+0

如果您顯示一些相關的代碼或回溯,您可能會得到更好的幫助。 – deefour

+0

我的代碼中沒有任何魔法,我沒有太多補充。我添加了完整的回溯,也許這可以提供幫助。 – user1105595

回答

12

當您使用YAML.dump序列化在Ruby中的對象,類name被用作Yaml標籤的一部分,以便在加載對象時可以使用正確的類。例如:

require 'yaml' 

class Foo; end 

puts YAML.dump Foo.new 

產生

--- !ruby/object:Foo {} 

當你對字符串中使用YAML.load,精極度緊張知道實例化什麼類的反序列化對象。

如果你試圖調用YAML.load在YAML字符串,指定尚未定義的類,那麼你將得到錯誤:

require 'yaml' 

# No Bar class has been defined 
YAML.load '--- !ruby/object:Bar {}' 

生產:

/Users/matt/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:312:in `path2class': undefined class/module Bar (ArgumentError) 
    from /Users/matt/.rvm/rubies/ruby-1.9.3-p327/lib/ruby/1.9.1/psych/visitors/to_ruby.rb:312:in `resolve_class' 
... 

這是因爲Psych需要創建類Bar的實例,但是沒有可用類的定義。這就解釋了爲什麼在加載Yaml之前添加require 'whatever' - 現在Ruby已經加載了類的定義,因此可以創建它的一個實例(請注意,Ruby中的類名和文件名之間沒有確切的關聯,這只是約定)。

因此解決的辦法是,以確保當你加載任何Ruby從YAML您已經要求可以包含任何類的定義可能在YAML任何文件對象。

+2

- 謝謝你的回答,但是我仍然不確定爲什麼這不能在rails中工作。當我添加'''Bar.new(some::params)'''它可以工作,所以即時對象_should_也能工作,對吧? – user1105595

+1

@ user1105595這很有趣。這是關於Rails自動加載類的。當你做'Bar.new'時會觸發正常的自動加載過程,但是從Yaml反序列化不會。它在生產環境中運行你的應用程序(或者只是使用'cache_classes = true')它應該可以工作,因爲所有的類都已經被加載了(你可能不會一直這麼做)。我不確定最好的解決方案是什麼,你可能需要明確地在初始化器或其他東西中需要這些文件。 – matt

+1

我發現這個錯誤報告指的是同一個問題(它是在談論元帥,但'rb_path_to_class'方法與在Psych中導致錯誤的方法是一樣的)http://bugs.ruby-lang.org/issues/3511 。 – matt

2

Matt's Answer提供必要的細節。

但是,當我做的代碼修改,然後做一些任務,即反序列化的一些數據,而無需頁面加載(在AJAX),那麼它失敗,同樣的錯誤。

這是更好地使用require_dependencyrequire自動加載更改。

在模塊(不帶class測試)和反序列化使用YAML的情況下,你也可以實例化模塊之前反序列與require來解決該問題。 See here.

來源:SO answerPsych issue report in Github

P.S:這個問題只能在發展中仍然存在的config.cache_classes是能夠在生產。

1

修改爲Matt's answer。代替基於純哈希的解決方案(Psych團隊似乎對此沒有興趣),修改標題字符串以去除對象分類。我只是用下面的代碼做了這個。

yamltext = File.read("somefile","r") 
yamltext.sub!(/^--- \!.*$/,'---') 
hash = YAML.load(yamltext) 

這可能會失敗(我不知道),如果輸入流包括與不同對象分類(我不知道這是連有效)的幾個文件。