views:

108

answers:

2

Complete rails newbie trying to get started.

I have two classes, Ingredient, and Unit. There are three units, lbs, gallons, and dozens, and each ingredient has exactly one unit. I think I got the associations/routes set up correctly. When creating a new ingredient, I need to require the user to set the units from these three. I used another question to get this far: http://stackoverflow.com/questions/1663499/drop-down-box-populated-with-data-from-another-table-in-a-form-ruby-on-rails

Model for Ingredients:

class Ingredient < ActiveRecord::Base
  belongs_to :unit
end

Model for Units:

class Unit < ActiveRecord::Base
end

Routes:

  map.resources :ingredients, :has_many => :unit_conversions
  map.resources :units, :has_many => :ingredients

Ingredients New controller

def new
    @ingredient = Ingredient.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @ingredient }
    end
  end

Ingredients New View:

<h1>New ingredient</h1>

<% form_for(@ingredient) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :needsDefrosting %><br />
    <%= f.check_box :needsDefrosting %>
  </p>
  <p>
   <%= f.label :baseName %>
   <%= f.collection_select :unit_id, @ingredient, :id, :baseName, :prompt => "Select a Base Measurement"%>
   <br />
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>

<%= link_to 'Back', ingredients_path %>

The error is

 NoMethodError in Ingredients#new

Showing app/views/ingredients/new.html.erb where line #16 raised:

undefined method `map' for #<Ingredient:0x3dae1c0>

Extracted source (around line #16):

13:   </p>
14:   <p>
15:    <%= f.label :baseName %>
16:    <%= f.collection_select :unit_id, @ingredient, :id, :baseName, :prompt => "Select a Base Measurement"%>
17:    <br />
18:   </p>
19:   <p>

RAILS_ROOT: C:/Users/joan/dh

I'm only about three days deep in RoR, so I suspect it's simple!

A: 

The associations in your model classes are incorrect according to your description of how ingredients and units are related. It should be:

class Ingredient < ActiveRecord::Base
  has_one :unit
end

class Unit < ActiveRecord::Base
  belongs_to :ingredient
end
John Topley
but, my impression from documentation/reading, was that if you use has_one, then each time I add a new ingredient, I ALSO add a new unit. I don't want this. There are only three units, I just need each ingredient to be associated with exactly one?
Joan
The `has_one` association does that.
John Topley
+2  A: 

collection_select needs an array of options, you are passing an ingredient. Changing @ingredient to Unit.all should fix it.

%= f.collection_select :unit_id, Unit.all, :id, :baseName, :prompt => "Select a Base Measurement"%>

As a side note if you are only ever going to have 3 types of units it might make more sense to create a constant instead of having a table for units. This would reduce the number of joins and make the overall model a little simpler.

John Duff