Ok, sempre vi por aí que o pessoal recomenda fortemente a utilização de factories de objetos ao invés de fixtures, porém as fixtures sempre serviram pra mim. Pelo menos até hoje.

O Problema comecou quando eu tive que sair da convenção do Rails. Tenho uma classe, digamos Customer, por exemplo, que possui dois Addresses:

class Customer < ActiveRecord::Base

has_one :business_address, :class_name => 'Address'
has_one :home_address, :class_name => 'Address'

end

Para os meus testes, criei os arquivos de fixtures

# addresses.yml

endereco_1:
street: Endereco 1

endereco_2:
street: Segundo Endereco

# customers.yml
rafael:
name: Rafael
business_address: endereco_1
home_address: endereco_2

Com as novas sexy fixtures, acreditei que isso seria possível. Porém, as fixtures, por natureza, refletem o que está no banco de dados, e nao nos objetos. Não importa que a minha classe Customer tenha atributos business_address e home_address mapeando para a classe Address, o sistema de fixtures não irá conseguir vincular o meu endereco_1 e endereco_2 com o customer rafael. Eu teria que criar uma fixture da seguinte forma:

# customers.yml
rafael:
name: Rafael
business_address_id: 1
home_address_id: 2

E com isso, perder toda a legibilidade. Imagina a bagunça que ficaria se todas as associações do meu modelo fossem com os ids. Quem conseguiria entender além do computador ?

Foi por isso que decidi utilizar o factory_girls. Com ele é possível fazer este tipo de associação sem ter que ficar fazendo macumba gambiarra workarounds. Após a instalação da gem, e configuração (que pode ser vista aqui), basta criar um factories.rb da seguinte forma:

Factory.define :endereco_1, :class => Address do |a|
a.street "Endereco 1"
end

Factory.define :endereco_2, :class => Address do |a|
a.street "Endereco 2"
end

Factory.define :rafael, :class => Customer do |c|
c.association :business_address, :factory => endereco_1
c.association :home_address, :factory => endereco_2
end

E no seu teste:

rafael = Factory(:rafael)

Simples, não ? E bem melhor…

No TweetBacks yet. (Be the first to Tweet this post)