Herança simples no ActiveRecord

Carlos Brando
Nome do Jogo
Published in
2 min readDec 24, 2015

Herança simples no Ruby on Rails é um problema comum, com uma solução trivial.

Vamos criar a seguinte situação: Imagine que eu tenha a necessidade de trabalhar com dois modelos Manager (gerente) e Employee (funcionário) no meu sistema. Seguindo o modelo de orientação a objetos, entendemos que ambos possuem características similares e por isso podemos criar uma nova classe Person.

class Person < ActiveRecord::Base 
end
class Manager < Person
end
class Employee < Person
end

O segundo passo é criar uma tabela no banco de dados onde os dados de ambos os perfis possam ser armazenar de uma forma que seja possível identificar se a pessoa é um gerente ou funcionário. Para isso basta ao criar a tabela adicionar uma coluna com o nome type (você pode mudar o nome dessa coluna sobrescrevendo Base.inheritance_column).

class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :type

# atributos comuns
t.string :name
t.string :email
# atributos do gerente
t.integer :dept
# atributos do funcionário
t.integer :reports_to
end
end
end

No exemplo acima os modelos Manager e Employee compartilham a mesma tabela para armazenar seus dados.

A classe Person sempre terá acesso a todos os registros dessa tabela, mas Manager e Employee funcionarão de forma completamente isolada, criando e pesquisando somente os registros correspondentes ao seu tipo.

Porém, existem dois efeitos colaterais aqui. O primeiro é que todos os atributos da tabela estarão presentes nos dois objetos. Na prática isso não é um problema grave, já que você pode simplesmente ignorar os atributos que não pertencem a classe correspondente. É um preço baixo a pagar por tamanha facilidade.

O segundo efeito colateral é que como a coluna type é um atributo da subclasse, toda nova instância automaticamente será marcada como suja e type será incluído na lista de atributos alterados no objeto.

Person.new.changed?  # => falseManager.new.changed? # => true
Manager.new.changes # => {“type”=>[“”,”Manager”]}

Originally published at nomedojogo.com on September 26, 2007.

--

--

Carlos Brando
Nome do Jogo

Programmer, CTO at @enjoei, Author of two books about Ruby on Rails, and Host of the @grokpodcast.