Associação has_many em Rails com múltiplos checkboxes

Nesse meu começo de estudos de Ruby on Rails, cai na questão de como modelar e implementar uma associação assim: "uma camiseta pode ter várias cores".
Primeiro pensei num Enum clássico do Java (e outras linguagens) mas não serviria, pois as cores teriam que ser cadastradas pelo usuário. Logo teria que ser uma associação many-to-many entre dois modelos. Depois de muito ler, preferi usar a :has_many com :through e um terceiro model fazendo a conexão do que a has_and_belongs_to (HABTM), Deixo para esse railscasts uma explicação mais detalhada das duas implementações, de qual o conceito por trás do :mas_many, e quando usar uma ou outra.

O exemplo abaixo foi testado no Ubuntu 11.04, RoR 3.0.9 e Ruby 1.8.7

Crie o projeto
rails new Camisetas

Scaffold para model Shirt
rails generate scaffold Shirt name:string description:text

Scaffold para model Color
rails generate scaffold Color name:string hexa:string

Gere o model Colorization (já vai criar a migration com os campos necessários), que fará a associação de Shirt com uma Color
rails generate model Colorization shirt_id:integer color_id:integer

Altere o model Colorization (app/model/colorization.rb)
class Colorization < ActiveRecord::Base
  belongs_to :shirt
  belongs_to :color
end

E altere o model Color (app/model/color.rb) dizendo que ele tem várias colorizações (colorizations) e que possue muitas shirts através das colorizations
class Color < ActiveRecord::Base
  has_many :colorizations
  has_many :shirts, :through => :colorizations
end

e o model Shirt (app/model/shirt.rb), nesse caso também dizendo que possui vários colorizações e que através delas, possui muitas cores
class Shirt < ActiveRecord::Base
  has_many :colorizations
  has_many :colors, :through => :colorizations
end

Criar o banco e rodar as migrações
rake db:create
rake db:migrate

Rode o servidor
rails server

Crie algumas shirts e colors
http://localhost:3000/shirts/
http://localhost:3000/colors/

Agora, precisamos relacionar na edição de uma shirt as colors possíveis a serem escolhidas, através de checkboxes.
Em app/views/shirt/_form.html.erb, dentro do form de edição


  <% Color.all.each do |color| -%>
    <%= check_box_tag :color_ids, color.id, @shirt.colors.include?(color), :name => 'shirt[color_ids][]' -%>
    <%= label_tag :color_ids, color.name -%>
  <% end -%>

Para exibir as cores, em app/views/shirt/show.html.erb


  Colors:
  <% @shirt.colors.each do |color| %>
    <%= color.name %>
  <% end %>

Pronto! Edição e visualização ok!

 

Obs.: vale a pena ver o link acima do railscast sobre as associações e esse post sobre o uso de múltiplos checkboxes com :has_many.