views:

49

answers:

1

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

+1  A: 

Hi, 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 %>
jenjenut233
technically the client is already built. So in the form there is a select with a couple different clients. The user chooses a client and it builds the extra question fields.
Nate Bird
Adding the instance to the fields_for produced an error stating "unknown method 'build_client'... "
Nate Bird
Ahh, would have been good to know about the client already existing, it appeared you were trying to create the client at the same time as the event. If they're choosing the client AND modifying the client at the same time, it's definitely quite a bit more complicated using fields_for ... I would almost suggest not using fields_for for the client params and letting the controller parse out separate parameters to modify the client. Otherwise, you can use javascript to do some UI trickery... I'll update the post with an option for doing it.
jenjenut233
I updated the top post to explain a bit more of the workflow. I'm willing to change it. I'm looking for a simpler solution if possible.
Nate Bird
Ah, I see you have an observer rendering the fields_for form, that is good! Now you should have access to something like @client, use that where I previously had @event.build_client.
jenjenut233
yeah that works. Kind of. I don't think the form is being built corretly because I'm getting input ids like this: <input id="nil_class_questions_content" name="nil_class[questions][content]" size="30" type="text">
Nate Bird
Since I'm rendering a partial I should probably be passing some parameters to it. I'm not sure how to pass them back to the new partial. I've added the controller code to the top post.
Nate Bird
debugging right after the client fields_for I get the @client object just fine however the @event is nil.
Nate Bird
You need to set @event in the controller... but at this point, I think you definitely have the tools/answers you need to go forth and conquer ;) Sounds like we're getting into super-basic Rails functionality now, but if you have other questions about fields_for, by all means. :)
jenjenut233