父模型不有效时的验证,嵌套属性和错误处理

时间:2015-05-08 17:50:54

标签: ruby-on-rails ruby-on-rails-4

最近我在我的应用程序中为其中一个模型添加了验证,这似乎引起了一种奇怪的行为,我在代码中没有正确处理。

这是一个假设的例子:

客户

# name: string, phone: string, address: string

class Client < ActiveRecord::Base
    has_many :transactions
    accepts_nested_attributes_for :transaction, allow_destroy: true

    validate :phone, numericality: true
end

交易

# p_date: date, location_id: integer

class Transaction < ActiveRecord::Base
    belongs_to :client
end

这就是控制器的样子(再次,请记住这是假设的):

PurchasesController

before_action :set_client, only: [:show, :edit, :update, :destroy]


def update
  respond_to do |format|
    if @client.update(client_params)
      format.html { redirect_to clients_path, notice: 'Updated Succesfully' }
      format.json { render :show, status: :ok, location: @client }
    else
      format.html { render :edit }
      format.json { render json: @client.errors, status: :unprocessable_entity }
    end
  end
end


def client_params
    params.require(:client).permit(
        :name, :phone, :address,
        transaction_attributes: [:id, :p_date, :location_id, :_destroy]
    )
end

def set_client
  @client = Client.find(params[:id])
end

对于新记录,这可以正常工作,但是当我遇到不符合电话号码中新验证规则的旧记录时,嵌套属性不会被保存,因为它的父记录是不再有效。

我试图找到解决此类错误的方法。

目前,这将由控制器中else中的if @client.update(client_params)条件处理。当发生错误时,控制器呈现:edit操作,这会导致我的视​​图中出现另一个错误,因此现在生成嵌套表单字段的帮助程序正在接收@client的空值。

产生错误的问题view如下所示:

购买/:CLIENT_ID / edit.html.haml

= form_for @client, :url => {:controller => 'purchase', :action => 'update'} do |f|
  - if @client.errors.any?
    #error_explanation
      %h2
        The following errors were found:
      %ul
        - @client.errors.full_messages.each do |message|
          %li= message
  =render 'form', f: f
  .actions
    =f.submit 'Save Changes', :class => 'btn btn-md btn-primary'

错误说:&#34;表格中的第一个参数不能包含nil或为空&#34;,我认为这是因为渲染不是发送客户端的ID。

如果您想知道,我使用form_for @client, :url => {:controller => 'purchase', :action => 'update'} do |f|导致此视图不在客户端控制器中。如果我省略了额外的参数,表单将直接发送到客户端控制器,该控制器具有仅与客户端模型相关的不同代码。

通过在更新操作中使用以下内容,我已部分设法解决此问题:

def update
  respond_to do |format|
    if @client.update(client_params)
      # *snip*
    else
      format.html { redirect_to edit_purchase_path(@client) }
      format.json { render json: @client.errors, status: :unprocessable_entity }
    end
  end
end

这会将我重定向回编辑操作,但不会打印错误。在编辑Transaction的值之前,我得到了一个相同的页面。我认为必须有一种简单的方法将错误发送回视图,但我不确定这些应该在哪里使用。

&#34;原作&#34;控制器是由脚手架生成的,因此render :edit部分来自脚手架本身。我知道我的例子可能有些模糊(我只是在抄写我经历过的事情),所以如果这听起来有点奇怪的话请耐心等待。如果提供的信息不够充分,我会很乐意详细说明。

0 个答案:

没有答案