factory_girl_extensions 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +57 -0
- data/Rakefile +58 -0
- data/VERSION.yml +4 -0
- data/lib/factory_girl_extensions.rb +67 -0
- data/spec/dog_spec.rb +35 -0
- data/spec/extensions_spec.rb +48 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +31 -0
- metadata +73 -0
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= factory_girl extensions
|
2
|
+
|
3
|
+
FactoryGirlExtensions is a simple set of extensions that I typically
|
4
|
+
like to use on projects, when using factory_girl
|
5
|
+
|
6
|
+
NOTE: I might try adding this as an official factory_girl 'syntax', in which case
|
7
|
+
these extensions will be available to anyone using factory_girl
|
8
|
+
|
9
|
+
== Install
|
10
|
+
|
11
|
+
$ sudo gem install remi-factory_girl_extensions -s http://gems.github.com
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
To use these extensions, <tt>require 'factory_girl_extensions'</tt> in your <tt>factories.rb</tt> (or wherever)
|
16
|
+
|
17
|
+
FactoryGirlExtensions adds some shortcut methods. Here are some examples:
|
18
|
+
|
19
|
+
User.generate! # this is equivalent to Factory(:user) or Factory.create(:user)
|
20
|
+
User.gen! # this is a shortcut alias for #generate
|
21
|
+
User.generate # this is equivalent to Factory.build(:user) and then #save
|
22
|
+
User.gen # this is equivalent to Factory.build(:user) and then #save
|
23
|
+
User.build # this is equivalent to Factory.build(:user)
|
24
|
+
User.gen! :name => 'Bob' # this is equivalent to Factory(:user, :name => 'Bob')
|
25
|
+
:email.next # this is equivalent to Factory.next(:email)
|
26
|
+
'email'.next # this will NOT work because String#next already exists
|
27
|
+
:admin_user.gen! # this is equivalent to Factory.gen(:admin_user)
|
28
|
+
'admin_user'.gen! # this is equivalent to Factory.gen(:admin_user)
|
29
|
+
User.attrs # this is equivalent to Factory.attributes_for(:user)
|
30
|
+
'user'.attrs # this is equivalent to Factory.attributes_for(:user)
|
31
|
+
:user.attrs # this is equivalent to Factory.attributes_for(:user)
|
32
|
+
|
33
|
+
# TODO
|
34
|
+
I think I would like to add User.gen_admin or maybe User.gen(:admin)
|
35
|
+
as a shortcut for generating an :admin_user factory
|
36
|
+
|
37
|
+
=== Why User.gen instead of Factory(:user)
|
38
|
+
|
39
|
+
Personally, I really dislike the <tt>Factory(:user)</tt> syntax. When you have a lot of
|
40
|
+
factories, it's hard to see the names of the actual model classes. I don't like this:
|
41
|
+
|
42
|
+
Factory(:user).should be_valid
|
43
|
+
Factory(:name, :string => 'something').should be_awesome
|
44
|
+
Factory(:comment, :user => Factory(:user)).should be_cool
|
45
|
+
Factory(:user).should do_some_stuff_with(:things)
|
46
|
+
|
47
|
+
To me, the thing that draws my attention in that code snippet is <tt>Factory</tt>.
|
48
|
+
I don't care about <tt>Factory</tt>, I care about the actual models! I prefer:
|
49
|
+
|
50
|
+
User.gen.should be_valid
|
51
|
+
Name.gen( :string => 'something' ).should be_awesome
|
52
|
+
Comment.gen( :user => User.gen ).should be_cool
|
53
|
+
User.gen.should do_some_stuff_with(:things)
|
54
|
+
|
55
|
+
If you syntax highlight the above code, it's likely that the model names will
|
56
|
+
be the things that really jump out at you. Even in plain text, it's easier to
|
57
|
+
understand that code than the above <tt>Factory(:code)</tt> in my opinion.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |s|
|
9
|
+
s.name = "factory_girl_extensions"
|
10
|
+
s.summary = "helpful extensions for factory_girl"
|
11
|
+
s.email = "remi@remitaylor.com"
|
12
|
+
s.homepage = "http://github.com/remi/factory_girl_extensions"
|
13
|
+
s.description = "helpful extensions for factory_girl"
|
14
|
+
s.authors = %w( remi )
|
15
|
+
s.files = FileList["[A-Z]*", "{bin,lib,spec,examples}/**/*"]
|
16
|
+
# s.executables = "foo"
|
17
|
+
s.add_dependency 'thoughtbot-factory_girl'
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
21
|
+
end
|
22
|
+
|
23
|
+
Spec::Rake::SpecTask.new do |t|
|
24
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
t.spec_opts = ['-c', '-f specdoc']
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Run all examples with RCov"
|
29
|
+
Spec::Rake::SpecTask.new('rcov') do |t|
|
30
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
31
|
+
t.rcov = true
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::RDocTask.new do |rdoc|
|
35
|
+
rdoc.rdoc_dir = 'rdoc'
|
36
|
+
rdoc.title = 'factory_girl_extensions'
|
37
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
38
|
+
rdoc.rdoc_files.include('README.rdoc')
|
39
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Confirm that gemspec is $SAFE'
|
43
|
+
task :safe do
|
44
|
+
require 'yaml'
|
45
|
+
require 'rubygems/specification'
|
46
|
+
data = File.read('factory_girl_extensions.gemspec')
|
47
|
+
spec = nil
|
48
|
+
if data !~ %r{!ruby/object:Gem::Specification}
|
49
|
+
Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
|
50
|
+
else
|
51
|
+
spec = YAML.load(data)
|
52
|
+
end
|
53
|
+
spec.validate
|
54
|
+
puts spec
|
55
|
+
puts "OK"
|
56
|
+
end
|
57
|
+
|
58
|
+
task :default => :spec
|
data/VERSION.yml
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'factory_girl'
|
4
|
+
|
5
|
+
# Adds helpful factory_girl methods to objects.
|
6
|
+
#
|
7
|
+
# This uses method_missing just incase the given Object
|
8
|
+
# already responds to one of these methods.
|
9
|
+
#
|
10
|
+
# == Usage
|
11
|
+
#
|
12
|
+
# User.generate! # this is equivalent to Factory(:user) or Factory.create(:user)
|
13
|
+
# User.gen! # this is a shortcut alias for #generate
|
14
|
+
# User.generate # this is equivalent to Factory.build(:user) and then #save
|
15
|
+
# User.gen # this is equivalent to Factory.build(:user) and then #save
|
16
|
+
# User.build # this is equivalent to Factory.build(:user)
|
17
|
+
# User.gen! :name => 'Bob' # this is equivalent to Factory(:user, :name => 'Bob')
|
18
|
+
# :email.next # this is equivalent to Factory.next(:email)
|
19
|
+
# 'email'.next # this will NOT work because String#next already exists
|
20
|
+
# :admin_user.gen! # this is equivalent to Factory.gen(:admin_user)
|
21
|
+
# 'admin_user'.gen! # this is equivalent to Factory.gen(:admin_user)
|
22
|
+
# User.attrs # this is equivalent to Factory.attributes_for(:user)
|
23
|
+
# 'user'.attrs # this is equivalent to Factory.attributes_for(:user)
|
24
|
+
# :user.attrs # this is equivalent to Factory.attributes_for(:user)
|
25
|
+
#
|
26
|
+
# == TODO
|
27
|
+
#
|
28
|
+
# * properly implement <tt>respond_to?</tt>
|
29
|
+
# * add syntax like User.gen_admin or User.gen(:admin) for generating an :admin_user
|
30
|
+
#
|
31
|
+
module FactoryGirlExtensions
|
32
|
+
def method_missing name, *args
|
33
|
+
|
34
|
+
messages = case name.to_s
|
35
|
+
when /^gen(erate)?\!$/
|
36
|
+
[:build, :save!]
|
37
|
+
when /^gen(erate)?$/
|
38
|
+
[:build, :save]
|
39
|
+
when 'build'
|
40
|
+
[:build]
|
41
|
+
when 'next'
|
42
|
+
[:next]
|
43
|
+
when /^attr(ibute)?s(_for)?$/
|
44
|
+
[:attributes_for]
|
45
|
+
end
|
46
|
+
|
47
|
+
if messages
|
48
|
+
# if this is an instance of String/Symbol use this instance as the factory name, else use the class name
|
49
|
+
factory_name = ( kind_of?(Symbol) || kind_of?(String) ) ? self.to_s.to_sym : self.name.underscore.to_sym
|
50
|
+
|
51
|
+
factory_method, instance_method = messages
|
52
|
+
instance = Factory.send factory_method, factory_name, *args
|
53
|
+
|
54
|
+
if instance_method
|
55
|
+
instance.send instance_method if instance.respond_to? instance_method
|
56
|
+
end
|
57
|
+
|
58
|
+
instance
|
59
|
+
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Object.send :include, FactoryGirlExtensions
|
data/spec/dog_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
#
|
4
|
+
# make sure our example class works as expected
|
5
|
+
#
|
6
|
+
describe Dog do
|
7
|
+
|
8
|
+
it 'should have a name' do
|
9
|
+
Dog.new.name.should be_nil
|
10
|
+
Dog.new( :name => 'Rover' ).name.should == 'Rover'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should have a breed' do
|
14
|
+
Dog.new.breed.should be_nil
|
15
|
+
Dog.new( :breed => 'American Pit Bull Terrier' ).breed.should == 'American Pit Bull Terrier'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should require a name' do
|
19
|
+
Dog.new.should_not be_valid
|
20
|
+
Dog.new( :name => 'rover' ).should be_valid
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return true/false if #save OK' do
|
24
|
+
Dog.new.save.should be_false
|
25
|
+
Dog.new.should_not be_valid
|
26
|
+
Dog.new( :name => 'rover' ).should be_valid
|
27
|
+
Dog.new( :name => 'rover' ).save.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should raise an exception if not #save! OK' do
|
31
|
+
lambda { Dog.new.save! }.should raise_error
|
32
|
+
Dog.new( :name => 'rover' ).save!.should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
Factory.sequence(:string){|n| "HelloWorld#{ n }" }
|
4
|
+
|
5
|
+
Factory.define :dog do |d|
|
6
|
+
d.name { :string.next }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe FactoryGirlExtensions do
|
10
|
+
|
11
|
+
it '#gen[erate] should build and save' do
|
12
|
+
Dog.gen.should be_valid
|
13
|
+
Dog.generate.should be_valid
|
14
|
+
|
15
|
+
Dog.gen( :name => nil ).should_not be_valid
|
16
|
+
Dog.generate( :name => nil ).should_not be_valid
|
17
|
+
end
|
18
|
+
|
19
|
+
it '#gen[erate]! should build and save!' do
|
20
|
+
Dog.gen!.should be_valid
|
21
|
+
Dog.generate!.should be_valid
|
22
|
+
|
23
|
+
lambda { Dog.gen!( :name => nil ) }.should raise_error
|
24
|
+
lambda { Dog.generate!( :name => nil ) }.should raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it '"dog".gen and :dog.gen should work' do
|
28
|
+
:dog.gen!.should be_valid
|
29
|
+
'dog'.gen!.should be_valid
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'Dog.attrs & "dog".attrs & :dog.attrs should return Factory.attributes_for(:dog)' do
|
33
|
+
[ Dog, 'dog', :dog ].each do |x|
|
34
|
+
%w( attrs attributes attrs_for attributes_for ).each do |msg|
|
35
|
+
x.send(msg).keys.should include(:name)
|
36
|
+
x.send(msg)[:name].should =~ /HelloWorld\d/
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it ':foo.next should generate the :foo sequence' do
|
42
|
+
lambda { :foo.next }.should raise_error(/No such sequence: foo/)
|
43
|
+
Factory.sequence(:foo){|n| "Foo ##{n}" }
|
44
|
+
:foo.next.should == 'Foo #1'
|
45
|
+
:foo.next.should == 'Foo #2'
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'factory_girl'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/factory_girl_extensions'
|
5
|
+
|
6
|
+
#
|
7
|
+
# a class that we can use to test factory_girl_extensions with
|
8
|
+
#
|
9
|
+
class Dog
|
10
|
+
attr_accessor :name, :breed
|
11
|
+
|
12
|
+
def initialize options = {}
|
13
|
+
options.each {|k,v| instance_variable_set "@#{k}", v }
|
14
|
+
end
|
15
|
+
|
16
|
+
def save
|
17
|
+
valid?
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid?
|
21
|
+
! @name.blank?
|
22
|
+
end
|
23
|
+
|
24
|
+
def save!
|
25
|
+
if valid?
|
26
|
+
true
|
27
|
+
else
|
28
|
+
raise 'Invalid Dog!'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factory_girl_extensions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- remi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-16 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: thoughtbot-factory_girl
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: helpful extensions for factory_girl
|
26
|
+
email: remi@remitaylor.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
files:
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- VERSION.yml
|
37
|
+
- lib/factory_girl_extensions.rb
|
38
|
+
- spec/dog_spec.rb
|
39
|
+
- spec/extensions_spec.rb
|
40
|
+
- spec/spec.opts
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://github.com/remi/factory_girl_extensions
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.3
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: helpful extensions for factory_girl
|
70
|
+
test_files:
|
71
|
+
- spec/dog_spec.rb
|
72
|
+
- spec/extensions_spec.rb
|
73
|
+
- spec/spec_helper.rb
|