【问题标题】:Validation before saving Rails保存 Rails 之前的验证
【发布时间】:2013-01-11 02:44:34
【问题描述】:

我想在保存前执行验证,确定用户是否填写了特定字段、下方的付款金额字段并在提交表单之前选择了状态 =“已关闭”。如果他只做一个没有另一个,那么表单不应该保存

编辑页面

<%= simple_form_for @invoice, :html => { :class => 'form-horizontal' } do |f| %>
<%= render "shared/error_messages", :target => @invoice %>

<%= f.association :customer, disabled: @invoice.persisted? %>
<%= f.input :due_date, as: :string, input_html: { class: "datepicker" }, disabled:  @invoice.persisted? %>
<%= f.input :invoice_date, as: :string, input_html: { class: "datepicker" }, disabled: @invoice.persisted? %>
<%= f.input :payment_method, as: :select, :collection => [['Cash','Cash'],['Cheque','Cheque'],['In-House transfer','In-House transfer'],['Account Ledger','Account ledger']], :selected => ['Cash','Cash'] %>
<%= f.input :reference_no, :label => 'Payment Reference No', as: :string %>
<%= f.input :amount, as: :string %>
<%= f.input :payment_date, as: :string, input_html: {class: "datepicker"} %>
<%= f.input :status, as: :select, collection: Invoice::VALID_STATUS %>

VALID_STATUS = [ 'Draft', 'Open', 'Closed', 'Void' ] in Invoice.rb

我希望如果用户将状态更改为已关闭,他应该在表单中输入金额。用户不应该能够在不输入金额的情况下将状态更改为已关闭

【问题讨论】:

  • 您想在表单发布后在服务器端执行此操作,还是在发布表单之前在客户端执行此操作? (真的,正确的答案是两者都有,但你的问题是什么?)
  • jQuery 可以还是必须是原始的 javascript?您可以控制您使用的 javascript 库/插件吗?

标签: javascript ruby-on-rails ruby-on-rails-3 forms validation


【解决方案1】:

在模型中(app/models/invoice_model.rb)放

validate :close_must_have_amount

然后定义它(同一个文件)

def close_must_have_amount
  :status == 'closed' && :amount # May need to tweak this
end

要在客户端应用模型级别验证,您可以使用
https://github.com/bcardarella/client_side_validations/

【讨论】:

  • 我尝试使用您的方法并收到错误“未初始化的常量 Invoice::False”我将金额不为零更改为 !amount.nil?
  • 其实我认为你可以只使用数量(更新答案),因为这是活动记录并且属性将存在。
【解决方案2】:

如果你想在客户端做:

<script>
   $(document).ready(function(){
      $('#status').change(function(){
          if($(this).val() == "Closed" && ($('#amount').val() == null || $('#amount') == "")){
            alert("Amount must be needed when status is closed")
          }
        });
     });
</script>

【讨论】:

    【解决方案3】:

    1) Javascript 表单验证通常通过名称完成。

     function ValidateForm(){
         var form = document.forms['myForm'];
         if ((form['status'].value == "Closed") && !(form['amount'].value)){
             alert("You gave a 'Closed' status value, but did not provide an amount, please rectify this problem!");
             return(false);
         } else {
            return(true);
         }
     }
    

    然后:

             <%= simple_form_for @invoice, :onsubmit => "ValidateForm();", :html => { :class => 'form-horizontal', :name => 'myForm' } do |f| %>
             <%= f.input :amount, :html => { :name => 'amount'}, as: :string %>
             <%= f.input :status, as: :select, :html => { :name => 'status'}, collection: Invoice::VALID_STATUS %>
    

    一个简短的演练onSubmit 在提交表单时触发,但在它实际发布到服务器之前。

    由事件触发并以return(false); 终止的 javasccrtipt 函数将立即终止该事件,而return(true);(或几乎其他任何东西)使事件按计划继续。

    最后,请注意,完全依赖客户端验证是一个糟糕的主意,因为坚定的用户可能会执行以下操作:

    1) 打开 firebug 并检查标题等进行完全合法的提交。
    2) 制作他们自己的包含虚假/错误数据的 HTTP 请求。
    3) 通过任何一种 HTTP 工具提交。

    客户端验证是“很高兴拥有”。 服务器端验证是“必须的”。

    【讨论】:

    • +Abraham P,感谢您的回复。这很棒。那么在服务器端上面提出的问题我该怎么做
    • @zurik Michael Durrant 给出的解决方案是服务器端验证
    • 谢谢@checkit,这真的很有帮助
    • 添加了有关使用模型级别验证进行客户端验证的 gem 的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-05
    相关资源
    最近更新 更多