【问题标题】:Rails 4 nested form with double association具有双重关联的 Rails 4 嵌套形式
【发布时间】:2014-08-05 09:06:04
【问题描述】:

我有一个这样的订单模型:

class Order < ActiveRecord::Base
  belongs_to :service_address, class_name: 'Address'
  belongs_to :billing_address, class_name: 'Address'

  accepts_nested_attributes_for :service_address, allow_destroy: true
  accepts_nested_attributes_for :billing_address, allow_destroy: true
end

class Address < ActiveRecord::Base

end

我正在努力使嵌套表单工作,以允许我以相同的表单添加两个地址。 Order 的 params 部分是这样的:

params.require(:order).permit(:contract_id, :billing_address_id, :service_address_id, :valid_from, :valid_to, :contact_person_id, :billing_mode,
                                service_address: [:city_id, :street_id, :number, :block, :entrance, :floor, :apartment, :_destroy],
                                billing_address: [:city_id, :street_id, :number, :block, :entrance, :floor, :apartment, :_destroy])

我的创建动作是这样的:

@order = Order.new(order_params)
@order.service_address = Address.new(params[:order][:service_address])
@order.billing_address = Address.new(params[:order][:billing_address])

以这种方式提交时,表单不会验证,billing_address 的所有字段都被突出显示为不完整。

如果我使用service_address_paramsbilling_adress_params,我会收到undefined local variable or method 'service_address_params' 的错误

我被困在这里两天,所以任何帮助将不胜感激。

编辑:new

def new
  @order = Order.new
  @order.service_address = Address.new
  @order.billing_address = Address.new
end

编辑:form

<%= simple_form_for @order, data: {validate: 'parsley'} do |f| %>
  <%= f.input :contract_id, as: :hidden, :input_html => { :value => @contract_id } %>
  <%= f.input :same_billing_address, as: :hidden, :input_html => { :value => 0 } %>

  <%= f.error_notification %>

  <%= render :partial => 'order_data', :locals => { f: f } %>
  <%= render :partial => 'service_address' %>
  <%= render :partial => 'billing_address' %>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

地址的一部分:

<%= simple_fields_for :service_address do |sa| %>
  <div class="form-inputs" id="inputs-step2">
    <%= sa.input :city_id, label: 'Oras', collection: @cities, input_html: { 'data-parsley-group' => "block2", :required => true, id: 'service_address_city_id' } %>
    <%= sa.input :street_id, label: 'Strada', collection: @streets, input_html: { 'data-parsley-group' => "block2", :required => true, id: 'service_address_street_id' } %>
    <%= sa.input :number, label: 'Numar', input_html: { 'data-parsley-group' => "block2", :required => true } %>
    <%= sa.input :block, label: 'Bloc' %>
    <%= sa.input :entrance, label: 'Scara' %>
    <%= sa.input :floor, label: 'Etaj' %>
    <%= sa.input :apartment, label: 'Apartament' %>
  </div>
<% end %>

帐单地址部分:

<%= simple_fields_for :billing_address do |ba| %>
  <div class="form-inputs" id="inputs-step3">
    <%= ba.input :city_id, label: 'Oras', collection: @cities, input_html: { 'data-parsley-group' => "block3", :required => true, id: 'billing_address_city_id' } %>
    <%= ba.input :street_id, label: 'Strada', collection: @streets, input_html: { 'data-parsley-group' => "block3", :required => true, id: 'billing_address_street_id' } %>
    <%= ba.input :number, label: 'Numar', input_html: { 'data-parsley-group' => "block3", :required => true } %>
    <%= ba.input :block, label: 'Bloc' %>
    <%= ba.input :entrance, label: 'Scara' %>
    <%= ba.input :floor, label: 'Etaj' %>
    <%= ba.input :apartment, label: 'Apartament' %>
  </div>
<% end %>

参数哈希:

--- !ruby/hash:ActionController::Parameters
utf8: ✓
authenticity_token: nZvowtR+Iwo/Rt420w55ZSzNtiZCrjga57dSimDPdg0=
order: !ruby/hash:ActionController::Parameters
  contract_id: ''
  same_billing_address: '0'
  valid_from: '2013-08-04'
  months: '12'
  billing_mode: '1'
service_address: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  city_id: '1'
  street_id: '19'
  number: '1'
  block: '1'
  entrance: '1'
  floor: '1'
  apartment: '1'
billing_address: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  city_id: '1'
  street_id: '19'
  number: '2'
  block: '2'
  entrance: '2'
  floor: '2'
  apartment: '2'
commit: Create Order
action: create
controller: orders

【问题讨论】:

  • 您可以发布您的控制器的new 方法吗?还有form code
  • 地址模型内没有验证。
  • 我把它们排除在外了。只有city_id和street。
  • 请也发布您的billing_address 部分。

标签: ruby-on-rails-4 nested-attributes strong-parameters


【解决方案1】:

首先,将accepts_nested_attributes_forbelongs_to 一起使用是一种痛苦,也相当棘手。其次,代码中有很多错误。我会一一解释。

错误 #1

你的new方法应该是这样的

def new
  @order = Order.new
  @order.build_service_address 
  @order.build_billing_address
end

在您的create 方法中,您不需要这些行,请将它们删除。

@order.service_address = Address.new(params[:order][:service_address])
@order.billing_address = Address.new(params[:order][:billing_address])

错误 #2

你的order_params方法应该是这样的

def order_params
 params.require(:order).permit(:contract_id, :billing_address_id, :service_address_id,    :valid_from, :valid_to, :contact_person_id, :billing_mode,service_address_attributes: [:city_id, :street_id, :number, :block, :entrance, :floor, :apartment, :_destroy],billing_address_attributes: [:city_id, :street_id, :number, :block, :entrance, :floor, :apartment, :_destroy])
end

注意 service_address_attributesbilling_address_attributes 的变化

错误 #3

您没有将locals 传递给您的service_addressbilling_address 部分。

这些行

<%= render :partial => 'service_address' %>
<%= render :partial => 'billing_address' %>

应该是这样的

<%= render :partial => 'service_address',:locals => { f: sa }%>
<%= render :partial => 'billing_address',:locals => { f: ba } %>

更新

尝试在main form 中像这样调用partials

<%= f.simple_fields_for :service_address do |sa| %>
  <%= render :partial => 'service_address',:locals => { f: sa }%>
<% end %>

<%= f.simple_fields_for :billing_address do |ba| %>
  <%= render :partial => 'billing_address',:locals => { f: ba } %>
<% end %>

并像这样更改service_addressbilling_address partials 中的代码

#_service_address.html.erb
<div class="form-inputs" id="inputs-step2">
    <%= f.input :city_id, label: 'Oras', collection: @cities, input_html: { 'data-parsley-group' => "block2", :required => true, id: 'service_address_city_id' } %>
    <%= f.input :street_id, label: 'Strada', collection: @streets, input_html: { 'data-parsley-group' => "block2", :required => true, id: 'service_address_street_id' } %>
    <%= f.input :number, label: 'Numar', input_html: { 'data-parsley-group' => "block2", :required => true } %>
    <%= f.input :block, label: 'Bloc' %>
    <%= f.input :entrance, label: 'Scara' %>
    <%= f.input :floor, label: 'Etaj' %>
    <%= f.input :apartment, label: 'Apartament' %>
  </div>

#_billing_address.html.erb
<div class="form-inputs" id="inputs-step3">
    <%= f.input :city_id, label: 'Oras', collection: @cities, input_html: { 'data-parsley-group' => "block3", :required => true, id: 'billing_address_city_id' } %>
    <%= f.input :street_id, label: 'Strada', collection: @streets, input_html: { 'data-parsley-group' => "block3", :required => true, id: 'billing_address_street_id' } %>
    <%= f.input :number, label: 'Numar', input_html: { 'data-parsley-group' => "block3", :required => true } %>
    <%= f.input :block, label: 'Bloc' %>
    <%= f.input :entrance, label: 'Scara' %>
    <%= f.input :floor, label: 'Etaj' %>
    <%= f.input :apartment, label: 'Apartament' %>
  </div>

【讨论】:

  • 感谢您的建议。我进行了更改,但 billing_address 字段仍然被突出显示。我编辑了问题并发布了参数哈希:
  • 如果使用nestead_attributesbelongs_to 很痛苦,那么最好的方法是什么?使用has_many 地址并添加addres_type 属性?
  • @HMihail 请用params hash 更新您的问题,不要尝试在我的回答中发布它:)
  • @HMihail 更改后您是否重新启动了服务器?这些值是否保存到数据库中?
  • 我重启了服务器。未保存任何数据,表单仍未验证,突出显示 billing address 的字段
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
  • 1970-01-01
相关资源
最近更新 更多