threedaymonk-factory_girl 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ 1.1.3 (September 12, 2008)
2
+ Automatically pull in definitions from factories.rb, test/factories.rb, or
3
+ spec/factories.rb
4
+ 1.1.2 (July 30, 2008)
5
+ Improved error handling for invalid and undefined factories/attributes
6
+ Improved handling of strings vs symbols vs classes
7
+ Added a prettier syntax for handling associations
8
+ Updated documentation and fixed compatibility with Rails 2.1
9
+
10
+ 1.1.1 (June 23, 2008)
11
+ The attribute "name" no longer requires using #add_attribute
12
+
13
+ 1.1.0 (June 3, 2008)
14
+ Added support for dependent attributes
15
+ Fixed the attributes_for build strategy to not build associations
16
+ Added support for sequences
17
+
18
+ 1.0.0 (May 31, 208)
19
+ First version
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008 Joe Ferris and thoughtbot, inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,155 @@
1
+ h1. factory_girl
2
+
3
+ Written by "Joe Ferris":mailto:jferris@thoughtbot.com.
4
+
5
+ Thanks to Tammer Saleh, Dan Croak, and Jon Yurek of thoughtbot, inc.
6
+
7
+ Copyright 2008 Joe Ferris and thoughtbot, inc.
8
+
9
+ h2. Download
10
+
11
+ Github: "Page":http://github.com/thoughtbot/factory_girl/tree/master "Clone":git://github.com/thoughtbot/factory_girl.git
12
+
13
+ Gem: <pre>gem install thoughtbot-factory_girl --source http://gems.github.com</pre>
14
+
15
+ Note: if you install factory_girl using the gem from Github, you'll need this
16
+ in your environment.rb if you want to use Rails 2.1's dependency manager:
17
+
18
+ config.gem "thoughtbot-factory_girl",
19
+ :lib => "factory_girl",
20
+ :source => "http://gems.github.com"
21
+
22
+ h2. Defining factories
23
+
24
+ <pre><code># This will guess the User class
25
+ Factory.define :user do |u|
26
+ u.first_name 'John'
27
+ u.last_name 'Doe'
28
+ u.admin false
29
+ end
30
+
31
+ # This will use the User class (Admin would have been guessed)
32
+ Factory.define :admin, :class => User do |u|
33
+ u.first_name 'Admin'
34
+ u.last_name 'User'
35
+ u.admin true
36
+ end</code></pre>
37
+
38
+
39
+ It is recommended that you create a test/factories.rb file and define your
40
+ factories there. This file can be included from test_helper or directly from
41
+ your test files. Don't forget:
42
+ <pre><code>require 'factory_girl'</code></pre>
43
+
44
+
45
+ h2. Lazy Attributes
46
+
47
+ Most attributes can be added using static values that are evaluated when the
48
+ factory is defined, but some attributes (such as associations and other
49
+ attributes that must be dynamically generated) will need values assigned each
50
+ time an instance is generated. These "lazy" attributes can be added by passing
51
+ a block instead of a parameter:
52
+
53
+ <pre><code>Factory.define :user do |u|
54
+ # ...
55
+ u.activation_code { User.generate_activation_code }
56
+ end</code></pre>
57
+
58
+
59
+ h2. Dependent Attributes
60
+
61
+ Some attributes may need to be generated based on the values of other
62
+ attributes. This can be done by calling the attribute name on
63
+ Factory::AttributeProxy, which is yielded to lazy attribute blocks:
64
+
65
+ <pre><code>Factory.define :user do |u|
66
+ u.first_name 'Joe'
67
+ u.last_name 'Blow'
68
+ u.email {|a| "#{a.first_name}.#{a.last_name}@example.com".downcase }
69
+ end
70
+
71
+ Factory(:user, :last_name => 'Doe').email
72
+ # => "joe.doe@example.com"</code></pre>
73
+
74
+
75
+ h2. Associations
76
+
77
+ Associated instances can be generated by using the association method when
78
+ defining a lazy attribute:
79
+
80
+ <pre><code>Factory.define :post do |p|
81
+ # ...
82
+ p.author {|author| author.association(:user, :last_name => 'Writely') }
83
+ end</code></pre>
84
+
85
+
86
+ When using the association method, the same build strategy (build, create, or attributes_for) will be used for all generated instances:
87
+
88
+ <pre><code># Builds and saves a User and a Post
89
+ post = Factory(:post)
90
+ post.new_record? # => false
91
+ post.author.new_record # => false
92
+
93
+ # Builds but does not save a User and a Post
94
+ Factory.build(:post)
95
+ post.new_record? # => true
96
+ post.author.new_record # => true</code></pre>
97
+
98
+ Because this pattern is so common, a prettier syntax is available for defining
99
+ associations:
100
+
101
+ <pre><code># The following definitions are equivilent:
102
+ Factory.define :post do |p|
103
+ p.author {|a| a.association(:user) }
104
+ end
105
+
106
+ Factory.define :post do |p|
107
+ p.association :author, :factory => :user
108
+ end</code></pre>
109
+
110
+ If the factory name is the same as the association name, the factory name can
111
+ be left out.
112
+
113
+
114
+ h2. Sequences
115
+
116
+ Unique values in a specific format (for example, e-mail addresses) can be
117
+ generated using sequences. Sequences are defined by calling Factory.sequence,
118
+ and values in a sequence are generated by calling Factory.next:
119
+
120
+ <pre><code># Defines a new sequence
121
+ Factory.sequence :email do |n|
122
+ "person#{n}@example.com"
123
+ end
124
+
125
+ Factory.next :email
126
+ # => "person1@example.com"
127
+
128
+ Factory.next :email
129
+ # => "person2@example.com"</code></pre>
130
+
131
+ You can also define an anonymous sequence within a Factory.define block:
132
+
133
+ <pre><code># Defines a sequence for name
134
+ Factory.define :person do |p|
135
+ p.sequence :name do |n|
136
+ "Johnny #{n}"
137
+ end
138
+ end</code></pre>
139
+
140
+ h2. Using factories
141
+
142
+ <pre><code># Build and save a User instance
143
+ Factory(:user)
144
+
145
+ # Build a User instance and override the first_name property
146
+ Factory.build(:user, :first_name => 'Joe')
147
+
148
+ # Return an attributes Hash that can be used to build a User instance
149
+ attrs = Factory.attributes_for(:user)</code></pre>
150
+
151
+ h2. More Information
152
+
153
+ "Our blog":http://giantrobots.thoughtbot.com
154
+
155
+ "factory_girl rdoc":http://dev.thoughtbot.com/factory_girl
@@ -0,0 +1,69 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+ require 'date'
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => :test
10
+
11
+ desc 'Test the factory_girl plugin.'
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'lib'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the factory_girl plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'Factory Girl'
22
+ rdoc.options << '--line-numbers' << '--inline-source' << "--main" << "README.textile"
23
+ rdoc.rdoc_files.include('README.textile')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ desc 'Update documentation on website'
28
+ task :sync_docs => 'rdoc' do
29
+ `rsync -ave ssh rdoc/ dev@dev.thoughtbot.com:/home/dev/www/dev.thoughtbot.com/factory_girl`
30
+ end
31
+
32
+ spec = Gem::Specification.new do |s|
33
+ s.name = %q{factory_girl}
34
+ s.version = "1.1.3"
35
+ s.summary = %q{factory_girl provides a framework and DSL for defining and
36
+ using model instance factories.}
37
+ s.description = %q{factory_girl provides a framework and DSL for defining and
38
+ using factories - less error-prone, more explicit, and
39
+ all-around easier to work with than fixtures.}
40
+
41
+ s.files = FileList['[A-Z]*', 'lib/**/*.rb', 'test/**/*.rb']
42
+ s.require_path = 'lib'
43
+ s.test_files = Dir[*['test/**/*_test.rb']]
44
+
45
+ s.has_rdoc = true
46
+ s.extra_rdoc_files = ["README.textile"]
47
+ s.rdoc_options = ['--line-numbers', '--inline-source', "--main", "README.textile"]
48
+
49
+ s.authors = ["Joe Ferris"]
50
+ s.email = %q{jferris@thoughtbot.com}
51
+
52
+ s.platform = Gem::Platform::RUBY
53
+ s.add_dependency(%q<activesupport>, [">= 1.0"])
54
+ end
55
+
56
+ Rake::GemPackageTask.new spec do |pkg|
57
+ pkg.need_tar = true
58
+ pkg.need_zip = true
59
+ end
60
+
61
+ desc "Clean files generated by rake tasks"
62
+ task :clobber => [:clobber_rdoc, :clobber_package]
63
+
64
+ desc "Generate a gemspec file"
65
+ task :gemspec do
66
+ File.open("#{spec.name}.gemspec", 'w') do |f|
67
+ f.write spec.to_ruby
68
+ end
69
+ end
@@ -0,0 +1,16 @@
1
+ require 'active_support'
2
+ require 'factory_girl/factory'
3
+ require 'factory_girl/attribute_proxy'
4
+ require 'factory_girl/attribute'
5
+ require 'factory_girl/sequence'
6
+ require 'factory_girl/aliases'
7
+
8
+ # Shortcut for Factory.create.
9
+ #
10
+ # Example:
11
+ # Factory(:user, :name => 'Joe')
12
+ def Factory (name, attrs = {})
13
+ Factory.create(name, attrs)
14
+ end
15
+
16
+ Factory.find_definitions
@@ -0,0 +1,37 @@
1
+ class Factory
2
+
3
+ cattr_accessor :aliases #:nodoc:
4
+ self.aliases = [
5
+ [/(.*)_id/, '\1'],
6
+ [/(.*)/, '\1_id']
7
+ ]
8
+
9
+ # Defines a new alias for attributes
10
+ #
11
+ # Arguments:
12
+ # pattern: (Regexp)
13
+ # A pattern that will be matched against attributes when looking for
14
+ # aliases. Contents captured in the pattern can be used in the alias.
15
+ # replace: (String)
16
+ # The alias that results from the matched pattern. Captured strings can
17
+ # be insert like String#sub.
18
+ #
19
+ # Example:
20
+ #
21
+ # Factory.alias /(.*)_confirmation/, '\1'
22
+ def self.alias (pattern, replace)
23
+ self.aliases << [pattern, replace]
24
+ end
25
+
26
+ def self.aliases_for (attribute) #:nodoc:
27
+ aliases.collect do |params|
28
+ pattern, replace = *params
29
+ if pattern.match(attribute.to_s)
30
+ attribute.to_s.sub(pattern, replace).to_sym
31
+ else
32
+ nil
33
+ end
34
+ end.compact << attribute
35
+ end
36
+
37
+ end
@@ -0,0 +1,38 @@
1
+ class Factory
2
+
3
+ class AttributeDefinitionError < RuntimeError
4
+ end
5
+
6
+ class Attribute #:nodoc:
7
+
8
+ attr_reader :name
9
+
10
+ def initialize (name, static_value, lazy_block)
11
+ name = name.to_sym
12
+
13
+ if name.to_s =~ /=$/
14
+ raise AttributeDefinitionError,
15
+ "factory_girl uses 'f.#{name.to_s.chop} value' syntax " +
16
+ "rather than 'f.#{name} = value'"
17
+ end
18
+
19
+ unless static_value.nil? || lazy_block.nil?
20
+ raise AttributeDefinitionError, "Both value and block given"
21
+ end
22
+
23
+ @name = name
24
+ @static_value = static_value
25
+ @lazy_block = lazy_block
26
+ end
27
+
28
+ def value (proxy)
29
+ if @lazy_block.nil?
30
+ @static_value
31
+ else
32
+ @lazy_block.call(proxy)
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,92 @@
1
+ class Factory
2
+
3
+ class AttributeProxy
4
+
5
+ attr_accessor :factory, :attribute_name, :strategy, :current_values #:nodoc:
6
+
7
+ def initialize (factory, attr, strategy, values) #:nodoc:
8
+ @factory = factory
9
+ @attribute_name = attr
10
+ @strategy = strategy
11
+ @current_values = values
12
+ end
13
+
14
+ # Generates an association using the current build strategy.
15
+ #
16
+ # Arguments:
17
+ # name: (Symbol)
18
+ # The name of the factory that should be used to generate this
19
+ # association.
20
+ # attributes: (Hash)
21
+ # A hash of attributes that should be overridden for this association.
22
+ #
23
+ # Returns:
24
+ # The generated association for the current build strategy. Note that
25
+ # assocaitions are not generated for the attributes_for strategy. Returns
26
+ # nil in this case.
27
+ #
28
+ # Example:
29
+ #
30
+ # Factory.define :user do |f|
31
+ # # ...
32
+ # end
33
+ #
34
+ # Factory.define :post do |f|
35
+ # # ...
36
+ # f.author {|a| a.association :user, :name => 'Joe' }
37
+ # end
38
+ #
39
+ # # Builds (but doesn't save) a Post and a User
40
+ # Factory.build(:post)
41
+ #
42
+ # # Builds and saves a User, builds a Post, assigns the User to the
43
+ # # author association, and saves the User.
44
+ # Factory.create(:post)
45
+ #
46
+ def association (name, attributes = {})
47
+ if strategy == :attributes_for
48
+ nil
49
+ else
50
+ Factory.send(strategy, name, attributes)
51
+ end
52
+ end
53
+
54
+ # Returns the value for specified attribute. A value will only be available
55
+ # if it was overridden when calling the factory, or if a value is added
56
+ # earlier in the definition of the factory.
57
+ #
58
+ # Arguments:
59
+ # attribute: (Symbol)
60
+ # The attribute whose value should be returned.
61
+ #
62
+ # Returns:
63
+ # The value of the requested attribute. (Object)
64
+ def value_for (attribute)
65
+ unless current_values.key?(attribute)
66
+ raise ArgumentError, "No such attribute: #{attribute.inspect}"
67
+ end
68
+ current_values[attribute]
69
+ end
70
+
71
+ # Undefined methods are delegated to value_for, which means that:
72
+ #
73
+ # Factory.define :user do |f|
74
+ # f.first_name 'Ben'
75
+ # f.last_name {|a| a.value_for(:first_name) }
76
+ # end
77
+ #
78
+ # and:
79
+ #
80
+ # Factory.define :user do |f|
81
+ # f.first_name 'Ben'
82
+ # f.last_name {|a| a.first_name }
83
+ # end
84
+ #
85
+ # are equivilent.
86
+ def method_missing (name, *args, &block)
87
+ current_values[name]
88
+ end
89
+
90
+ end
91
+
92
+ end