最近我在我的应用程序中为其中一个模型添加了验证,这似乎引起了一种奇怪的行为,我在代码中没有正确处理。
这是一个假设的例子:
客户
# 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
部分来自脚手架本身。我知道我的例子可能有些模糊(我只是在抄写我经历过的事情),所以如果这听起来有点奇怪的话请耐心等待。如果提供的信息不够充分,我会很乐意详细说明。