Nate Bird
Nate Bird

Reputation: 5335

Accepting nested attributes on a belongs_to association

I have a complex form for scheduling events. Here are the abbreviated associations:

class Event < ActiveRecord::Base
  belongs_to :client
  accepts_nested_attributes_for :client, :reject_if => lambda { |a| a[:name].blank? }
end

class Client < ActiveRecord::Base
  has_many :events
  has_many :questions, :dependent => :destroy
  accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }
end

The form is creating a new event and I have the following structure:

- form_for @event do |event_form|
    %select=collection_select(client_options_for_select, :options, :group_name, :id, :name, @event.client_id)

   - event_form.fields_for :client do |client|
     = client.text_field :name

     - client.fields_for :questions do |question|
       = question.text_field :content

The client already exists and is chosen from a select menu. An observer renders the nested attributes form by setting the client variable in a controller action and then rendering the partial.

Here is the error I'm getting:

ActionView::TemplateError (wrong number of arguments (0 for 1)) on line #1 of app/views/proceedings/_questions.html.haml:
1: - event_form.fields_for :client do |client|

app/views/proceedings/_questions.html.haml:1:in `form'
app/views/proceedings/_questions.html.haml:1:in `_run_haml_app47views47events47_client_questions46html46haml_locals_client_questions_object'
haml (3.0.21) rails/./lib/haml/helpers/action_view_mods.rb:13:in `render'
app/controllers/proceedings_controller.rb:261:in `__instance_exec0'
app/controllers/proceedings_controller.rb:260:in `corp_client_questions'
app/controllers/proceedings_controller.rb:258:in `corp_client_questions'

I'm having problems (I think) with the belongs_to association between Event and Client. I don't know if Event can accept nested attributes of Client when the Event belongs_to the Client. I've always done it the other way around (Client accepts nested attributes of Event).

Any ideas? I can elaborate if you need more code or background. Thanks!

Update: Added controller code as requested.

def client_questions
if params[:client_id].blank?
  render_no_client_questions
elsif @client = Client.find(params[:client_id]) and @client.is_unspecified?
  render_no_client_questions
else
  respond_to do |format|
    format.js {
      render :update do |page|
        page[:client_questions].replace_html :partial => 'client_questions', :layout => false
      end
    }
  end
end

end

Upvotes: 4

Views: 7031

Answers (3)

Sia
Sia

Reputation: 9212

In your controller method(s), you need to add:

@event.build_client

The form cannot display fields_for when it does not have a valid object. Most of the time, we use something like @event.client.build, but this will not work with a belongs_to association. That method is only valid with has_many and has_and_belongs_to_many.

Reference here.

Upvotes: 0

pastullo
pastullo

Reputation: 4201

I had the same issue using accepts_nested_attributes_for :address on a belongs_to :address association for my Order object.

The field_for wasn't echoing nothing, but all it took was adding @order.build_address() and that made it work.

I think is because we are using the association sort of reversed from the usual, so you have to manually create the association.

Upvotes: 2

jenjenut233
jenjenut233

Reputation: 1938

try adding an instance of the fields_for object in the options... generally a symbol isn't enough when creating a new top-level form object... Try the following, but yes it is possible to accept nested attributes on a belongs_to.

<%= event_form.fields_for :client, @client do |client| %>
  <%= client.text_field :name %>
  <%= client.fields_for :questions, Question.new do |question| %>
    <%= question.text_field :content %>
  <% end %>
<% end %>

Upvotes: 8

Related Questions