factory_girl_extensions 0.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/README.markdown +115 -0
- data/Rakefile +10 -0
- data/factory_girl_extensions.gemspec +27 -0
- data/lib/factory_girl_extensions/core.rb +151 -0
- data/lib/factory_girl_extensions/version.rb +8 -0
- data/lib/factory_girl_extensions.rb +2 -4
- data/spec/factory_girl_extensions_spec.rb +232 -0
- metadata +62 -55
- data/lib/factory_girl_extensions/module.rb +0 -91
data/.gemtest
ADDED
File without changes
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# FactoryGirl extensions
|
2
|
+
|
3
|
+
factory_girl_extensions is a simple set of syntax extensions that I typically like to use on projects when using factory_girl.
|
4
|
+
|
5
|
+
## Install
|
6
|
+
|
7
|
+
gem install factory_girl_extensions
|
8
|
+
|
9
|
+
## FactoryGirl extensions 2.0
|
10
|
+
|
11
|
+
As of version 2.0, factory_girl_extensions now targets the new FactoryGirl 2.0 API.
|
12
|
+
|
13
|
+
- Only FactoryGirl 2.0+ is supported now. If you are using an older version of FactoryGirl, please use factory_girl_extensions < 2.0
|
14
|
+
- You can no longer use `:email.next` to generate the next :email sequence. factory_girl_extensions no longer includes custom sequence code (because this feature wasn't heavily used and the new FactoryGirl inline sequences are pretty awesome)
|
15
|
+
- The code has been updated to be Ruby 1.8/1.9 compatible and now follows the same patterns as other official FactoryGirl alternative syntaxes
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'factory_girl_extensions'
|
21
|
+
|
22
|
+
FactoryGirl.define do
|
23
|
+
factory :user do
|
24
|
+
name 'Bob Smith'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates a saved instance without raising (same as saving the result of FactoryGirl.build)
|
29
|
+
User.generate(:name => 'Johnny')
|
30
|
+
|
31
|
+
# Creates a saved instance and raises when invalid (same as FactoryGirl.create)
|
32
|
+
User.generate!
|
33
|
+
|
34
|
+
# Creates an unsaved instance (same as FactoryGirl.build)
|
35
|
+
User.build
|
36
|
+
|
37
|
+
# Creates an instance and yields it to the passed block
|
38
|
+
User.generate do |user|
|
39
|
+
# ...do something with user...
|
40
|
+
end
|
41
|
+
|
42
|
+
# Creates and returns a Hash of attributes from this factory (same as FactoryGirl.attributes_for).
|
43
|
+
User.attributes
|
44
|
+
|
45
|
+
# A few short aliases are included for convenience.
|
46
|
+
User.gen
|
47
|
+
User.gen!
|
48
|
+
User.attrs
|
49
|
+
|
50
|
+
# Factories with custom prefix/suffixes are also supported.
|
51
|
+
FactoryGirl.define do
|
52
|
+
factory :admin_user, :parent => :user do
|
53
|
+
is_admin true
|
54
|
+
end
|
55
|
+
|
56
|
+
factory :user_with_profile, :parent => :user do
|
57
|
+
profile_complete true
|
58
|
+
end
|
59
|
+
|
60
|
+
factory :admin_user_with_profile, :parent => :admin_user do
|
61
|
+
profile_complete true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generates the :admin_user factory
|
66
|
+
User.generate(:admin)
|
67
|
+
User.generate(:admin, :name => 'Cool Admin')
|
68
|
+
|
69
|
+
# Generates the :user_with_profile factory
|
70
|
+
User.generate(:with_profile)
|
71
|
+
|
72
|
+
# Generates the :admin_user_with_profile factory
|
73
|
+
User.generate(:admin, :with_profile)
|
74
|
+
User.generate(:admin, :with_profile, :name => 'Custom name')
|
75
|
+
|
76
|
+
# User.build and User.attributes also support these custom prefix/suffixes.
|
77
|
+
```
|
78
|
+
|
79
|
+
## Why User.gen instead of FactoryGirl(:user)?
|
80
|
+
|
81
|
+
Personally, I really dislike the `FactoryGirl(:user)` syntax. When you have a lot of
|
82
|
+
factories, it's hard to see the names of the actual model classes. I don't like this:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
FactoryGirl(:user).should be_valid
|
86
|
+
FactoryGirl(:name, :string => 'something').should be_awesome
|
87
|
+
FactoryGirl(:comment, :user => Factory(:user)).should be_cool
|
88
|
+
FactoryGirl(:user).should do_some_stuff_with(:things)
|
89
|
+
```
|
90
|
+
|
91
|
+
To me, the thing that draws my attention in that code snippet is `FactoryGirl`.
|
92
|
+
I don't care about `Factory`, I care about the actual models! I prefer:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
User.gen.should be_valid
|
96
|
+
Name.gen(:string => 'something').should be_awesome
|
97
|
+
Comment.gen(:user => User.gen).should be_cool
|
98
|
+
User.gen.should do_some_stuff_with(:things)
|
99
|
+
```
|
100
|
+
|
101
|
+
When you syntax highlight the above code, the constants (model names) are usually
|
102
|
+
the things that really jump out at you. Even in plain text, it's easier to
|
103
|
+
understand that code than the above `FactoryGirl(:code)` in my opinion.
|
104
|
+
|
105
|
+
## Dude, why isn't this stuff included in the official FactoryGirl gem as an alternative syntax?
|
106
|
+
|
107
|
+
Originally, when I made this, not many people were using this syntax.
|
108
|
+
|
109
|
+
Now that I know many people using this syntax, I may send a pull request to FactoryGirl to see if they would consider accepting this.
|
110
|
+
|
111
|
+
As of factory_girl_extensions 2.0, the code is actually written in the same style as official syntaxes, so it should be very easy to include this into the official FactoryGirl gem.
|
112
|
+
|
113
|
+
## License
|
114
|
+
|
115
|
+
factory_girl_extensions is released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/factory_girl_extensions/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "factory_girl_extensions"
|
6
|
+
gem.author = "remi"
|
7
|
+
gem.email = "remi@remitaylor.com"
|
8
|
+
gem.homepage = "http://github.com/remi/factory_girl_extensions"
|
9
|
+
gem.summary = "Alternative FactoryGirl API"
|
10
|
+
|
11
|
+
gem.description = <<-desc.gsub(/^\s+/, '')
|
12
|
+
Alternative FactoryGirl API allowing you to build/generate factories
|
13
|
+
using your class constants, eg. User.gen instead of Factory(:user).
|
14
|
+
desc
|
15
|
+
|
16
|
+
files = `git ls-files`.split("\n")
|
17
|
+
gem.files = files
|
18
|
+
gem.executables = files.grep(%r{^bin/.*}).map {|f| File.basename(f) }
|
19
|
+
gem.test_files = files.grep(%r{^spec/.*})
|
20
|
+
gem.require_paths = ["lib"]
|
21
|
+
gem.version = FactoryGirlExtensions::VERSION
|
22
|
+
|
23
|
+
gem.add_dependency "factory_girl", ">= 2.0"
|
24
|
+
|
25
|
+
gem.add_development_dependency "rake"
|
26
|
+
gem.add_development_dependency "rspec"
|
27
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require "factory_girl_extensions/version"
|
2
|
+
|
3
|
+
module FactoryGirl
|
4
|
+
module Syntax
|
5
|
+
|
6
|
+
# Extends any object to provide generation methods for factories.
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# require 'factory_girl_extensions'
|
11
|
+
#
|
12
|
+
# FactoryGirl.define do
|
13
|
+
# factory :user do
|
14
|
+
# name 'Bob Smith'
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # Creates a saved instance without raising (same as saving the result of FactoryGirl.build)
|
19
|
+
# User.generate(:name => 'Johnny')
|
20
|
+
#
|
21
|
+
# # Creates a saved instance and raises when invalid (same as FactoryGirl.create)
|
22
|
+
# User.generate!
|
23
|
+
#
|
24
|
+
# # Creates an unsaved instance (same as FactoryGirl.build)
|
25
|
+
# User.build
|
26
|
+
#
|
27
|
+
# # Creates an instance and yields it to the passed block
|
28
|
+
# User.generate do |user|
|
29
|
+
# # ...do something with user...
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # Creates and returns a Hash of attributes from this factory (same as FactoryGirl.attributes_for).
|
33
|
+
# User.attributes
|
34
|
+
#
|
35
|
+
# # A few short aliases are included for convenience.
|
36
|
+
# User.gen
|
37
|
+
# User.gen!
|
38
|
+
# User.attrs
|
39
|
+
#
|
40
|
+
# # Factories with custom prefix/suffixes are also supported.
|
41
|
+
# FactoryGirl.define do
|
42
|
+
# factory :admin_user, :parent => :user do
|
43
|
+
# is_admin true
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# factory :user_with_profile, :parent => :user do
|
47
|
+
# profile_complete true
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# factory :admin_user_with_profile, :parent => :admin_user do
|
51
|
+
# profile_complete true
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# # Generates the :admin_user factory
|
56
|
+
# User.generate(:admin)
|
57
|
+
# User.generate(:admin, :name => 'Cool Admin')
|
58
|
+
#
|
59
|
+
# # Generates the :user_with_profile factory
|
60
|
+
# User.generate(:with_profile)
|
61
|
+
#
|
62
|
+
# # Generates the :admin_user_with_profile factory
|
63
|
+
# User.generate(:admin, :with_profile)
|
64
|
+
# User.generate(:admin, :with_profile, :name => 'Custom name')
|
65
|
+
#
|
66
|
+
# # User.build and User.attributes also support these custom prefix/suffixes.
|
67
|
+
#
|
68
|
+
# This syntax was derived from remi Taylor's factory_girl_extensions.
|
69
|
+
module ObjectMethods
|
70
|
+
|
71
|
+
# Creates an unsaved instance (same as FactoryGirl.build)
|
72
|
+
def build(*args, &block)
|
73
|
+
factory, overrides = ObjectMethods.factory_and_overrides(name.underscore, args)
|
74
|
+
instance = factory.run(Strategy::Build, overrides, &block)
|
75
|
+
instance
|
76
|
+
end
|
77
|
+
|
78
|
+
# Creates a saved instance without raising (same as saving the result of FactoryGirl.build)
|
79
|
+
def generate(*args, &block)
|
80
|
+
instance = build(*args)
|
81
|
+
instance.save
|
82
|
+
yield instance if block_given?
|
83
|
+
instance
|
84
|
+
end
|
85
|
+
|
86
|
+
# Creates a saved instance and raises when invalid (same as FactoryGirl.create)
|
87
|
+
def generate!(*args, &block)
|
88
|
+
factory, overrides = ObjectMethods.factory_and_overrides(name.underscore, args)
|
89
|
+
instance = factory.run(Strategy::Create, overrides, &block)
|
90
|
+
instance
|
91
|
+
end
|
92
|
+
|
93
|
+
# Creates and returns a Hash of attributes from this factory (same as FactoryGirl.attributes_for)
|
94
|
+
def attributes(*args, &block)
|
95
|
+
factory, overrides = ObjectMethods.factory_and_overrides(name.underscore, args)
|
96
|
+
attrs = factory.run(Strategy::AttributesFor, overrides, &block)
|
97
|
+
attrs
|
98
|
+
end
|
99
|
+
|
100
|
+
alias attrs attributes
|
101
|
+
alias gen generate
|
102
|
+
alias gen! generate!
|
103
|
+
|
104
|
+
# @private
|
105
|
+
#
|
106
|
+
# Helper to get the Factory object and overrides hash from the arguments passed to any ObjectMethods.
|
107
|
+
def self.factory_and_overrides(base_name, args)
|
108
|
+
overrides = args.last.is_a?(Hash) ? args.pop : {}
|
109
|
+
factory = find_factory(base_name, args)
|
110
|
+
raise ArgumentError.new("Could not find factory for #{base_name.inspect} with #{args.inspect}") unless factory
|
111
|
+
[factory, overrides]
|
112
|
+
end
|
113
|
+
|
114
|
+
# @private
|
115
|
+
#
|
116
|
+
# Given the base_name for a class's factory and 0-2 parts (prefix/suffixes),
|
117
|
+
# this finds the first matching factory that FactoryGirl has in its registry.
|
118
|
+
def self.find_factory(base_name, parts)
|
119
|
+
case parts.length
|
120
|
+
when 0
|
121
|
+
detect_factory base_name
|
122
|
+
when 1
|
123
|
+
detect_factory "#{parts.first}_#{base_name}", "#{base_name}_#{parts.first}"
|
124
|
+
when 2
|
125
|
+
detect_factory "#{parts.first}_#{base_name}_#{parts.last}", "#{parts.last}_#{base_name}_#{parts.first}"
|
126
|
+
else
|
127
|
+
raise ArgumentError.new("Don't know how to find factory for #{base_name.inspect} with #{parts.inspect}")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# @private
|
132
|
+
#
|
133
|
+
# Given any number of arguments representing the possible names for a factory that you
|
134
|
+
# want to find, this iterates over the given names and returns the first FactoryGirl
|
135
|
+
# factory object that FactoryGirl returns (skipping unregistered factory names).
|
136
|
+
def self.detect_factory(*possible_factory_names)
|
137
|
+
factory = nil
|
138
|
+
possible_factory_names.each do |factory_name|
|
139
|
+
begin
|
140
|
+
factory = FactoryGirl.factory_by_name(factory_name)
|
141
|
+
break
|
142
|
+
rescue ArgumentError => e
|
143
|
+
raise e unless e.message =~ /Factory not registered/
|
144
|
+
next
|
145
|
+
end
|
146
|
+
end
|
147
|
+
factory
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# If you require "factory_girl_extensions", it automatically extends Object with these extensions.
|
2
|
+
#
|
3
|
+
# If you require "factory_girl_extensions/core", it doesn't automatically include extensions anywhere
|
4
|
+
# so you can choose which classes/objects you want to extend to get the gen/build/etc methods.
|
5
|
+
require "factory_girl_extensions/core"
|
6
|
+
|
7
|
+
# Required after factory_girl_extensions to ensure that factory_girl_extensions doesn't
|
8
|
+
# blow up if factory_girl hasn't been required yet.
|
9
|
+
require "factory_girl"
|
10
|
+
|
11
|
+
require "rspec"
|
12
|
+
|
13
|
+
# Example class
|
14
|
+
class Dog
|
15
|
+
extend FactoryGirl::Syntax::ObjectMethods
|
16
|
+
|
17
|
+
attr_accessor :name, :saved
|
18
|
+
|
19
|
+
def save
|
20
|
+
self.saved = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def saved?
|
24
|
+
saved == true
|
25
|
+
end
|
26
|
+
|
27
|
+
def save!
|
28
|
+
raise "Called save!" unless name == "Valid Name"
|
29
|
+
self.saved = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Example factories
|
34
|
+
FactoryGirl.define do
|
35
|
+
factory :dog do
|
36
|
+
name "Rover"
|
37
|
+
end
|
38
|
+
|
39
|
+
factory :awesome_dog, :class => Dog do
|
40
|
+
name "Awesome Dog"
|
41
|
+
end
|
42
|
+
|
43
|
+
factory :dog_with_toys, :class => Dog do
|
44
|
+
name "Dog with toys"
|
45
|
+
end
|
46
|
+
|
47
|
+
factory :awesome_dog_with_toys, :class => Dog do
|
48
|
+
name "Awesome Dog with toys"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe Dog do
|
53
|
+
it "should act as expected" do
|
54
|
+
dog = Dog.new
|
55
|
+
dog.name.should be_nil
|
56
|
+
|
57
|
+
dog.name = "Rover"
|
58
|
+
dog.name.should == "Rover"
|
59
|
+
|
60
|
+
dog.saved?.should == false
|
61
|
+
dog.save
|
62
|
+
dog.saved?.should == true
|
63
|
+
|
64
|
+
dog.saved = false
|
65
|
+
expect { dog.save! }.to raise_error(RuntimeError, /Called save!/)
|
66
|
+
dog.saved?.should == false
|
67
|
+
|
68
|
+
dog.name = "Valid Name" # this let's you call save!
|
69
|
+
dog.save!
|
70
|
+
dog.saved?.should == true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe FactoryGirl::Syntax::ObjectMethods do
|
75
|
+
|
76
|
+
it "raises useful Exception when no matching factory can be found" do
|
77
|
+
expect { Dog.build(:foo, :bar) }.to raise_error(ArgumentError, %{Could not find factory for "dog" with [:foo, :bar]})
|
78
|
+
expect { Dog.generate(:foo, :bar) }.to raise_error(ArgumentError, %{Could not find factory for "dog" with [:foo, :bar]})
|
79
|
+
expect { Dog.attributes(:foo, :bar) }.to raise_error(ArgumentError, %{Could not find factory for "dog" with [:foo, :bar]})
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#build" do
|
83
|
+
after do
|
84
|
+
@dog.should_not be_saved if @dog
|
85
|
+
end
|
86
|
+
|
87
|
+
it "without arguments" do
|
88
|
+
@dog = Dog.build
|
89
|
+
@dog.name.should == "Rover"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "with overrides" do
|
93
|
+
@dog = Dog.build(:name => "Spot")
|
94
|
+
@dog.name.should == "Spot"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "yields the built instance to block" do
|
98
|
+
@dog = Dog.build(:name => "Spot"){|d| d.name += " Remover" }
|
99
|
+
@dog.name.should == "Spot Remover"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "with prefix" do
|
103
|
+
@dog = Dog.build(:awesome)
|
104
|
+
@dog.name.should == "Awesome Dog"
|
105
|
+
end
|
106
|
+
|
107
|
+
it "with suffix" do
|
108
|
+
@dog = Dog.build(:with_toys)
|
109
|
+
@dog.name.should == "Dog with toys"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "with prefix and suffix" do
|
113
|
+
@dog = Dog.build(:awesome, :with_toys)
|
114
|
+
@dog.name.should == "Awesome Dog with toys"
|
115
|
+
end
|
116
|
+
|
117
|
+
it "with prefix and suffix (reversed works too)" do
|
118
|
+
@dog = Dog.build(:with_toys, :awesome)
|
119
|
+
@dog.name.should == "Awesome Dog with toys"
|
120
|
+
end
|
121
|
+
|
122
|
+
it "cannot pass more than 2 prefix/suffix" do
|
123
|
+
expect { Dog.build(:one, :two, :three) }.to raise_error(ArgumentError, %{Don't know how to find factory for "dog" with [:one, :two, :three]})
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#generate" do
|
128
|
+
after do
|
129
|
+
@dog.should be_saved if @dog
|
130
|
+
end
|
131
|
+
|
132
|
+
it "can call #gen as a shortcut" do
|
133
|
+
@dog = Dog.gen
|
134
|
+
@dog.name.should == "Rover"
|
135
|
+
@dog.should be_saved
|
136
|
+
end
|
137
|
+
|
138
|
+
it "can call with a bang to save! (to raise an Exception on failure)" do
|
139
|
+
expect { Dog.generate! }.to raise_error(RuntimeError, /Called save!/)
|
140
|
+
expect { Dog.gen! }.to raise_error(RuntimeError, /Called save!/)
|
141
|
+
|
142
|
+
Dog.gen!(:name => "Valid Name").name.should == "Valid Name"
|
143
|
+
Dog.gen!(:name => "Valid Name"){|d| d.name += " FOO" }.name.should == "Valid Name FOO"
|
144
|
+
end
|
145
|
+
|
146
|
+
it "without arguments" do
|
147
|
+
@dog = Dog.generate
|
148
|
+
@dog.name.should == "Rover"
|
149
|
+
end
|
150
|
+
|
151
|
+
it "with overrides" do
|
152
|
+
@dog = Dog.generate(:name => "Spot")
|
153
|
+
@dog.name.should == "Spot"
|
154
|
+
end
|
155
|
+
|
156
|
+
it "yields the built instance to block (after calling #save on it)" do
|
157
|
+
@dog = Dog.generate(:name => "Spot") do |dog|
|
158
|
+
dog.should be_saved
|
159
|
+
dog.name += " Remover"
|
160
|
+
end
|
161
|
+
@dog.name.should == "Spot Remover"
|
162
|
+
end
|
163
|
+
|
164
|
+
it "generate! yields the resulting instance (after calling save! on it)" do
|
165
|
+
Dog.gen!(:name => "Valid Name") do |dog|
|
166
|
+
dog.should be_saved
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
it "with prefix" do
|
171
|
+
@dog = Dog.generate(:awesome)
|
172
|
+
@dog.name.should == "Awesome Dog"
|
173
|
+
end
|
174
|
+
|
175
|
+
it "with suffix" do
|
176
|
+
@dog = Dog.generate(:with_toys)
|
177
|
+
@dog.name.should == "Dog with toys"
|
178
|
+
end
|
179
|
+
|
180
|
+
it "with prefix and suffix" do
|
181
|
+
@dog = Dog.generate(:awesome, :with_toys)
|
182
|
+
@dog.name.should == "Awesome Dog with toys"
|
183
|
+
end
|
184
|
+
|
185
|
+
it "with prefix and suffix (reversed works too)" do
|
186
|
+
@dog = Dog.generate(:with_toys, :awesome)
|
187
|
+
@dog.name.should == "Awesome Dog with toys"
|
188
|
+
end
|
189
|
+
|
190
|
+
it "cannot pass more than 2 prefix/suffix" do
|
191
|
+
expect { Dog.generate(:one, :two, :three) }.to raise_error(ArgumentError, %{Don't know how to find factory for "dog" with [:one, :two, :three]})
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "#attributes" do
|
196
|
+
it "without arguments" do
|
197
|
+
Dog.attributes.should == { :name => "Rover" }
|
198
|
+
end
|
199
|
+
|
200
|
+
it "can call #attrs as a shortcut" do
|
201
|
+
Dog.attrs.should == { :name => "Rover" }
|
202
|
+
end
|
203
|
+
|
204
|
+
it "with overrides" do
|
205
|
+
Dog.attributes(:name => "Spot").should == { :name => "Spot" }
|
206
|
+
end
|
207
|
+
|
208
|
+
it "yields the built instance to block" do
|
209
|
+
Dog.attributes(:name => "Spot"){|hash| hash[:name] += " Remover" }.should == { :name => "Spot Remover" }
|
210
|
+
end
|
211
|
+
|
212
|
+
it "with prefix" do
|
213
|
+
Dog.attributes(:awesome).should == { :name => "Awesome Dog" }
|
214
|
+
end
|
215
|
+
|
216
|
+
it "with suffix" do
|
217
|
+
Dog.attributes(:with_toys).should == { :name => "Dog with toys" }
|
218
|
+
end
|
219
|
+
|
220
|
+
it "with prefix and suffix" do
|
221
|
+
Dog.attributes(:awesome, :with_toys).should == { :name => "Awesome Dog with toys" }
|
222
|
+
end
|
223
|
+
|
224
|
+
it "with prefix and suffix (reversed works too)" do
|
225
|
+
Dog.attributes(:with_toys, :awesome).should == { :name => "Awesome Dog with toys" }
|
226
|
+
end
|
227
|
+
|
228
|
+
it "cannot pass more than 2 prefix/suffix" do
|
229
|
+
expect { Dog.attributes(:one, :two, :three) }.to raise_error(ArgumentError, %{Don't know how to find factory for "dog" with [:one, :two, :three]})
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
metadata
CHANGED
@@ -1,82 +1,89 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: factory_girl_extensions
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 4
|
9
|
-
- 0
|
10
|
-
version: 0.4.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- remi
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-02-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: factory_girl
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &19502360 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
- 0
|
32
|
-
- 0
|
33
|
-
version: 0.0.0
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
34
22
|
type: :runtime
|
35
|
-
|
36
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *19502360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &19501200 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *19501200
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &19499300 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *19499300
|
47
|
+
description: ! "Alternative FactoryGirl API allowing you to build/generate factories
|
48
|
+
\nusing your class constants, eg. User.gen instead of Factory(:user).\n"
|
37
49
|
email: remi@remitaylor.com
|
38
50
|
executables: []
|
39
|
-
|
40
51
|
extensions: []
|
41
|
-
|
42
52
|
extra_rdoc_files: []
|
43
|
-
|
44
|
-
|
45
|
-
-
|
53
|
+
files:
|
54
|
+
- .gemtest
|
55
|
+
- .gitignore
|
56
|
+
- Gemfile
|
57
|
+
- README.markdown
|
58
|
+
- Rakefile
|
59
|
+
- factory_girl_extensions.gemspec
|
46
60
|
- lib/factory_girl_extensions.rb
|
61
|
+
- lib/factory_girl_extensions/core.rb
|
62
|
+
- lib/factory_girl_extensions/version.rb
|
63
|
+
- spec/factory_girl_extensions_spec.rb
|
47
64
|
homepage: http://github.com/remi/factory_girl_extensions
|
48
65
|
licenses: []
|
49
|
-
|
50
66
|
post_install_message:
|
51
67
|
rdoc_options: []
|
52
|
-
|
53
|
-
require_paths:
|
68
|
+
require_paths:
|
54
69
|
- lib
|
55
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
71
|
none: false
|
57
|
-
requirements:
|
58
|
-
- -
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
|
61
|
-
|
62
|
-
- 0
|
63
|
-
version: "0"
|
64
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
77
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
segments:
|
71
|
-
- 0
|
72
|
-
version: "0"
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
73
82
|
requirements: []
|
74
|
-
|
75
83
|
rubyforge_project:
|
76
84
|
rubygems_version: 1.8.17
|
77
85
|
signing_key:
|
78
86
|
specification_version: 3
|
79
|
-
summary:
|
80
|
-
test_files:
|
81
|
-
|
82
|
-
has_rdoc:
|
87
|
+
summary: Alternative FactoryGirl API
|
88
|
+
test_files:
|
89
|
+
- spec/factory_girl_extensions_spec.rb
|
@@ -1,91 +0,0 @@
|
|
1
|
-
# Just the module. You should require this if you don't want FactoryGirlExtensions
|
2
|
-
# automatically included into Object.
|
3
|
-
|
4
|
-
# Adds helpful factory_girl methods to objects.
|
5
|
-
#
|
6
|
-
# This uses method_missing just incase the given Object
|
7
|
-
# already responds to one of these methods.
|
8
|
-
#
|
9
|
-
# == Usage
|
10
|
-
#
|
11
|
-
# User.generate! # this is equivalent to Factory(:user) or Factory.create(:user)
|
12
|
-
# User.gen! # this is a shortcut alias for #generate
|
13
|
-
# User.generate # this is equivalent to Factory.build(:user) and then #save
|
14
|
-
# User.gen # this is equivalent to Factory.build(:user) and then #save
|
15
|
-
# User.build # this is equivalent to Factory.build(:user)
|
16
|
-
# User.gen! :name => 'Bob' # this is equivalent to Factory(:user, :name => 'Bob')
|
17
|
-
# :email.next # this is equivalent to Factory.next(:email)
|
18
|
-
# 'email'.next # this will NOT work because String#next already exists
|
19
|
-
# :admin_user.gen! # this is equivalent to Factory.gen(:admin_user)
|
20
|
-
# 'admin_user'.gen! # this is equivalent to Factory.gen(:admin_user)
|
21
|
-
# User.attrs # this is equivalent to Factory.attributes_for(:user)
|
22
|
-
# 'user'.attrs # this is equivalent to Factory.attributes_for(:user)
|
23
|
-
# :user.attrs # this is equivalent to Factory.attributes_for(:user)
|
24
|
-
#
|
25
|
-
# == TODO
|
26
|
-
#
|
27
|
-
# * properly implement <tt>respond_to?</tt>
|
28
|
-
# * add syntax like User.gen_admin or User.gen(:admin) for generating an :admin_user
|
29
|
-
#
|
30
|
-
module FactoryGirlExtensions
|
31
|
-
|
32
|
-
# I was relying on String#underscore being available and it's not always.
|
33
|
-
# Copies this from ActiveSupport.
|
34
|
-
def underscore_string string
|
35
|
-
string.to_s.gsub(/::/, '/').
|
36
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
37
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
38
|
-
tr("-", "_").
|
39
|
-
downcase
|
40
|
-
end
|
41
|
-
|
42
|
-
# This is the actual (private) implementation
|
43
|
-
def self.__method_missing object, name, *args, &block
|
44
|
-
raise 'Factory is not defined. Have you required factory_girl?' unless defined? Factory
|
45
|
-
|
46
|
-
messages = case name.to_s
|
47
|
-
when /^gen(erate)?\!$/
|
48
|
-
[:build, :save!]
|
49
|
-
when /^gen(erate)?$/
|
50
|
-
[:build, :save]
|
51
|
-
when 'build'
|
52
|
-
[:build]
|
53
|
-
when 'next'
|
54
|
-
[:next]
|
55
|
-
when /^attr(ibute)?s(_for)?$/
|
56
|
-
[:attributes_for]
|
57
|
-
end
|
58
|
-
|
59
|
-
if messages
|
60
|
-
# if this is an instance of String/Symbol use this instance as the factory name, else use the class name
|
61
|
-
factory_name = ( object.kind_of?(Symbol) || object.kind_of?(String) ) ? object.to_s.to_sym : underscore_string(object.name).to_sym
|
62
|
-
|
63
|
-
factory_method, instance_method = messages
|
64
|
-
instance = Factory.send factory_method, factory_name, *args
|
65
|
-
|
66
|
-
if instance_method
|
67
|
-
instance.send instance_method if instance.respond_to? instance_method
|
68
|
-
end
|
69
|
-
|
70
|
-
instance
|
71
|
-
|
72
|
-
else
|
73
|
-
:no_extension_found
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# This is the public implementation. When you include
|
78
|
-
# FactoryGirlExtensions into a class, this is what gives
|
79
|
-
# you the #gen and other methods.
|
80
|
-
def method_missing name, *args, &block
|
81
|
-
object = FactoryGirlExtensions.__method_missing(self, name, *args, &block)
|
82
|
-
|
83
|
-
# If no extensions were found, call super
|
84
|
-
if object == :no_extension_found
|
85
|
-
super
|
86
|
-
else
|
87
|
-
object
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|