2013-06-17 9 views
6

La mia app (Rails 4) consente agli utenti di votare sui post. È possibile memorizzare nella cache il post, ma personalizzare la cache dei voti in modo che mostri uno personalizzato per current_user? Ad esempio, se l'utente ha votato o meno.Come posso memorizzare in cache un frammento personalizzato in Rails 4?

Preferirei non modificare la struttura html per ottenere ciò.

# posts/_post.html.slim 
- cache post do 
    h1 = post.title 
    = post.text 
    = render 'votes/form', post: post 

# votes/_form.html.slim 
- if signed_in? && current_user.voted?(post) 
    = form_for current_user.votes.find_by(post: post), method: :delete do |f| 
    = f.submit 
- else 
    = form_for Vote.new do |f| 
    = f.submit 

risposta

6

Hai due opzioni qui:

Opzione 1: non nascondono i voti

Questa è la soluzione più semplice e quello che ho raccomanda personalmente. È solo che non in cache la parte a carico dell'utente dinamica in modo da avere qualcosa di simile:

# posts/_post.html.slim 
- cache post do 
    h1 = post.title 
    = post.text 
= render 'votes/form', post: post # not cached 

Opzione 2: usare javascript

Questa soluzione è più complessa, ma è in realtà come campo base farlo (però per lo più con esempi più semplici). Hai entrambi reso parte sulla pagina, ma rimuovi uno di essi con javascript. Ecco un esempio utilizzando jQuery e CoffeeScript:

# posts/_post.html.slim 
- cache post do 
    h1 = post.title 
    = post.text 
    = render 'votes/form', post: post 

# votes/_form.html.slim 
div#votes{"data-id" => post.id} 
    .not_voted 
    = form_for current_user.votes.find_by(post: post), method: :delete do |f| 
     = f.submit 
    .voted 
    = form_for Vote.new do |f| 
     = f.submit 

# css 
.not_voted { 
    display:none; 
} 

# javascript (coffeescript) 
jQuery -> 
    if $('#votes').length 
    $.getScript('/posts/current/' + $('#votes').data('id')) 

# posts_controller.b 
def current 
    @post = Post.find(params[:id]) 
end 

# users/current.js.erb 
<% signed_in? && current_user.voted?(@post) %> 
    $('.voted').hide(); 
    $('.not_voted').show(); 
<% end %> 

Vorrei però cambiare correttamente voted? metodo per accettare un id, quindi non c'è bisogno di fare una nuova query. È possibile ottenere ulteriori informazioni su questo approccio in questo tipo di railscast: http://railscasts.com/episodes/169-dynamic-page-caching-revised?view=asciicast

+0

Grazie. In che modo la modifica votata per ricevere un ID impedisce di eseguire una query aggiuntiva? Non è già disponibile come variabile di istanza? L'unica query di cui hai bisogno è 'votes.where user_id = foo e post_id = foo'. – dee

+0

Sì, ma con la soluzione javascript '$ .getScript' attiva una richiesta ajax che quindi imposterà la variabile istanza' @ post' tramite una query db. Se potessi avere un '@ post_id' sarebbe più veloce, il che è importante in questo scenario. – jokklan

+0

Grazie. Un ultimo commento. La tua prima soluzione significa che non posso eseguire il rendering di una raccolta, come in '= render @ posts' perché il rendering avverrà all'interno del partial' _post', e verrà memorizzato nella cache. Avrei bisogno di ricorrere alla raccolta, alla cache e al rendering di ogni singolo post, quindi all'esterno del blocco della cache renderò il partial '_vote'. Destra? – dee

1

Provare quanto segue per creare 2 diversi frammenti sia per i votati che per quelli non votati. Sarà letto in base al suo stato.

# posts/_post.html.slim 
- cache [post, current_user.votes.find_by(post: post)]do 
    h1 = post.title 
    = post.text 
    = render 'votes/form', post: post 
Problemi correlati