0

I have Committee and Meeting objects. When creating a Meeting, I want to associate a Committee or Committees at the same time. CommitteeMeeting is a nested attribute of Meeting.

Following the solution here almost exactly, I get the following parameters:

--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
utf8: ✓
authenticity_token: us1hzugov7DDIpKNobOZJbuk14KsIsoz3uJRZEy2VRc=
meeting: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  date: '2001-01-03'
  room_id: '1'
  committee_meetings_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    '0': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
      committee_id: '1'
    '1': !ruby/hash:ActiveSupport::HashWithIndifferentAccess
      committee_id: '2'
commit: Create meeting
action: create
controller: meetings

The committee_meeting_attributes are properly nested, but in an array, which seems to be what is causing the error. Rails is expecting a hash. The solution I'm using as a reference gets a hash in the parameters.

    {"user"=>{"password_confirmation"=>"[FILTERED]", 
"roles_attributes"=>{"id"=>"2"}, ...

In this question, the developer got a similar error in his parameters, but his problem was not having the nested attributes accessible in the parent model. I do have the nested attributes accessible in the model.

Here is the view:

<% provide(:title, 'Create site') %>
<h1>Create meeting</h1>

<div class="row"> 
  <div class="span6 offset3">

    <%= form_for(@meeting) do |f| %>
    <%= render :partial => 'shared/error_messages', 
                           :locals => {:object => @meeting} %>

      <%= f.label :date %>
      <%= f.text_field :date %>

      <% @rooms.each do |room| %>
        <%= f.radio_button :room_id, room.id %> <%= room.name %><br />
      <% end %>

        <%= f.fields_for :committee_meetings do |builder| %>
          <% committee = Committee.find(builder.object.committee_id) %>
          <li><%= builder.check_box :committee_id, { :checked => false },
                        builder.object.committee_id %>
          <%= builder.label :committee_id, "#{committee.name}" %>
          </li>
        <% end %>

      <%= f.submit "Create meeting", class: "btn btn-large btn-primary" %>
    <% end %>
  </div>
</div>

Here is the Meetings controller:

class MeetingsController < ApplicationController
 def create
    @rooms = Room.all
    @committees = Committee.all
    @meeting = Meeting.new(params[:meeting])
    @meeting.creator_id = current_user.id
    @meeting.updater_id = current_user.id

  if @meeting.save
    flash[:success] = "You have succesfully created a meeting on #{@meeting.date}
                       in #{@meeting.room.site.name}, #{@meeting.room.name}!"
    redirect_to root_url 
  else
    render 'new'
  end
end

  def new
    @rooms = Room.all
    @meeting = Meeting.new
    @committees = Committee.all
  end 

Here is the model:

class Meeting < ActiveRecord::Base
attr_accessible :creator_id, :date, :room_id, :updater_id, :committee_meetings_attributes

  has_many :committee_meetings
  accepts_nested_attributes_for :committee_meetings, :allow_destroy => true

  has_many :committees, through: :committee_meetings

  belongs_to :room
  belongs_to :creator,     :class_name => 'User'
  belongs_to :updater,     :class_name => 'User'

end
Community
  • 1
  • 1
Sean
  • 1
  • 1
  • Does this actually show any checkboxes for committees? My understanding of `fields_for` is it will loop through the array, but your `new` object is an array of length 0, so it seems like this shouldn't do anything. – Geoff Jan 23 '13 at 17:40
  • It does display the checkboxes for committees. And, as the parameter snippet shows, the array includes the correct values for checked checkboxes. – Sean Jan 23 '13 at 19:26
  • I've done exactly what you want to do and could answer with how I did it, but since I don't understand how what you're currently doing works at all I'm a little hesitant. My way might be very stupid. – Geoff Jan 23 '13 at 20:37
  • Here's an (old) forum post which explains what I expected to happen with your code: http://railsforum.com/viewtopic.php?id=40329 – Geoff Jan 23 '13 at 20:37
  • I am having no problem building the form. It works fine. And, I'm gathering information from the form into the parameters. The problem is that somehow the form of the parameters for the nested attributes is causing the create action to croak. – Sean Jan 24 '13 at 16:46

1 Answers1

0

As I said in my comments, I can show you what I do but it may be too clever by half or there may be a much more direct way to accomplish it that I just don't know about.

For me, I would want all my committees to show in the same order each time so I first prebuild all the possible associations in my new and edit controllers as well as the failure case of create and update.

I have code here which will make sure all the possible associations exist, respect ones that are saved and orders them the same way each time:

Rails: How do I prepend or insert an association with build?

Then in my view, I use checkboxes to delete the ones I don't want saved.

= f.fields_for :committee_meetings do |cm|
  = cm.check_box :_destroy, {:checked => cm.object.persisted?}, 0, 1
  = cm.label :_destroy, cm.object.committee.name
  = cm.hidden_field :committee_id, :value => f.object.committee.id

Basically, I've reversed the polarity of the checkbox so it will send :_destroy if it's not checked or nothing if it is.

It works for me, and I'm sure you can get it to work for you. I'm afraid I can't say why your code is failing since I don't understand why it's even partially working. I'd prefer to just fix your issue, but perhaps this alternate method will help.

Community
  • 1
  • 1
Geoff
  • 2,208
  • 1
  • 16
  • 17