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.