在rails中优雅的进行模型校验

      在用rails进行开发时,最常见的操作的是前台提交表单,后台保存相关的模型对象,对于一个复杂的表单,可能需要保存的模型对象不止一个,但这些对象在保存之前都是要经过合法性检验的,请看如下的场景,一个表单提交了订单信息、用户基本资料、用户所在地,那么后台需要对用户、订单、地点这3个对象进行校验并做相关处理,通常会用到error_messages_for做错误信息输出, 具体有以下3种做法:

 

1

if @user.save && @order.save && @city.save
  #跳转到成功页面
  else
  #返回原来页面
end

 

   这里存在的问题是,加入前两个模型合法性校验通过,但最后一个模型出现问题,那么原本3个对象都不该被保存,但前两个对象已经被保存,所以存在严重的脏数据问题

 

2

 

if @user.valid? && @order.valid? && @city.valid?
  @user.save
  @order.save
  @city.save
  #跳转到成功页面
else
  #返回原页面
end

 

      这个方法倒是不存在脏数据问题,但是如果第一个模型对象出现合法性问题,那么程序将停止之后的合法性校验,所以显示返回页面的错误提示将不完整,严重影响了系统的用户体验。

 

3 利用事务,基于第一种方法之上,如果任何一个模型合法性出现合法性问题,将采取数据库回滚操作,个人认为这种方法不仅复杂,性能也不高。

 

 

那么以下有个比较简洁的方法解决这样的问题

 

  def new
    @users = User.new
    @city = City.new
    @order = Order.new
  end
  
  def create
    @city = City.new params[:city]
    
    @user = User.new params[:user]
    @user.city = @city
    
    @order = Order.new params[:order]
    @order.user = @user

    unless [@user, @city, @order].map(&:valid?).include?(false)
      @user.save
      @city.save
      @order.save
      redirect_to "/main/new"
    else
      render :action => "new"
    end
  end

 

 

 关键在于这句:

 

 unless [@user, @city, @order].map(&:valid?).include?(false) 

 

在保存之前就遍历各个模型,并运行valid?方法,之后判断结果列表中是否包括false,以此作为判断合法性的依据,并且不会造成脏数据的问题。

 

 

相关的view如下所示,关于错误汉化这里不做讨论

 

<%= error_messages_for :user %> 
<%= error_messages_for :city %> 
<%= error_messages_for :order %> 

<% form_for :user, :url => "/main/create" do |f| %> 
  <fieldset>     
    <legend>用户信息</legend>     
    <ol>       
      <li>        
        <%= f.label :name %>        
        <%= f.text_field :name %>      
      </li>     
    </ol>  
  </fieldset>   
  <% fields_for :city do |city| %>     
    <fieldset>       
      <legend>地点信息</legend>      
      <ol>     
        <li>      
          <%= city.label :code %>   
          <%= city.text_field :code %>       
        </li>       
      </ol>     
    </fieldset>   
  <% end %> 

  <% fields_for :order do |order| %>  
    <fieldset>       
      <legend>订单信息</legend>     
      <ol>      
        <li>           
          <%= order.label :price %>          
          <%= order.text_field :price %>        
        </li>    
      </ol>     
    </fieldset>
  <% end %>
  <%= f.submit '提交' %> 
<% end %>


 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值