Outro dia, tive um problema chatíssimo com o ActiveRecord: eu precisava criar um código de autenticidade, que conteria várias matrículas, que conteria várias disciplinas. O problema é o seguinte: Essas matrículas só seriam válidas se, por exemplo, o total de créditos das disciplinas não ultrapassassem um determinado número. Logo, resolvi fazer a validação no modelo de autenticidade, da seguinte forma:
class Autenticidade < ActiveRecord::Base
MAX_CREDITOS = 40
has_many :matriculas
has_many :disciplinas, :through => :matriculas
validate :credito_alto?
def credito_alto?
total = disciplinas.inject(0) { |r, v| r += v.creditos }
errors.add(:disciplinas, 'créditos acima do permitido') if total > MAX_CREDITOS
end
end
class Matricula < ActiveRecord::Base
belongs_to :disciplina
belongs_to :autenticidade
end
class Disciplina < ActiveRecord::Base
end
Ok, o problema agora é o seguinte: Se eu crio uma autenticidade, com o parâmetro :disciplina_ids => [1, 2], por exemplo, e a autenticidade não é válida, nenhuma nova matrícula é criada – como deveria ser. Agora, se eu atualizo uma autenticidade, com o autenticidade.update_attributes( :disciplina_ids => [1, 2]), e essa autenticidade não é válida, o ActiveRecord salva as matrículas. Nesse caso, eu tenho uma inconsistência na base de dados feia – e precisava encontrar uma alternativa que não envolvesse muitos hacks, coisa que ainda não encontrei. Mas isso me estimulou a pesquisar o DataMapper.
(more…)