简体   繁体   English

在 Rails 中删除多条记录

[英]Deleting Multiple Records in Rails

I'm working on an application that allows user to select multiple entries.我正在开发一个允许用户选择多个条目的应用程序。 Once those entries are selected, the user can choose to delete them all.一旦选择了这些条目,用户就可以选择将它们全部删除。 When clicking on the delete button (after selected one or more entries), a modal dialog window is displayed showing the entries that the user has selected with a confirmation button.单击删除按钮时(在选择一个或多个条目后),会显示一个模式对话窗口,显示用户已通过确认按钮选择的条目。

Currently, all of the above is done using jQuery on the clientside.目前,以上所有内容都是在客户端使用 jQuery 完成的。 I've managed to get it all set so that the confirmation button (which is a link_to using the :method => :delete ) has a URL of /entries/12,13,16,17 where the numbers represent the id's of the entries that the user selected.我已经设法将其全部设置好,以便确认按钮(这是一个使用:method => :deletelink_to )具有/entries/12,13,16,17的 URL,其中数字表示用户选择的条目。 I've also tried sending the url with the format of /entries/[1,2,3,4] with no luck.我也试过用/entries/[1,2,3,4]格式发送网址,但没有成功。 I have a feeling I'm not sending a real array.我有一种感觉,我没有发送一个真正的数组。

Here's my delete method, which works perfectly fine when one id is used (ie /entries/1 ), and would hopefully continue to work with one id:这是我的删除方法,当使用一个 id(即/entries/1 )时它工作得很好,并且希望继续使用一个 id:

def destroy
 @entry = current_user.entries.find(params[:id])
 @entry.destroy

 respond_to do |format|
  format.html { redirect_to(entries_url) }
  format.xml  { head :ok }
 end
end

When I send multiple id's (in the format of 1,2,3,4,5 ), only the first entry is deleted, while the rest are left untouched.当我发送多个 id 的(格式为1,2,3,4,5 )时,只有第一个条目被删除,而其余的则保持不变。 Here is what my webrick log looks like after performing the action:这是我的 webrick 日志在执行操作后的样子:

Processing EntriesController#destroy (for 127.0.0.1 at 2009-12-03 23:07:24) [DELETE]
  Parameters: {"action"=>"destroy", "_method"=>"delete", "id"=>"19,22", "controller"=>"entries"}
  User Load (0.3ms)   SELECT * FROM "users" WHERE ("users"."id" = '2') LIMIT 1
  User Update (0.3ms)   UPDATE "users" SET "updated_at" = '2009-12-04 04:07:24', "last_request_at" = '2009-12-04 04:07:24' WHERE "id" = 2
  Entry Load (0.2ms)   SELECT * FROM "entries" WHERE ("entries"."id" = 19 AND ("entries".user_id = 2)) 
  Tagging Load (0.4ms)   SELECT * FROM "taggings" WHERE ("taggings".taggable_id = 19 AND "taggings".taggable_type = 'Entry' AND (taggings.context = 'tags')) 
  Tag Load (0.2ms)   SELECT * FROM "tags" WHERE ("tags"."id" IN (22,23,24,29)) 
  Tagging Destroy (0.2ms)   DELETE FROM "taggings" WHERE "id" = 66
  Tagging Destroy (0.1ms)   DELETE FROM "taggings" WHERE "id" = 67
  Tagging Destroy (0.0ms)   DELETE FROM "taggings" WHERE "id" = 68
  Tagging Destroy (0.1ms)   DELETE FROM "taggings" WHERE "id" = 69
  Tagging Load (0.1ms)   SELECT * FROM "taggings" WHERE ("taggings".taggable_id = 19 AND "taggings".taggable_type = 'Entry') 
  Entry Destroy (0.1ms)   DELETE FROM "entries" WHERE "id" = 19
  Entry Load (0.5ms)   SELECT * FROM "entries" WHERE ("entries".user_id = 2) 
Redirected to http://localhost:3000/entries

As you can see, the ids are sent ( "id"=>"19,22" ) but only the first entry is loaded.如您所见,ID 已发送( "id"=>"19,22" )但仅加载了第一个条目。 After that, its associated taggings are deleted (I'm using the acts_as_taggable_on plugin).之后,它的关联标签被删除(我使用的是acts_as_taggable_on插件)。 Then, the first entry ( id => 19 ) is destroyed, and the user is redirected back to the entries listing page.然后,第一个条目 ( id => 19 ) 被销毁,用户被重定向回条目列表页面。

What is should do is repeat that process (up the the redirect) for each id passed.应该做的是为每个传递的 id 重复该过程(向上重定向)。 I'm confused, because the RoRs docs state that:我很困惑,因为RoRs 文档指出:

id - Can be either an Integer or an Array of Integers. id - 可以是整数或整数数组。

What am I doing wrong?我究竟做错了什么? I feel like I'm so close, I can taste it!我觉得我很近,我可以品尝它! It was a huge triumph for me to get all the jQuery working, so now I know the only piece missing in the controller method handling the multiple id's.让所有 jQuery 工作对我来说是一个巨大的胜利,所以现在我知道处理多个 id 的控制器方法中唯一缺少的部分。

There's an ActiveRecord method to do exactly what you want -- check out destroy_all .有一个 ActiveRecord 方法可以完全按照您的要求执行操作——请查看destroy_all It expects a string, array, or hash of ids to delete.它需要一个字符串、数组或要删除的 id 散列。

I often add another action to the controller for destroy_multiple -- don't forget to add the collection route as well:我经常为destroy_multiple的控制器添加另一个操作——不要忘记添加收集路由:

def destroy_multiple
  current_user.entries.destroy_all(:id => params[:user_ids])
  redirect_to entries_url
end

Quick Fix:快速解决:

I personally would send the ids a different way, but I don't want to mess up your routing.我个人会以不同的方式发送ids ,但我不想弄乱您的路由。 So this will work, but I am only addressing the destroy part:所以这会起作用,但我只解决destroy部分:

current_user.entries.destroy(params[:id].split(','))

This keeps it scoped to current_user but calls the destroy function directly with the array of ids.这使其作用域保持在current_user范围内,但直接使用 id 数组调用destroy函数。

The Better Way:更好的方法:

How I might suggest making it more obvious is something like this:我如何建议让它更明显是这样的:

Instead of /entries/12,13,16,17 I would use /entries/multiple?del[]=12&del[]=13&del[]=16&del[]=17而不是/entries/12,13,16,17我会使用/entries/multiple?del[]=12&del[]=13&del[]=16&del[]=17

I know that is longer, but it is more in line with how rails works naturally.我知道那更长,但它更符合 rails 的自然工作方式。 Then on the controller:然后在控制器上:

def destroy
   id = params[:id]
   id = (params[:del] || []) if(id == "multiple")

   current_user.entries.destroy(id)

   respond_to do |format|
     format.html { redirect_to(entries_url) }
     format.xml  { head :ok }
   end 
end

Now your function supports the normal single destroy action as well as your new multiple destroy .现在您的函数支持正常的单次destroy操作以及新的多次destroy

Did you try debugging and checking what is being returned in @entry .您是否尝试调试并检查 @entry 中返回的内容。 I think you might not be getting the entire array .我想你可能没有得到整个数组。 You can try using the ruby-debug plugin to debug your code .您可以尝试使用 ruby​​-debug 插件来调试您的代码。 On a side note , deleting using GET might not be the best option附带说明一下,使用 GET 删除可能不是最佳选择

您可以解析 params[:id] 并从中创建一个数组,然后使用它。

Here's what a friend helped me come up with:这是朋友帮我想出的:

def destroy
    params[:id].split(',').each do |id| 
        @entry = current_user.entries.find(id)
        @entry.destroy
    end

    respond_to do |format|
        format.html { redirect_to(entries_url) }
        format.xml  { head :ok }
    end
end

I'm sure this could all be done much better and more efficiently, but for an Alpha, this'll work.我相信这一切都可以做得更好、更有效,但对于 Alpha 来说,这会奏效。 Thanks for the help everyone!感谢大家的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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