Herança de tabela simples no ActiveRecord

26 de setembro de 2007  |  Ruby on Rails  | 

458624987_1c4a9ee690

Um problema comum e uma solução trivial. É assim que posso descrever o uso de heranças em modelos no Rails.

Imagine a seguinte situação: No meu diagrama de classes tenho uma classe Person com duas subclasses, Manager e Employee. De inicio a primeira coisa que faríamos seria criar três modelos no Rails:

[source:ruby]
class Person < ActiveRecord::Base
end

class Manager < ActiveRecord::Base
end

class Employee < ActiveRecord::Base
end
[/source]

Mas como modelar as tabelas neste caso? Podemos usar o recurso de heranças do ActiveRecord e fazer tudo em cima de apenas uma tabela.

[source:sql]
create table people (
id INT AUTO_INCREMENT NOT NULL,
type VARCHAR(20),

/* atributos comuns */
name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,

/* atributos do gerente */
dept INT,

/* atributos do funcionario */
reports_to INT,
PRIMARY KEY (id)
);
[/source]

Note que criamos uma coluna chamada type na tabela people, é aqui que está o segredo.

Agora alteramos os modelos para que as classes Manager e Employee sejam subclasses de Person:

[source:ruby]
class Person < ActiveRecord::Base
end

class Manager < Person
end

class Employee < Person
end
[/source]

Pronto. Agora todos os modelos acessam a mesma tabela. Se você utilizar a classe Person, o ActiveRecord vai sempre retornar todas as linhas desta tabela, mas se usar Manager ou Employee ele somente tratará os registros com o tipo especificado.

Mas temos um problema aí, você vai verificar que todas as classes possuem os mesmos atributos. Mas na prática isto nem é um problema assim tão sério. Você pode simplesmente ignorar os atributos que não pertencem àquela classe. É um preço baixo a pagar por tamanha facilidade. Sem contar que isto vai lhe poupar a criação de pelo menos três tabelas, e melhorar o desempenho de sua aplicação, já que menos tabelas são menos associações.


3 Comentários


  1. Muito bom essa facilidade do Rails, mas acho que deveria dar suporte a CTI também.

  2. Normalizar? Nem pensar! :)

    No livro do Akita ele comenta sobre os OLTP (OnLine Transaction Processing) que requerem consistência nos dados e OLAP (OnLine Analytical Processing) que precisam de velocidade na consulta. Como na maioria das vezes desenvolvemos sistemas OLTP, o melhor caminho provavelmente é a normalização e , neste caso do artigo, criar as três tabelas.

  3. Já utilizei isso e de fato é muito legal.
    Tem algumas informações legais na propria página wiki do rails, que tem umas referências para o Matin Fowler:

    http://wiki.rubyonrails.org/rails/pages/SingleTableInheritance

    []‘s

    João

Deixe um comentário