Используя идентификатор объекта FactoryGirl в другом поле? - PullRequest
2 голосов
/ 13 марта 2012
factory :foo do
  bar # want this to use foo's id in calculating bar's value

  # current solution
  # ugly because it requires an extra save
  after_create { |foo| foo.bar = foo.id; foo.save! }

  # tried this too but foo.id is still nil at this point
  # after_build { |foo| foo.bar = foo.id } 
end

Есть ли лучший способ работы с идентификатором объекта при создании объекта?Это произошло в сценарии, изложенном выше.

Это также встречается в другом сценарии, где foo имеет ActiveRecord before_create_callback, который использует foo.id.С AR объект имеет идентификатор, когда вызывается обратный вызов, и метод делает то, что ожидалось.При использовании FG объект не имеет идентификатора при вызове обратного вызова, и поэтому метод не работает должным образом.Опять же, я прибегаю к after_create с дополнительным явным сохранением.

Будем весьма благодарны за любые предложения / советы по работе с идентификаторами объектов во время создания объекта FactoryGirl.

1 Ответ

1 голос
/ 27 марта 2012

Вот полный пример, который работает вне рельсов в irb.Однако вы должны установить правильные гемы.

Создайте таблицы в sqlite:

sqlite3 /tmp/development.db
> create table foos ( id int, name varchar(50), primary key(id));
> create table bars ( id int, name varchar(50), foo_id int, primary key(id));

Обратите внимание, что это синтаксис factory_girl 3.x.

require 'factory_girl'
require 'active_record'
require 'active_support'

ActiveRecord::Base.establish_connection(
  :adapter => 'sqlite3', :database => '/tmp/development.db'
)

class Foo < ActiveRecord::Base
  attr_accessible :id, :name
  has_one :bar
end

class Bar < ActiveRecord::Base
  attr_accessible :id, :name
  belongs_to :foo
end

FactoryGirl.define do
  factory :foo do
    sequence :id do |n|
      n
    end
    name "Foo Name" # use Faker
  end
end

FactoryGirl.define do
  factory :bar do
    sequence(:id) {|n| n }
    association :foo, :factory => :foo
    name "Bar Name" # use Faker
  end
end

bar = FactoryGirl.build(:bar)
puts bar.inspect
# => #<Bar id: 1, name: "Bar Name", foo_id: 1>

Вы заметите, что вы можете запустить это только один раз, потому что мы не откатываем наши таблицы после этого запуска.Это потому, что factory_girl выяснил, что необходима ассоциация, и записал записи в БД, хотя все, что мы сделали, это build вызов.Обычно build не записывает в БД.Вы можете выполнить откат вручную:

> delete from foos;
> delete from bars;

Извините за очень неряшливый пример, но, по крайней мере, вы можете играть с этим на стороне, не связываясь с вашим проектом.

...