2017-04-19 68 views
8

我正在使用Rails 5来使用Rails缓存来存储Nokogiri对象。如何使用Rails缓存来存储Nokogiri对象?

我在配置/初始化/ cache.rb创造了这个:

$cache = ActiveSupport::Cache::MemoryStore.new 

,我想保存文件一样:

$cache.fetch(url) { 
    result = get_content(url, headers, follow_redirects) 
} 

,但我得到这个错误:

Error during processing: (TypeError) no _dump_data is defined for class Nokogiri::HTML::Document 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:671:in `dump' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:671:in `dup_value!' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache/memory_store.rb:128:in `write_entry' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:398:in `block in write' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:562:in `block in instrument' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/notifications.rb:166:in `instrument' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:562:in `instrument' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:396:in `write' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:596:in `save_block_result_to_cache' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/activesupport-5.0.2/lib/active_support/cache.rb:300:in `fetch' 
/Users/davea/Documents/workspace/myproject/app/helpers/webpage_helper.rb:116:in `get_cached_content' 
/Users/davea/Documents/workspace/myproject/app/helpers/webpage_helper.rb:73:in `get_url' 
/Users/davea/Documents/workspace/myproject/app/services/abstract_my_object_finder_service.rb:29:in `process_data' 
/Users/davea/Documents/workspace/myproject/app/services/run_crawlers_service.rb:26:in `block (2 levels) in run_all_crawlers' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:348:in `run_task' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:337:in `block (3 levels) in create_worker' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `loop' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:320:in `block (2 levels) in create_worker' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `catch' 
/Users/davea/.rvm/gems/ruby-2.4.0/gems/concurrent-ruby-1.0.5/lib/concurrent/executor/ruby_thread_pool_executor.rb:319:in `block in create_worker' 

为了能够将这些对象存储在缓存中,我需要做些什么?

+1

显然,不是。不过,缓存对于存储字符串非常有用。 –

+1

你为什么要存储一个对象?使用Nokogiri存储包含从HTML或XML中获取的信息的序列化哈希或数组。如果你需要存储对象,然后看看memoization。 –

+1

想想更多,内存缓存对于需要立即访问的内容非常有用,但是,如果机器停机,也可以快速重新创建。如果您使用的是Nokogiri,那么您可能正在抓取页面,这意味着您正在加载该页面,并且加载,解析和刮取过程会增加您不想要的延迟(因此,使用缓存的想法) ,而是应该收集(元数据)数据并将其存储在永久可用的数据库中。 DBM将在内部缓存。它不像内存缓存那么快,但是它比根据请求或在应用程序启动时重新创建要好。 –

回答

2

用户引入nokogiri的序列化功能:

$cache = ActiveSupport::Cache::MemoryStore.new 
noko_object = Nokogiri::HTML::Document.new 

serial = noko_object.serialize 
$cache.write(url, serial) 
// Serialized Nokogiri document is now in store at the URL key. 
result = $cache.read(url) 

noko_object = Nokogiri::HTML::Document.new(result) 
// noko_object is now the original document again :) 

Check out the documentation here for more information

+0

感谢但“存储序列化对象缓存”中的代码是什么?我认为“$ cache.fetch(url){”的主体会负责存储和检索东西? – Dave

+1

你很可能不需要任何东西,我想你可能会在那里做一些额外的事情。简单地跳过它,你正在寻找的是'serialize'。 –

+0

是的,但这仍然失败,因为“get_content”返回一个Nokogiri文档(该方法不能被改变,令人伤心),因此它导致外部“$ cache.fetch”失败,并列出错误。假设我什么都不知道(这基本上是真的),请为我拼写。如何编写一个返回使用我的Rails缓存的Nokogiri文档的方法? – Dave

3

将xml存储为字符串,而不是对象,并在您将它们从缓存中取出后解析它们。

编辑:回应置评

缓存这个代替

nokogiri_object.to_xml 

EDIT2:回应置评。沿着这条线的东西。如果您想获得更具体的帮助,您需要发布更多的代码。

nokogiri_object = Nokogiri::XML(cache.fetch('xml_doc')) 

编辑3:'谢谢,但是什么是“在缓存中存储序列化对象”代码?我认为“$ cache.fetch(url){”的主体会负责存储和检索内容?

cache.write('url', xml_or_serialized_nokogiri_string) 
+0

我们来看一些代码示例。 – Dave

+0

嗨,你在哪里转换回Nokogiri文档?我的要求是我需要调用缓存方法,允许我存储和检索Nokogiri文档。如果他们之间有一些中间形式,那很好,但最终的结果必须是Nokogiri文档。我还没有看到如何用你提供的东西来实现这一点。 – Dave

+0

完成!在我的问题中查看我的代码。 get_cached_data方法包含代码“$ cache.fetch(url){”。方法“get_content(url,headers,follow_redirects)”返回Nokogiri文档。那么我在哪里取得这个结果,将其转换为XML,然后将其转换回字符串? – Dave