2017-04-19 52 views
8

Używam Rails 5, aby użyć pamięci podręcznej Rails do przechowywania obiektów Nokogiri.Jak używać pamięci podręcznej Rails do przechowywania obiektów Nokogiri?

Stworzyłem ten w config/inicjalizatorów/cache.rb:

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

i chciałem przechowywać dokumenty takie jak:

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

ale dostaję ten błąd:

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' 

Co muszę zrobić, aby móc przechowywać te obiekty w pamięci podręcznej?

+1

Najwyraźniej nie. Pamięć podręczna jest jednak dobra do przechowywania ciągów. –

+1

Dlaczego chcesz przechowywać obiekt? Przechowuj spersonalizowaną tablicę asocjacyjną lub tablicę zawierającą informacje skradzione z HTML lub XML za pomocą Nokogiri. Jeśli chcesz przechowywać obiekty, zajrzyj do notowania. –

+1

Myśląc o tym więcej, pamięć podręczna jest odpowiednia dla rzeczy, do których trzeba natychmiast uzyskać dostęp, ale jeśli urządzenie zostanie wyłączone, można je szybko odtworzyć. Jeśli korzystasz z Nokogiri, szanse są dobre, gdy zgarniesz stronę, co oznacza, że ​​ładujesz tę stronę, a ładowanie, parsowanie, proces skrobania dodaje opóźnienia, których nie chcesz (stąd pomysł użycia cache) , ale zamiast tego powinieneś zebrać swoje dane (meta) i przechowywać je w bazie danych, gdzie są one stale dostępne. DBM będzie buforował wewnętrznie. Nie jest tak szybki jak pamięć podręczna w pamięci, ale jest lepszy niż odtwarzanie na żądanie lub podczas uruchamiania aplikacji. –

Odpowiedz

2

użytkownika Nokogiri za funkcjonalność Serializować:

$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

Dzięki, ale jaki jest kod "Przechowuj serializowany obiekt w pamięci podręcznej"? Myślałem, że ciało "$ cache.fetch (url) {" zajmie się przechowywaniem, a następnie wyszukiwanie rzeczy? – Dave

+1

Bardzo dobrze, może nie potrzebujesz niczego, myślałem, że możesz robić coś dodatkowego. Po prostu pomiń to, czego szukasz, to 'serialize'. –

+0

tak, ale to wciąż nie działa, ponieważ "get_content" zwraca dokument Nokogiri (metoda nie może być zmieniona, niestety) i jako taki powoduje to niepowodzenie zewnętrznego "$ cache.fetch" z podanym przeze mnie błędem. Załóżmy, że nic nie wiem (co jest w zasadzie prawdziwe) i proszę, przeliteruj to dla mnie. Jak napisać metodę, która zwraca dokument Nokogiri, który wykorzystuje moją pamięć podręczną Rails? – Dave

3

Przechowuj xml jako ciąg znaków, a nie obiekt i parsuj je, gdy usuniesz je z pamięci podręcznej.

Edycja: Odpowiedź na komentarz

Cache zamiast

nokogiri_object.to_xml 

Edit2: odpowiedzi na komentarz. Coś w tym stylu. Będziesz musiał opublikować więcej kodu, jeśli potrzebujesz bardziej szczegółowej pomocy.

Edit3: Odpowiedź na "Dzięki, ale jaki jest kod" Przechowuj serializowany obiekt w pamięci podręcznej "? Myślałem, że ciało "$ cache.fetch (url) {" zajmie się przechowywaniem, a następnie wyszukiwanie rzeczy?

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

Zobaczmy przykłady kodu. – Dave

+0

Cześć, Gdzie konwertujesz to z powrotem do dokumentu Nokogiri? Moim wymaganiem jest, aby wywołać metodę pamięci podręcznej, która pozwala mi przechowywać i pobierać dokumenty Nokogiri. Jeśli weźmie się pośrednią formę, to w porządku, ale końcowy wynik musi być dokumentem Nokogiri. Nadal nie widzę, jak to osiągnąć dzięki dostarczonym przez ciebie produktom. – Dave

+0

Gotowe! Zobacz mój kod w moim pytaniu. Metoda get_cached_data zawiera kodowanie za pomocą "$ cache.fetch (url) {". Metoda "get_content (url, headers, follow_redirects)" zwraca dokument Nokogiri. Więc skąd wziąć ten wynik, przekonwertować go na XML, a następnie przekonwertować z powrotem na ciąg? – Dave