【问题标题】:Deleting Multiple Records in Rails在 Rails 中删除多条记录
【发布时间】:2009-12-04 04:32:28
【问题描述】:

我正在开发一个允许用户选择多个条目的应用程序。一旦选择了这些条目,用户就可以选择将它们全部删除。单击删除按钮时(在选择一个或多个条目后),将显示一个模式对话框窗口,显示用户使用确认按钮选择的条目。

目前,以上所有操作都是在客户端使用 jQuery 完成的。我已设法将其全部设置好,以便确认按钮(使用:method => :deletelink_to)具有/entries/12,13,16,17 的URL,其中数字代表用户选择的条目的ID。我也尝试过发送格式为/entries/[1,2,3,4] 的网址,但没有成功。我感觉我没有发送 real 数组。

这是我的删除方法,当使用一个 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

当我发送多个 id(格式为1,2,3,4,5)时,只有第一个条目被删除,其余条目保持不变。这是执行操作后我的 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

如您所见,发送了 ID ("id"=>"19,22"),但只加载了第一个条目。之后,它的相关标签被删除(我正在使用acts_as_taggable_on 插件)。然后,第一个条目 (id => 19) 被销毁,用户被重定向回条目列表页面。

应该为每个传递的 id 重复该过程(向上重定向)。我很困惑,因为RoRs docs 声明:

id - 可以是整数或 整数数组。

我做错了什么?我觉得我很接近,我可以品尝它!让所有 jQuery 工作对我来说是一个巨大的胜利,所以现在我知道处理多个 id 的控制器方法中唯一缺少的部分。

【问题讨论】:

    标签: jquery ruby-on-rails arrays


    【解决方案1】:

    有一个 ActiveRecord 方法可以完全按照您的意愿行事——请查看destroy_all。它期望删除一个字符串、数组或 id 散列。

    我经常为destroy_multiple 的控制器添加另一个动作——不要忘记添加收集路由:

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

    【讨论】:

    • 关于单独操作的要点很好,但是destroy 可以很好地满足这里的需求,因为它接受单个 id 或数组。
    【解决方案2】:

    快速修复:

    我个人会以不同的方式发送ids,但我不想弄乱您的路由。所以这会起作用,但我只解决destroy 部分:

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

    这使它的范围为current_user,但直接使用id数组调用destroy函数。

    更好的方法:

    我建议如何让它更明显是这样的:

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

    我知道这更长,但它更符合 Rails 的自然工作方式。然后在控制器上:

    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
    

    现在您的函数支持普通的单个 destroy 操作以及您的新多个 destroy

    【讨论】:

    • 这违反了 RESTful 约定,应该放在另一个动作中。
    【解决方案3】:

    您是否尝试调试并检查 @entry 中返回的内容。我认为您可能没有得到整个数组。您可以尝试使用 ruby​​-debug 插件来调试您的代码。 附带说明,使用 GET 删除可能not be the best 选项

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        这是朋友帮我想出的:

        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
        

        我确信这一切都可以做得更好、更有效,但对于 Alpha 来说,这会奏效。感谢大家的帮助!

        【讨论】:

        • "inefficient",因为它为每个 find 单独调用数据库,而不是一次获取它们。
        • 我确实尝试了上述解决方案,但都没有成功。我真的很感谢您为帮助我付出的时间和精力。老实说,我无意浪费任何人的时间。我相信上面的解决方案将来会派上用场,但现在我需要让一些东西快速工作。希望您能理解并再次感谢。
        • @shaunandrews 很抱歉对尝试解决方案感到沮丧。我正在删除我原来的评论,这样我就不会觉得自己是个混蛋了 :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-23
        • 2023-03-20
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多