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" οnclick="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"
   οnclick="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 οnclick=\"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,那么就可以轻松地实现资源的批量删除工作。而其它批量操作(批量更新、排序....)都可以仿照上面的方法,加以实现。

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值