Pulsante Mi piace Ajax in Ruby on Rails

Ho un progetto Ruby on Rails con un modello User e un modello di Content , tra gli altri. Volevo rendere ansible per un utente “mi piace” un contenuto, e l’ho fatto con la gem act_as_votable .

Al momento, il sistema mi piace funziona ma sto aggiornando la pagina ogni volta che viene premuto il pulsante Mi piace (link_to).

Mi piacerebbe farlo utilizzando Ajax, per aggiornare il pulsante e il contatore dei like senza la necessità di aggiornare la pagina.

Nel mio Content -> Show vista, questo è quello che ho:

        ·    users like this 

Il controller dei Content fa questo per piacere / non mi piace:

     def like @content = Content.find(params[:id]) @content.liked_by current_user redirect_to @content end def dislike @content = Content.find(params[:id]) @content.disliked_by current_user redirect_to @content end 

    E nel mio file routes.rb, questo è quello che ho:

     resources :contents do member do put "like", to: "contents#like" put "dislike", to: "contents#dislike" end end 

    Come ho detto, il sistema Mi piace funziona bene, ma non aggiorna il contatore dei Mi piace né un pulsante Mi piace dopo che un utente lo ha premuto. Invece, per ingannarlo, chiamo redirect_to @content del controller.

    Come potrei implementarlo con una semplice chiamata Ajax? C’è un altro modo per farlo?

    Puoi farlo in vari modi, il modo semplice va così:

    preparativi

    1. Includi Rails UJS e jQuery nel tuo application.js (se non è già stato fatto):

       //= require jquery //= require jquery_ujs 
    2. Aggiungi remote: true al tuo link_to aiutanti:

       <%= link_to "Like", '...', class: 'vote', method: :put, remote: true %> 
    3. Lascia che il controller risponda con un non-reindirizzamento sulle richieste AJAX:

       def like @content = Content.find(params[:id]) @content.liked_by current_user if request.xhr? head :ok else redirect_to @content end end 

    Comportamento avanzato

    Probabilmente vuoi aggiornare la visualizzazione di “n utenti piaciuto”. Per ottenere ciò, attenersi alla seguente procedura:

    1. Aggiungi un handle al tuo valore contatore, in modo che tu possa trovarlo in un secondo momento con JS:

        <%= @content.get_likes.size %>  users like this 

      Si prega di notare anche l’uso di data-id , non id . Se questo frammento di codice viene usato spesso, lo rifatterei in un metodo di supporto.

    2. Lascia che il controller risponda con il conteggio e non semplicemente un “OK” (aggiungi inoltre alcune informazioni per trovare il contatore sulla pagina, le chiavi sono arbitrarie):

       #… if request.xhr? render json: { count: @content.get_likes.size, id: params[:id] } else #… 
    3. Costruisci un JS (preferirei CoffeeScript) per rispondere alla richiesta AJAX:

       # Rails creates this event, when the link_to(remote: true) # successfully executes $(document).on 'ajax:success', 'a.vote', (status,data,xhr)-> # the `data` parameter is the decoded JSON object $(".votes-count[data-id=#{data.id}]").text data.count return 

      Di nuovo, stiamo usando l’attributo data-id , per aggiornare solo i contatori interessati.

    Passa da uno stato all’altro

    Per cambiare dynamicmente il link da “mi piace” a “non mi piace” e viceversa, hai bisogno di queste modifiche:

    1. Modifica la tua vista:

       <% if current_user.liked? @content %> <%= link_to "Dislike", dislike_content_path(@content), class: 'vote', method: :put, remote: true, data: { toggle_text: 'Like', toggle_href: like_content_path(@content), id: @content.id } %> <% else %> <%= link_to "Like", like_content_path(@content), class: 'vote', method: :put, remote: true, data: { toggle_text: 'Dislike', toggle_href: dislike_content_path(@content), id: @content.id } %> <% end %> 

      Ancora: questo dovrebbe andare in un metodo di supporto (ad es. vote_link current_user, @content ).

    2. E il tuo CoffeeScript:

       $(document).on 'ajax:success', 'a.vote', (status,data,xhr)-> # update counter $(".votes-count[data-id=#{data.id}]").text data.count # toggle links $("a.vote[data-id=#{data.id}]").each -> $a = $(this) href = $a.attr 'href' text = $a.text() $a.text($a.data('toggle-text')).attr 'href', $a.data('toggle-href') $a.data('toggle-text', text).data 'toggle-href', href return return