`
lzqustc
  • 浏览: 206283 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

Rails批量删除(更新)

阅读更多

  对于Rails web应用,涉及到最频繁的操作就是增、删、查、改操作,因此为了满足用户体验,批量删除(或更新)操作是必不可少。

在Rails自动生成的模板中,每个控制器(Controller)都包含7个基本Action,即index、show、new、create、edit、update、destroy,每个Action都只能处理一个对象,而批量操作必然要求能够处理多个对象,为此需要自定义一个批量操作的Action,下面就介绍如何在Rails中实现批量删除功能。

首先,客户要求批量删除功能的效果,如下图所示:

 

 

上图首先以表格的方式列出来库表(departs)里的所以记录(表格每一行,就代表库表的一条记录),然后每一行的第一列设置了一个单选框,用于标记是否选中此行,最后通过  “删除选中”链接,即可完成批量删除被选中记录功能,而且还通过JS实现了选中全部记录的功能。

要实现上面的效果,本人采用的一个解决方案,步骤如下:

①、通过 JS文件实现,“全选”和“反选”功能,js代码如下:

/*全选*/

function checkall (s,k){

   var a = document.getElementsByTagName('input'); 

   var n = a.length;

   for (var i=0; i<n; i++){

       if((a[i].type == "checkbox") && ( a[i].name.substr(0,k-1)==s )){ 

       a[i].checked = true;

     } 

   }

}

 

/*反选*/

function uncheck (s,k){

   var a = document.getElementsByTagName('input'); 

   var n = a.length;

   for (var i=0; i<n; i++){

     if((a[i].type == "checkbox") &&  (a[i].name.substr(0,k-1)==s) ){ 

       if(a[i].checked == true){

          a[i].checked = false;

       }

       else{ a[i].checked = true; } 

     }

   }

}

function doall (s,k,n ){

 if( k ){  checkall (s,n ) }

 else{ uncheck (s,n ) } 

}

而在视图中首先是设计每一行的checkbox的id,然后在最后一个代表“全选”的checkbox中调用上面代码的doall 方法,由参数的不同实现,全选和反选。代码片段如下:每一行的checkbox:

  <td width="5%" align='left' height='30' valign='middle' >

      <%= check_box_tag  ' depart_ '   + depart.id .to_s ,'yes',false %>    

  </td>

 

生成的html代码就是如下格式:

<input  id ="depart_ 7198 "  type ="checkbox "  value ="yes "  name ="depart_7198 " />

 

最后代表“全选”的checkbox:

<input id="all" type="checkbox" onclick="doall ( depart ,this.checked,7 );" /> 全选

 

其中,根据需求要选中的是所有 id 类似于"depart_ 7198 "的 checkbox,但是后面的 7198是 变化的为此应将所有id含有 depart_ checkbox都选择,那么就需要进行配备即JS中的 a[i].name.substr(0,k-1)==s) 7 就是字符串“ depart_ ”的长度

 

②、实现 “删除选中”链接的功能。

通过分析Rails模板自带的删除(destroy)Action,以及视图中实现“删除”链接的代码:<%= link_to '删除', depart, :confirm => '是否确定?', :method => :delete %>,可知其实使用了一个变量 :method,用它来表示 Http的DELETE动作。因为浏览器不支持DELETE动作,所以,Rails 会生成一些javascript来解决这个问题:例如下面的代码

 

link_to 删除 ,depart,:confirm => 是否确定? ,   :method => :delete 

 

会自动生成相应的javascript代码,如下:
<a href="/departs/1"
   onclick="var f = document.createElement( form );
   f.style.display = none ; this.parentNode.appendChild(f);
   f.method =  POST ; f.action = this.href;
   var m = document.createElement( input );
   m.setAttribute( type hidden );
   m.setAttribute( name , _method );
  m.setAttribute( value , ’delete’); 

  f.appendChild(m);f.submit(); return false;">删除</a>


     这段javascript代码会生成一个form,把 Http 的DELETE动作放在隐藏变量里传递给服务器,然后,Rails 会判断这个变量,决定是否去调用Controller的destroy 方法。

 

那么仿照这段javascript代码,并加以适当处理,使得其中的form,包含多个记录,再设置链接的地址,使其能提交给事先在Controller里自定义好的批量删除方法:destroy_selected,那么就能够实现批量删除的功能。

由于这部分代码是使用 link_to 这个Helper 方法来构造一个链接,那么我们要实现的批量删除链接,就应该是重载这个link_to方法,但是重载link_to方法可能影响到其它链接的生成,为此需要自定义一个Helper方法:destroy_selected (action_name,paramsname,obj_id,url),即在application_helper.rb中添加该方法,代码如下:

 

def destroy_selected  ( action_name,paramsname,obj_id,url )

    "<a onclick=\"if (confirm('是否确定?')){        

       var f = document.createElement('form');

       f.style.display = 'none';

       this.parentNode.appendChild(f);

       f.method = 'POST';

       var m = document.createElement('input');

       m.setAttribute('type', 'hidden');

       m.setAttribute('name', '_method');

        m.setAttribute('value', '#{action_name}');

       f.appendChild(m);

       var s = document.createElement('input');

       s.setAttribute('type', 'hidden');

       s.setAttribute('name', ' authenticity_token ');

       s.setAttribute('value', authenticity_token);

       f.appendChild(s);

       var a = document.getElementsByTagName('input');

       var n = a.length;

       ii = 0

       for (var i=0;i<n;i++){

        if((a[i].type == 'checkbox' )&& (a[i].checked == true ) && 

           (a[i].id != 'all')){

           var s = document.createElement('input');

           s.setAttribute('type', 'hidden');

            s.setAttribute('name', '#{paramsname}');

           s.setAttribute('value', a[i].name.slice(#{obj_id}) );

           f.appendChild(s);

           ii = ii + 1

         }

       }

       if (ii > 0){ f.action = this.href;  f.submit(); }

     };

    return false;\"  href=\"" + url_for(url).to_s+"\"  >删除选中</a> "

end

   

上面的代码主要处理了4个事件,即粗体部分:下面简要分析

    1)、 m.setAttribute('value', '#{action_name}');  根据传入的参数确

        定链接要提交的目标action.

    2)、 s.setAttribute('name', ' authenticity_token '); 由于Rails的安

        全机制,需要为该方法传入 authenticity_token。

3)、 s.setAttribute('name', '#{paramsname}');

    s.setAttribute('value', a[i].name.slice(#{obj_id}) );

     为form添加被选择的需要删除的记录,然后以参数形式,传给action。

4)、 href=\"" + url_for(url).to_s+"\", 设置链接地址。

 

根据上面的方法,在视图中的 “删除选中”链接代码就是

<%=destroy_selected ('destroy_selected ','depart_id[] ',7 [:destroy_selected,:departs]) %>

 

 

接下来就是,DepartsController里的destroy_selected方法了:

def destroy_selected

  respond_to do |format|

    if not params[:depart_id] .nil?

      begin 

        Depart.transaction do

          params[:depart_id].each do |did|

           if did != ""

              @depart = Departs.find(did)

              @depart.destroy

            end

          end 

        end 

        flash[:notice] = "删除数据成功!"     

      rescue     

        flash[:notice] = "删除数据失败!"     

      end    

    else 

      flash[:notice] = '请选择要删除的部门!'

    end

    format.html { redirect_to(departs_url) }

    format.xml  { head :ok }

  end

end

 

 

首先,根据前面的设计,“删除选择”链接提交时会通过form传出参数(数组):depart_id[],然后destroy_selected方法遍历depart_id[],再通过@depart = Departs.find(id);@depart.destroy 来逐个删除;为了保证数据安全和同步,代码中还使用了数据库的事务机制:Depart.transaction do,这样只要其中一条记录删除失败,那么所有记录都不会被删除。

 

最后,还要在路由中配置这个action的url ,即:

map.resources :departs,:collection => { :destroy_selected => :post}

 

这样,只要为数据库的每一张表对应的Controller都设计一个action——destroy_selected,那么就可以轻松地实现资源的批量删除工作。而其它批量操作(批量更新、排序....)都可以仿照上面的方法,加以实现。

        

  • 大小: 21.4 KB
分享到:
评论
6 楼 lzqustc 2013-03-05  
这个都是2009年的事了,估计当时的rails版本2.3.0比较低,所以....
5 楼 lzqustc 2013-03-05  
这个都是2009年的事了,估计当时的rails版本2.3.0比较低,所以....
4 楼 dohkoos 2012-12-14  
3 楼 chen_miao 2012-06-21  
请问你这是不是rails 3.2.1
2 楼 lzqustc 2011-02-15  
samwalt 写道
请问必须使用javascript才能实现吗?

以上只是我个人找到的一个解决方案,我相信一定有更好的实现方式(不一定必须用javascript)
1 楼 samwalt 2011-01-17  
请问必须使用javascript才能实现吗?

相关推荐

    batch_request_api, 在 Rails 应用程序上,提供批处理操作的ruby 中间件.zip

    batch_request_api, 在 Rails 应用程序上,提供批处理操作的ruby ...更新和删除的Rails 中间件 gem 。可以定制的中间件批量创建。更新和删除记录或者并行删除记录安装将此行添加到你的应用程序的Gemfile中:gem 'ba

    bulk_discounts

    可以创建,更新和删除这些折扣。概述此Rails应用程序模拟一个商业智能应用程序,该应用程序显示记录及其关联的记录,并允许用户对这些记录执行CRUD操作。 资源展示了一对多和多对多的关系。Heroku部署状态:已部署...

    image-repo:对于Shopify 2021年夏季的开发实习生挑战。 这是一个构建为Web应用程序的图像存储库,用户可以在其中查看和上传他们的图像(一对一或批量),添加标题字幕并控制其公共_私人可见性

    此Web应用程序具有身份验证/授权功能,图像的安全上载/存储/删除,一对一或批量上载以及图像的访问控制。 它也已部署在Heroku上! 签出: : 如何使用注册一个帐户,在“上传”标签中上传1张或多张图片,然后填写...

    jQuery File Upload文件上传插件-其他

    jQuery File Upload 是一个 jQuery 图片上传组件,支持多文件上传、取消、删除,上传前缩略图预览、列表显示图片大小,支持上传进度条显示;支持各种动态语言开发的服务器端。 特征: 1、多文件上传: 允许一次选择...

    MongoDB权威指南(中文版)高清

    152.6.1 基本数据类型 152.6.2 数字 172.6.3 日期 182.6.4 数组 192.6.5 内嵌文档 192.6.6 _id和ObjectId 20第3章 创建、更新及删除文档 233.1 插入并保存文档 233.1.1 批量插入 233.1.2 插入:...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    中文名: 经典Java EE企业应用实战--基于WebLogic/JBoss的...11.4 批量更新和批量删除 478 11.4.1 批量更新 479 11.4.2 批量删除 480 11.5 原生SQL查询 481 11.5.1 使用原生SQL查询 481 11.5.2 结果集映射和实体查询 482...

    java开源包1

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包11

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包2

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包3

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包6

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包5

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包10

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包4

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包8

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包7

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包9

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包101

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    Java资源包01

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    JAVA上百实例源码以及开源项目源代码

    从内存中清除,从账户中取出amt,如果amt&gt;账户余额抛出异常,一个实体Bean可以表示不同的数据实例,我们应该通过主键来判断删除哪个数据实例…… ejbCreate函数用于初始化一个EJB实例 5个目标文件,演示Address ...

Global site tag (gtag.js) - Google Analytics