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
在对象创建过程中有没有更好的方法来处理对象的id?这已经出现在上面概述的情景中。
另一种情况是,foo有一个使用foo.id的ActiveRecord before_create_callback。对于AR,当调用回调并且方法按预期方式执行时,对象具有id。使用FG,在调用回调时对象没有id,因此该方法的行为不符合预期。再次,我使用额外明确的保存来使用after_create。
在FactoryGirl对象创建过程中使用对象id的任何建议/提示都将非常感激。
答案 0 :(得分:1)
这是一个完整的示例,它在irb中的rails之外工作。但是你必须安装正确的宝石。
在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
不会写入DB。您可以手动回滚:
> delete from foos;
> delete from bars;
很抱歉这个非常不受欢迎的例子,但至少你可以在旁边玩这个而不会弄乱你的项目。