In UI for belongs_to relationships, I discussed a way to make a belongs_to UI. Unfortunately, it was very complex, and I found a better way since then.

I have to thank Michael C. Toren for the spark that inspired this entry.

The way I now do my belongs_to UIs today is much simpler. Let us assume the following models for discussion:

app/models/product.rb
1 class Product
2   belongs_to :color
3 
4   validates_presence_of :color
5 end

app/models/color.rb
1 class Color
2   def self.all
3     self.find(:all, :order => 'name')
4   end
5 end

When creating a product, we would like to select the color of said product. The UI should be a simple SELECT box.

Rails makes it easy to have SELECT boxes coming from some table:

app/views/products/_form.rhtml
1 <p><label>Description:
2   <%= text_field 'product', 'description' %></p>
3 <p><label>Color:
4   <%= collection_select 'product', 'color_id',
5       Color.all, :id, :name %></p>

See how I call #collection_select with color_id instead of color ? That’s the trick to use.

One nice side-effect of this is that validation will still run. The validates_presence_of declaration will be respected if no color_id is assigned.

The only problem left to resolve is the field highlighting that Rails field helpers automagically add when a field validation rule is not respected.

There are two ways to resolve that:

  1. Change the validation to require both color and color_id (adding two messages to the message area), or;
  2. Add the error DIV manually when an error is found on the counterpart field, such as this:



    app/views/products/_form.rhtml

    1 <p><label>Description:
    2 <%= text_field ‘product’, ‘description’ ></p>
    3 <p><label>Color:
    4 <div class="<= ‘fieldWithErrors’ if error_message_on ‘product’, ‘color’ >">
    5 <= collection_select ‘product’, ‘color_id’,
    6 Color.all, :id, :name %>
    </div></p>

UPDATE (2006-01-04): John Indra noted that there didn’t exist an error_messages_on, only error_message_on. Code above corrected.

Search

Your Host

A picture of me

I am François Beausoleil, a Ruby on Rails and Scala developer. During the day, I work on Seevibes, a platform to measure social interactions related to TV shows. At night, I am interested many things. Read my biography.

Top Tags

Books I read and recommend

Links

Projects I work on

Projects I worked on