1

I'm getting started with Ruby on Rails and I have encountered an issue with the has_many :through association.

The models I'm using are:

class Phrase < ActiveRecord::Base
  attr_accessible :event_type_id, :template_pieces

  belongs_to :event_type
  has_many :phrases_pieces
  has_many :template_pieces, :through => :phrases_pieces
end

class TemplatePiece < ActiveRecord::Base
  attr_accessible :datatype, :fixed_text, :name

  has_many :phrase_pieces
  has_many :phrases, :through => :phrases_pieces
end

class EventType < ActiveRecord::Base
  attr_accessible :name

  has_many :phrases
end

class PhrasesPiece < ActiveRecord::Base
  attr_accessible :order, :phrase_id, :template_piece_id

  belongs_to :phrase
  belongs_to :template_piece
end

And I'm trying to create a new phrase, editing its default form to:

<%= form_for(@phrase) do |f| %>
  <% if @phrase.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@phrase.errors.count, "error") %> prohibited this phrase from being saved:</h2>

      <ul>
      <% @phrase.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  Select the event type:
    <%= collection_select(:phrase, :event_type_id, EventType.all, :id, :name) %>
    Select the phrases to be used:
    <%= collection_select(:phrase, :template_pieces, TemplatePiece.all, :id, :name) %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

I first had an issue with Mass Assignment, but I fixed that adding the attr_accessible :template_pieces to the phrases model. I'm unsure if that is the correct way of fixing it, but at least it stopped complaining that it could not mass assign the protected attribute.

Now, I'm getting the following error when submitting a new phrase:

undefined method `each' for "1":String

Which I kinda think happens due to the fact that there are supposed to be many template_pieces for a given phrase, but I'm currently only able to submit them one at a time. So it just finds the one, tries to iterate through it and fails.

How would I go about fixing that? Is there a better way of entering models with the has_many :through to the database? Do I have to do it manually (as in dismissing the default controller @phrase = Phrase.new(params[:phrase])?

Thanks!

Charles
  • 50,943
  • 13
  • 104
  • 142
snowingheart
  • 120
  • 9

1 Answers1

0

You should use the fields_for helper to wrap the nested attributes:

<%= f.fields_for :template_pieces do |template_f| %>
  <%= template_f.collection_select, :event_type_id, EventType.all, :id, :name %>
  Select the phrases to be used:
  <%= template_f.collection_select, :template_pieces, TemplatePiece.all, :id, :name %>
<% end %>

Reference

fields_for documentation.

Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
  • That particular syntax yields an error. I tried removing the comma after `collection_select`, and now, after submit, responds with: `TemplatePiece(#70324553021400) expected, got Array(#10676920)` – snowingheart Mar 06 '13 at 23:25