2017-04-19 67 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