Finalmente o primeiro post sobre Rails. Essa dica é muito legal e prática para quem quer fazer auto-relaciomento com Rails. Estou postando porque não foi tão fácil encontrar a solução. Para facilitar, vamos exemplificar:
Vamos supor que em nosso sistema (um blog, por exemplo) temos categorias. E categorias podem possuir categorias filhas. Temos aí um auto-relacionamento para fazer, certo ?
No Rails, isso é muito fácil. No esquema das migrations, deveríamos ter algo parecido com isso:
class CreateCategories < ActiveRecord::Migration def self.up create_table :categories do |t| t.string :name t.string :description t.integer :father_id end end def self.down drop_table :categories end end
A coluna father_id indica a o ID de uma categoria pai. Seria como uma Foreign Key. Agora precisamos definir o relacionamento no Model para que o Rails possa compreender a tabela que criamos.
class Category < ActiveRecord::Base has_many :children, :class_name => "Category", :foreign_key => "father_id" belongs_to :father, :class_name => "Category" end
Essas duas linhas de código significam o seguinte:
- A primeira linha, indica que Category tem filhos, utilizando o Model Category e chave estrangeira father_id;
- A segunda linha diz que o mesmo Model Category pertence a um Category, estabelecendo aí o auto-relacionamento.
A partir daí, você já pode brincar e descobrir os filhos de um Category pai usando @category.children. Para descobrir o pai de um Category, use @category.father.
Para quem quiser aprender mais sobre relacionamentos no Rails, acesse o Guia Rails, ainda na versão em Inglês. Em breve haverá uma versão em português. Assim que sair eu anunciarei por aqui.

Valeu pela iniciativa Felipe.
Ótimo artigo.
@mateus,
obrigado pela visita.
Olá.
E como faço para acessar os registros do pai no console?
Category.children por exemplo não funciona.
Abraços
Eu fiz exatamente isso, fiz a migração, mas na hora de selecionar os filhos em um multiple select, ele reconhece os filhos como strings e não como filhos… Daí dá um ActiveRecord::AssociationTypeMismatch :(
Muito bom cara, seus posts me ajudam muito =)
Luiz,
obrigado por visitar meu site. Espero ajudar cada vez.
Abs!
E como ficaria isso a nivel de controller e view?
supondo que eu queira criar um tela com um combox
pra trazer as categorias onde father_id é Null
(que são as de hierarquia mais alta)
e um campo pra cadastrar uma nova categoria, se eu selecionar
um pai, quer dizer que ela é filha do mesmo, se não quer
dizer que ela é uma nova categoria pai. como ficaria?
Luiz,
você vai fazer uma busca onde father_id é nil. Não tem mistério.
E sobre cadastrar, é um processo parecido. Infelizmente eu não tenho tempo agora para criar um código de exemplo, mas é um formulário simples, com um combo representando father_id. Se vc não escolher ninguém, ele será considerado pai. Se escolher, a nova entrada será filha de um pai.
Abs.
Eu implementei isso, é é muito simples, MUITO mesmo, só gerar o combo trazendo as categorias e mais nada, continue com os posts, abraços!