简体   繁体   中英

Reload ActiveRecordCollectionProxy after record creation via ajax

Been trying to implement a like button that will be disabled after create the record via ajax .Below is my code implementation .How do i make the user only able to click once and reload the page and disabled the button?.Current implementation works only when the page is reloaded manually.

My implementation idea : Load the like association relation user_id array via this line in the view

<% if listing.like.collect(&:user_id).include?(current_user.id)%>

and verify if the current_user is included in order to display the disabled button.

Models

class Listing < ActiveRecord::Base
   has_many   :like, foreign_key: :listing_id, dependent: :destroy
end 

class Like < ActiveRecord::Base  
  belongs_to  :listing
  belongs_to  :user
end

like Controller

class LikesController < ApplicationController  
before_filter :authenticate_user!

  def create 
     @like = Like.new(like_params)
     respond_to do|format|
     if@like.save
         current_user.create_activity(@like, "like")
       format.js
     else
        format.html (redirect_to root_url , notice:"Unable to proceed")
        format.js
     end
    end
  end

 [...]

end

Views

 <%=form_for(Like.new,:remote => true) do |f| %> 
       <%= f.hidden_field :listing_id, value: listing.id %>
       <%= f.hidden_field :user_id, value: current_user.id %>
       <% if (listing.like.collect(&:user_id).include?(current_user.id)) == true %>
             <%= f.button " " , class: 'round-button btn-center', data:{disabled: true} do %>
                <span class="glyphicon glyphicon-heart"></span>    
             <%end%>   
          <%else%>
              <%= f.button " " , class: 'round-button btn-center', data:{disable_with: "<i class='fa fa-spinner fa-spin'></i>"} do %>
                <span class="glyphicon glyphicon-heart"></span>    
             <%end%>
        <%end%>
      <%end%>

=>_listing.html.erb

<div class="item">
  <%= link_to (image_tag listing.image.url(:medium)), listing_path(listing) %>               
    <div class="info">
      <span class="item_title"><%= listing.name %></span>
        <%if listing.display_usd == true %>
          <span class="item_price"><%=number_to_currency(listing.price, unit:"$", precision: 2)%></span> 
        <% else %>
          <span class="item_price"><%=number_to_currency(listing.price, unit:"HTG", precision: 2)%></span> 
        <%end%>
      <span class="avatar_info">
         <%=link_to seller_path(listing.user.id) do %>
         <%=image_tag listing.user.avatar.url(:athumb), size: "20x20", 
             alt: "avatar",class: "img-circle has-tooltip ",
             title: listing.user.username , 'data-toggle' => 'tooltip', 'data-placement' => 'top'  %>
         <%end%>
      </span>

    </div>

    <% if listing.created_at >= (Date.today)%>
      <span class="label label-green">New</span>
    <%end%>

  <div class="block-actions clearfix">
    <%= render partial: "likes/form", listing: @listing %>
  </div>
</div>

You can create new file create.js.erb , in this file you can re-render your form and the content will be updated, eg:

$('#your-form-wrapper').html("<%= j render('likes/form') %>");

Tips: has_many :like should be has_many :likes , the association should be plural noun.

  listing.like.collect(&:user_id).include?(current_user.id) # yours
  listing.like.exists?(user_id: current_user.id) # better performance

If your record creating work successfully on your current code and functionality then ok current code for creating the record, now just need some updating this code for show disable button without reloading the whole page.

I don't know what is your view file name, in the view file you can declare an id like

#=> index.html.erb
<div id="like-form">
   <%= render partial: "likes/form", listing: @listing %>
</div>

Now create a partial and placed the form inside partial

#=> _like_form.html.erb
<%=form_for(Like.new,:remote => true) do |f| %> 
    <%= f.hidden_field :listing_id, value: listing.id %>
    <%= f.hidden_field :user_id, value: current_user.id %>
    <% if (listing.like.collect(&:user_id).include?(current_user.id)) == true %>
         <%= f.button " " , class: 'round-button btn-center', data:{disabled: true} do %>
            <span class="glyphicon glyphicon-heart"></span>    
         <%end%>   
    <%else%>
        <%= f.button " " , class: 'round-button btn-center', data:{disable_with: "<i class='fa fa-spinner fa-spin'></i>"} do %>
            <span class="glyphicon glyphicon-heart"></span>    
        <% end %>
    <% end %>
<% end %>

Now create a JS file which named with your view file like if I hold on view file is index.html.erb then JS file is index.js.erb

#=> index.js.erb
$("#like-form").html("<%= escape_javascript(render("likes/form", , listing: @listing)) %>");

Now update your controller create action

def create 
    @like = Like.new(like_params)
    respond_to do|format|
        if @like.save
            current_user.create_activity(@like, "like")
            format.html { redirect_to request.referer }
            format.xml  { render :xml => @like, :status => :created, :location => @like }
        else
            format.html (redirect_to request.referer , notice:"Unable to proceed")
        end
    end
end

Hope it helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM