ErikAtLarge
ErikAtLarge

Reputation: 83

Rails Drop Down Menu based on new Model

I've been trying to work through this for a few days and can't get anything to work. I have been building my first app based on Michael Hartl's amazing tutorial: http://ruby.railstutorial.org/. Additionally, I have tried this tutorial, but the differences in my code and his prove to be too great for me to follow along.

Where my app differs from Michael Hurtl's is that I am trying to create a site where you can post your left over cans of paint (instead of microposts, AKA twitter). When I created the app, I had a column in the Paints model called "color_family". Now I am looking to change it from a text field to a drop down with predetermined values, e.g. "Reds", Oranges", "Yellows", Greens" etc.

I started out by generating a new scaffold:

rails generate scaffold Color_Family family:string

then I generated a migration:

rails generate migration AddColor_FamilyToPaints family_id:int

and migrated it all.

Then I created the associations

class ColorFamily < ActiveRecord::Base
    has_many :paints
end

and

class Paint < ActiveRecord::Base
    attr_accessible :family_id, :name, :hex, :location, :quantity, :additional_info
    belongs_to :user
    belongs_to :color_family
    ...
end

This is where I get lost, and any tutorial I try to follow breaks everything. Where do I define my predetermined list of color_families?

Is it even worth it for me to go through the creation of a new model? I previously tried this in the form field:

<%= form_for(@paint) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
    <%= f.label :color_family %>
    <%= select_tag(:color_family, options_for_select([['Red', 1],
                                                        ['Orange', 2], 
                                                        ['Yellow', 3], 
                                                        ['Green', 4], 
                                                        ['Blue', 5], 
                                                        ['Purple', 6], 
                                                        ['Black', 7], 
                                                        ['Grey', 8], 
                                                        ['White', 9], 
                                                        ['Cream', 10],
                                                        ['Brown', 12]])) %> 

and while it created a dropdown for me, it never captured the info when I added a new paint.

Any help is greatly appreciated. Also, a link to a tutorial would probably do me the biggest help as I've very new to RoR and backend stuff in general.

Upvotes: 1

Views: 2424

Answers (1)

CrazyVipa
CrazyVipa

Reputation: 927

I'm not sure if you are doing the reading version of the book, or the video. Personally, I recommend both! Absolutely amazing tutorial! One of the first things he does mention though, "Scaffold is not really for the real world" and you should consider this. When I'm doing projects, new old or just refactoring, I usually add everything by hand with the script/generate. The only "scaffold" I've ever used was the scaffold_controller because I was too lazy to do the controller by hand.

The short answer, you should have another model "Color" and the form should:

f.collection_select(:color_id, Color.find(:all), :id, :name, {:include_blank => 'Please Select A Color'})

And the ColorFamily should probably be a has_many_and_belongs_to_many Colors

If you could give me a run down of details associations supposed to be taking place, I can write up a small data modal for you.


Edit #1

You are needing a has_one :through relationship. The general concept will be...

Pivot tabel:

rails g migration ColorFamilyPaints paint_id:integer color_family_id:integer

Paint Class:

class Paint < ActiveRecord::Base
    attr_accessible :family_id, :name, :hex, :location, :quantity, :additional_info,
                    :color_families_attributes # Need to add this in order for you to be able to post with drop down
    belongs_to :user
    ...
    # Creates the Relationship
    has_one :color_families, :through => :color_family_paints

    # Allows color families to be nested in the form.
    accepts_nested_attributes_for :color_families, :allow_destroy => true
end

You'll notice a few changes. Addition to the attr_accessible, and the accepts_nested_attributes_for (you may need this, not sure with a has_one though). When you build the form, look at the ID/Name of the select box. If it ends in _attributes, use the accepts line. If not, you don't need it. Alter the :color_families_attributes to match the name of the select box.

Form HTML:

<%= form_for(@paint) do |f| %>
    <%= render 'shared/error_messages', object: f.object %>
    <div class="field">
        <%= f.label :color_family %>
        <%= f.collection_select(:color_family, ColorFamily.find(:all), :id, :name, {:include_blank => 'Please Select Color Family'}) %>
    </div>
<% end %>

More information on associations @ RoR website.

Upvotes: 2

Related Questions