Forum: Italian Ruby user group Fragment Cache

33c7c2cca02b80f026c30039cf8e312c?d=identicon&s=25 Michele Boscolo (sphynx)
on 2014-05-06 21:35
Ciao a tutti, e scusatemi se pongo domande che per voi possono sembrare
banali, ma sto imparando Ror da solo a casa solo per Hobby, e non ho
altro punto di riferimento se non questo forum....
Vediamo al punto, leggendo il libro Agile Web Development with Rails 4,
sono incappato in questo pezzo di codice:

<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>

<h1>Your Pragmatic Catalog</h1>
<% cache ['store', Product.latest] do %>
<% @products.each do |product| %>
<% cache ['entry', product] do %>
<div class= "entry" >
   <%= image_tag(product.image_url) %>
   <h3> <%= product.title %> </h3>
   <%= sanitize(product.description) %>
   <div class= "price_line" >
      <span class= "price" ><%= number_to_currency(product.price,
:locale => :it) %></span>
   </div>
</div>
<% end %>
<% end %>
<% end %>

La mia perplessita, è come funziona la fragment cache, in pratica qui
vedo che viene richimata due volte la funzione cache, e leggendo il
libro si parla di cache matrioska, e perchè gli viene passato un array
con due elementi?? Credo che il primo elemento sia il nome della cache,
e l'altro a cosa serve??

Sarei grato a chiunque riesca a schiarmi le idee al riguardo.

GRAZIE.
Cb8e3a1650513848561ca38f84399fa1?d=identicon&s=25 Fabrizio Regini (freegenie)
on 2014-05-06 22:01
(Received via mailing list)
Matrioska (o russian doll caching) perch la cache  nidificata. Ce n' una
esterna che trovi alla riga 6, mentre alla riga 8 ce n' un'altra
interna.
Immagino che latest restituisca l'ultimo prodotto.

Quello che succeder  che verr generata una cache entry per ogni prodotto
(cache interna, riga 8). Alla fine dell'iterazione, il risultato
dell'output del ciclo viene messo in una cache che ha come chiave
l'ultimo
elemento restituito, supponiamo con id 10.
Supponendo che tu abbia 10 prodotti, avrai, nel tuo cache store, 10
frammenti di cache interna e un solo frammento di cache esterna.
Se non fai nessuna modifica, e ricarichi la pagina quello che succede
che
Rails chiama dal cache store il frammento di cache esterna, che  stato
generato in corrispondenza della riga 6. Se lo trova non invoca affatto
il
codice ERB interno, quindi non prova neanche a recuperare gli oggetti in
cache generati alla riga 8.

Quindi ci sar una sola chiamata al cache store e sar soddisfatta.

Poi tu crei un altro prodotto, quindi Product.latest ti da qualcosa di
diverso diciamo id 11. Ricarichi la pagina, la cache alla riga 6 non
trova
pi un elemento in cache che si chiama 'store-10' (per intenderci) e
proceder quindi alla nuova valutazione del codice ERB interno. Entrer
nel
ciclo, a questo punto far una chiamata di cache ogni volta per ogni
prodotto. Per 10 volte otterr un risultato dalla cache, quindi non
valuter il codice ERB all'interno della chiamata cache alla riga 8.
L'undicesima volta non trover un elemento con nome 'entry-11' (per
intenderci) e entrer nel codice ERB interno una sola volta per generare
l'output che poi metter in cache. Alla fine del ciclo, stessa storia,
tutto l'output HTML generato dal ciclo viene messo nella cache con
chiave
'store-11' (per intenderci).

Fin qui tutto facile.

Ora il meccanismo sottile di Rails risolve un ulteriore problema non
immediatamente visibile. Che succede se tu cambi il codice ERB
all'interno
del blocco pi interno, quello che parte alla riga 8? Non hai introdotto
nuovi prodotti, ma comunque il codice HTML che deve essere generato
diverso, *sia* per la cache di tipo 'store' *sia* per la cache di tipo
'entry'.

Nelle versioni precedenti di Rails questa pulizia della cache doveva
essere
fatta a mano. Con le versioni recenti, mi pare con la 4 appunto, quello
che
succede  che Rails:

1) capisce che il codice da cui dipende la cache (ERB in questo caso)
cambiato, quindi invalida al cache
2) capisce che deve invalidare anche la cache dei frammenti pi esterni
che
contengono quello il cui codice  cambiato.

Quindi, quando sei a deployare una nuova versione della tua applicazione
la
cache viene invalidata e quindi rigenerata solo per quei frammenti che
sono
effettivamente *da cambiare*, lasciando inalterati gli altri. Per una
applicazione che fa molto uso di cache  un vantaggio non indifferente.
Immagina che ogni volta che fai la cache di qualcosa eviti di fare
almeno
10 query sul database. Se hai molti elementi in cache e molte richieste,
e
dovessi ad ogni deploy invalidare tutta la cache (come molti facevano in
precedenza), beh avvertiresti il colpo.

Come disse un celebre papa recentemente beatificato, si sbalio
coregetemi.


2014-05-06 21:35 GMT+02:00 michele boscolo <miboscol@gmail.com>:
33c7c2cca02b80f026c30039cf8e312c?d=identicon&s=25 Michele Boscolo (sphynx)
on 2014-05-08 12:16
Grazie mille per la tua celere risposta...

Mi hai chiarito abbastanza le idee, un'ultimo dubbio che mi è rimasto è
sull'array che gli viene passato come argomento, il primo elemento
dell'array è tipo un nome che gli viene dato per identificare quella
cache, mentre il secondo elemento dell'array è l'elemento che devo
monitorare..

GRAZIE.
Cb8e3a1650513848561ca38f84399fa1?d=identicon&s=25 Fabrizio Regini (freegenie)
on 2014-05-08 15:11
(Received via mailing list)
Puoi passare quello che vuoi nell'ordine che vuoi. Due stringhe, tre
oggetti, un oggetto prima e una stringa dopo. Rails far le sue cose per
trarre da quell'array la chiave da usare per la cache. Se l'oggetto
passato
non  una stringa o un numero Rails chiama su quell'oggetto il metodo
'cache_key' (
http://api.rubyonrails.org/classes/ActiveRecord/In...).


Questo metodo  presente negli oggetti ActiveRecord. Nel caso volessi
passare qualcosa che non  un AR, basta che implementi questo metodo nel
tuo oggetto, in modo che restituisca un identificativo che vuoi usare
quando si tratta di generare la chaive per la cache.


2014-05-08 12:16 GMT+02:00 michele boscolo <miboscol@gmail.com>:
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.