0

I have an Order model like this:

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

I am struggling to make a nested form work to allow me to add both addresses in the same form. The params section of the Order is like this:

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])

My create action is like this:

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

When submitting this way, the form does not validate, all fields for billing_address being highlighted as incomplete.

If I use service_address_params and billing_adress_params I get an error of undefined local variable or method 'service_address_params'

I am stuck here for two days, so any help would be appreciated.

EDIT: new

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

EDIT: 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 %>

One of the partials for addresses:

<%= 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 %>

Billing address partial:

<%= 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 %>

The params hash:

--- !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
4
  • Can you post your new method of your controller? And also the form code Commented Aug 5, 2014 at 9:08
  • there are no validations inside address model. Commented Aug 5, 2014 at 9:10
  • I left them out. There are only for city_id and street. Commented Aug 5, 2014 at 9:16
  • Please post your billing_address partial too. Commented Aug 5, 2014 at 9:19

1 Answer 1

1

Firstly,using accepts_nested_attributes_for with a belongs_to is a pain and quite tricky as well.And secondly there are lot of mistakes in the code.I will be explaining one by one.

Mistake #1

Your new method should be like this

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

In your create method,you don't need these lines,remove them.

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

Mistake #2

Your order_params method should be like this

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

Notice the changes service_address_attributes and billing_address_attributes

Mistake #3

You are not passing locals to your service_address and billing_address partials.

These lines

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

should be like this

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

Update

Try calling the partials like this in the main form

<%= 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 %>

And change the code in your service_address and billing_address partials like this

#_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>
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the suggestions. I did the changes, but the billing_address fields still gets highlightetd. I edited the question and posted the params hash also:
If using nestead_attributes with belongs_to is a pain, what would be the best approach? Use has_many addresses and add an addres_type property?
@HMihail Please update your question with params hash,don't try to post it in my answer :)
@HMihail Did you restarted your server after the changes? And did the values save in to the DB?
I restarted the server. No data was saved, and the form still not validates, highlighting fields for billing address
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.