原文在我另外一个博客上,地址:http://caok1231.com/blog/2013/05/02/factory-girl/
这里直接拷贝过来的,就不在另外排版了。
很多时候我们都会使用 factory-girl 去构建测试数据,但如何去定义表之间的关系,特别是那种用户角色、权限之类的,接下来就稍微总结下如何用factory girl 去定义测试数据中的用户角色。
1.Many-to-Many
假定用户角色是通过many-to-many的关系定义的,比如结构是如下定义的:
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end
class UserRole < ActiveRecord::Base
belongs_to :user
belongs_to :role
end
class Role < ActiveRecord::Base
attr_accessible :name
has_many :user_roles
has_many :users, :through => :user_roles
end
1.1通过seeds.rb
先介绍下一种简单的处理,通过加载seeds.rb,预先生成“role”
seeds.rb
Role.delete_all
Role.create!([{ name: 'admin' }, { name: 'member' }])
在spec_helper.rb中将其加载
spec_helper.rb
RSpec.configure do |config|
.....
config.before(:all) do
DatabaseCleaner.start
# execute seed.rb
load File.expand_path('db/seeds.rb', Rails.root)
end
.....
end
介绍两种调用方式:
第一种:
factory :user do
name "xxx"
trait :admin do
after(:build) {|u| u.roles << Role.find_by_name('admin') }
end
end
//测试中创建admin角色的user
create :user, :admin
另外一种:
factory :user do
name "xxx"
trait :admin do
after(:build) {|u| u.roles << Role.find_by_name('admin') }
end
factory :admin, traits: [:admin]
end
//测试中创建admin角色的user
create :admin
Traits 允许你组合属性,然后将它们应用到任何 factory 中。
1.2直接构建 many-to-many
上面的方法有些讨巧,实际上这个就是要解决如何通过 factory-girl 去构建 many-to-many 的关系
factory :user do
name "xxx"
factory :admin_user do
roles {[ create(:admin_role) ]}
end
factory :member_user do
roles {[ create(:member_role) ]}
end
end
factory :role do
factory :admin_role do
name "admin"
end
factory :member_role do
name "member"
end
end
//测试中创建admin角色的user
create :admin_user
2.has-many
factory :article do
body 'article body'
factory :article_with_comment do
after(:create) do |article|
create(:comment, article: article)
end
end
end
factory :comment do
body 'Great article!'
end
// 调用
article = create(:article_with_comment)
更多的比如多态之类的关系可以参考Factory Girl callbacks
3.补充
定义角色还有种更常见的方式,就是通过 Role Based Authorization 这样去定义用户角色的,可以这么处理
FactoryGirl.define do
factory :user do
name "xxx"
.....
# create role user for all roles
#
# trait :admin do
# roles ["admin"]
# end
#
# factory :admin_user, :traits => [:admin]
User::ROLES.each do |r|
trait r do
roles r
end
factory "#{r}_user", :traits => [r]
end
end
end
调用时直接这样来:
create :admin_user
原文在我另外一个博客上,地址:http://caok1231.com/blog/2013/05/02/factory-girl/
这里直接拷贝过来的,就不在另外排版了。