How to perform Controller.destroy action asynchron

2019-05-21 06:14发布

I can easily delete the entries of post synchronously in rails application by following code:

views

<% @post.each do |post| %>
 <tr>
   <td colspan="3"><%= link_to 'Destroy', post, :method => :delete, :confirm => 'Are you sure?', :class => 'btn btn-mini btn-danger' %></td>
 </tr>
<% end %>

Controller class

def destroy
 @post = Post.find(params[:id])
 @post.destroy
 respond_to do |format|
   format.html redirect_to(posts_url) }
   format.xml  { head :ok }
 end
end

This works fine. How make this destroy process async. So, that I will not required to add route or refresh the page.

Edit

Adding more explanation

Task is to make destroy method async. So that the client will not wait for the response and destroy method will run in background async. Also the destroy method has no guaranteed completion time.

Another example could be: I have to delete multiple post at a time.

2条回答
叼着烟拽天下
2楼-- · 2019-05-21 06:37

For making Async request you need Ajax and basic javascript to remove the code of <td>.

First change your views code to :

<% @post.each do |post| %>
<tr>
  <td colspan="3"><%= link_to 'Destroy', post, :method=> :delete, id: post.id, :class => 'btn btn-mini btn-danger', data: { confirm: 'Are you Sure?', remote: true } %> </td>
</tr>
<% end %>

Above code says that it will call the destroy method of PostController class. Now you need to make some changes in destroy method of controller class

def destroy
 @post = Post.find(params[:id])
 @post.destroy
 respond_to do |format|
   format.js 
   format.html { redirect_to(posts_url) }
 end
end

Above code is pretty understandable, except why we use respond_to. In rails we can render the data in two ways:

  1. Javascript

  2. HTML

we will use javascript to render the code because it's a easy way to remove the <td> tag with the help of ID.

Now we need a js file to render the response of destroy method. To do this add destroy.js.erb in the same folder of your views.

Add this following code in destroy.js.erb:

 var element = document.getElementById("<%= @post.id %>");
 element.parentNode.parentNode.remove();

You are done! I will recommend you to read : http://www.gotealeaf.com/blog/the-detailed-guide-on-how-ajax-works-with-ruby-on-rails

查看更多
Animai°情兽
3楼-- · 2019-05-21 06:44

Try remote: true option,

<%= link_to 'Destroy', post, :method => :delete, remote: true, :confirm => 'Are you sure?', :class => 'btn btn-mini btn-danger' %>

def destroy
  @post = Post.find(params[:id])
  @post.destroy

  # Just Guessing you have @posts to refresh and `posts_template` using it.
  @posts = Post.all 

  respond_to do |format|
    format.html redirect_to(posts_url) }
    format.xml  { head :ok }
    format.js { render 'posts.js.erb' }
  end
end

posts.js.erb

$('some_element').replaceWith('<%=j render 'posts_template' %>');

Please change as you need. I am just guessing.

查看更多
登录 后发表回答