fabrication 0.9.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,199 +1,14 @@
1
- ### Fabrication ###
1
+ # Overview
2
2
 
3
- Fabrication is an object generation library. It allows you to define Fabricators that are essentially the schematic for objects you want to generate. You can then generate them as needed anywhere in your app or specs.
3
+ ## About Fabrication
4
4
 
5
- Currently supported object types are...
5
+ Fabrication is an object generation framework for Ruby.
6
6
 
7
- * Plain old Ruby objects
8
- * ActiveRecord objects
9
- * Mongoid Documents
10
- * Sequel Models
7
+ ## Compatibility
11
8
 
12
- By default it will lazily generate active record associations. So if you have a has_many :widgets defined, it will not actually generate the widgets until the association is accessed. You can override this by appending "!" to the name of the parameter when defining the field in the Fabricator.
9
+ Fabrication is developed against Ruby 1.8.7 and 1.9.2.
13
10
 
14
- ### Installation ###
11
+ ## Documentation
15
12
 
16
- Add this to your gemfile.
17
-
18
- `gem 'fabrication'`
19
-
20
- Now you can define fabricators in any of the following locations.
21
-
22
- * `spec/fabricators.rb`
23
- * `spec/fabricators/*.rb`
24
-
25
- * `test/fabricators.rb`
26
- * `test/fabricators/*.rb`
27
-
28
- They are automatically loaded, so no additional requires are necessary.
29
-
30
- ### Rails 3 Generators ###
31
-
32
- They are really easy to configure! Just add this to your `config/application.rb`:
33
-
34
- config.generators do |g|
35
- g.test_framework :rspec, :fixture => true
36
- g.fixture_replacement :fabrication, :dir => "spec/fabricators"
37
- end
38
-
39
- ### Cucumber Steps ###
40
-
41
- Packaged with the gem is a generator which will load some handy cucumber table steps into your step_definitions folder. You can get them by running `rails g fabrication:cucumber_steps`.
42
-
43
- To generate a single "widget" object (expecting a Fabricator(:widget) to be defined):
44
-
45
- Given 1 widget
46
-
47
- To generate a single "widget" object with specified attributes:
48
-
49
- Given the following widget:
50
- | name | widget_1 |
51
- | color | red |
52
-
53
- To generate multiple "widget" objects:
54
-
55
- Given 10 widgets
56
-
57
- To generate multiple "widget" objects with specified attributes:
58
-
59
- Given the following widgets:
60
- | name | color |
61
- | widget_1 | red |
62
- | widget_2 | blue |
63
- ...
64
-
65
- To generate "wockets" nested within "widget" objects:
66
-
67
- And that widget has the following wocket:
68
- | title | Amazing |
69
- | category | fancy |
70
-
71
- That will use the most recently defined "widget" and pass it into the Fabricator. That requires your "wocket" to have a setter for a "widget".
72
-
73
- ### Usage ###
74
-
75
- Define your fabricators.
76
-
77
- Fabricator(:company) do
78
- name "Fun Factory"
79
- employees(:count => 20) { |company, i| Fabricate(:drone, :company => company, :name => "Drone #{i}") }
80
- location!
81
- after_build { |company| company.name = "Another #{company.name}" }
82
- after_create { |company| company.update_attribute(:ceo, Fabricate(:drone, :name => 'Lead Drone') }
83
- end
84
-
85
- Breaking down the above, we are defining a "company" fabricator, which will generate Company model objects.
86
-
87
- * The object has a name field, which is statically filled with "Fun Factory".
88
- * It has a has_many association to employees and will generate an array of 20 records as indicated by the :count => 20. The block is passed the company object being fabricated and index of the array being created.
89
- * It has a belongs_to association to location and this will be generated immediately with the company object. This is because of the "!" after the association name. Also, leaving off the block will cause "{ Fabricate(:location) }" to be automatically generated for you. It will singularize the name of the attribute (if String#singularize is present) and use that as the fabricator name.
90
- * After the object is built but before it is saved, it will update the name to "Another Fun Factory".
91
- * After the object is created, it will update the "ceo" association with a new "drone" record.
92
-
93
-
94
- For a class with required arguments in its constructor, use the `on_init` method:
95
-
96
- Fabricator(:location) do
97
- on_init { init_with(30.284167, -81.396111) }
98
- end
99
-
100
-
101
- ### Inheritance ###
102
-
103
- So you already have a company fabricator, but you need one that specifically generates an LLC. No problem!
104
-
105
- Fabricator(:llc, :from => :company) do
106
- type "LLC"
107
- end
108
-
109
- Setting the :from option will inherit the class and all the attributes from the named Fabricator.
110
-
111
- You can also explicitly specify the class being fabricated with the :class_name parameter.
112
-
113
- Fabricator(:llc, :class_name => :company) do
114
- type "LLC"
115
- end
116
-
117
- The callbacks will be stacked when inheriting from other fabricators. For example, when you define something like this:
118
-
119
- Fabricator(:user) do
120
- after_create { |user| user.confirm! }
121
- end
122
-
123
- Fabricator(:admin, :from => :user) do
124
- after_create { |user| user.make_admin! }
125
- end
126
-
127
- When calling `Fabricate(:admin)`, the user callback will be executed first and then the admin callback.
128
-
129
- ### Fabricating ###
130
-
131
- Now that your Fabricators are defined, you can start generating some objects! To generate the LLC from the previous example, just do this:
132
-
133
- llc = Fabricate(:llc, :name => "Awesome Labs", :location => "Earth")
134
-
135
- That will return an instance of the LLC using the fields defined in the Fabricators and overriding with anything passed into Fabricate.
136
-
137
- If you need to do something more complex, you can also pass a block to Fabricate. You can use all the features available to you when defining Fabricators, but they only apply to the object generated by this Fabricate call.
138
-
139
- llc = Fabricate(:llc, :name => "Awesome, Inc.") do
140
- location!(:count => 2) { Faker::Address.city }
141
- end
142
-
143
- Sometimes you don't actually need to save an option when it is created but just build it. In that case, just call `Fabricate.build` and it will skip the saving step.
144
-
145
- Fabricate.build(:company, :name => "Hashrocket")
146
-
147
- You can also fabricate the object as an attribute hash instead of an actual instance. This is useful for controller or API testing where the receiver wants a hash representation of the object. If you have activesupport it will be a HashWithIndifferentAccess, otherwise it will be a regular Ruby Hash.
148
-
149
- Fabricate.attributes_for(:company)
150
-
151
- ### Sequences ###
152
-
153
- Sometimes you need a sequence of numbers while you're generating data. Fabrication provides you with an easy and flexible means for keeping track of sequences.
154
-
155
- This will create a sequence named ":number" that will start at 0. Every time you call it, it will increment by one.
156
-
157
- Fabricate.sequence(:number)
158
-
159
- If you need to override the starting number, you can do it with a second parameter. It will always return the seed number on the first call and it will be ignored with subsequent calls.
160
-
161
- Fabricate.sequence(:number, 99)
162
-
163
- If you are generating something like an email address, you can pass it a block and the block response will be returned.
164
-
165
- Fabricate.sequence(:name) { |i| "Name #{i}" }
166
-
167
- And in a semi-real use case, it would look something like this:
168
-
169
- Fabricate(:person) do
170
- ssn { Fabricate.sequence :ssn, 111111111 }
171
- email { Fabricate.sequence(:email) { |i| "user#{i}@example.com" } }
172
- end
173
-
174
- ### Contributing ###
175
-
176
- I (paulelliott) am actively maintaining this project. If you would like to contribute, please fork the project, make your changes on a feature branch, and submit a pull request.
177
-
178
- To run rake successfully:
179
-
180
- 1. Clone the project
181
- 2. Install mongodb and sqlite3 (brew install ...)
182
- 3. Install bundler (gem install bundler)
183
- 4. Run `bundle install` from the project root
184
- 5. Run `rake` and the test suite should be all green!
185
-
186
- ### Contributors ###
187
-
188
- * Les Hill (leshill)
189
- * Jim Remsik (bigtiger)
190
- * Dave Ott (daveott)
191
- * Matt (winescout)
192
- * Lar Van Der Jagt (supaspoida)
193
- * Sandro Turriate (sandro)
194
- * Justin Smestad (jsmestad)
195
- * Christopher Hanks (chanks) - Chained callbacks
196
- * monsterlabs - Rails 3 Generators
197
- * Brandon Weiss (brandonweiss) - Sequal Model support
198
- * Tim Pope (tpope) - Singularize generated fabricator names
199
- * hakanensari - Default attribute cucumber steps
13
+ Please see the Fabrication website for up-to-date documentation:
14
+ {fabricationgem.org}[http://fabricationgem.org]
@@ -5,6 +5,7 @@ module Fabrication
5
5
  autoload :UnknownFabricatorError, 'fabrication/errors/unknown_fabricator_error'
6
6
 
7
7
  autoload :Attribute, 'fabrication/attribute'
8
+ autoload :Config, 'fabrication/config'
8
9
  autoload :Fabricator, 'fabrication/fabricator'
9
10
  autoload :Sequencer, 'fabrication/sequencer'
10
11
  autoload :Schematic, 'fabrication/schematic'
@@ -13,7 +14,7 @@ module Fabrication
13
14
  module Generator
14
15
  autoload :ActiveRecord, 'fabrication/generator/active_record'
15
16
  autoload :Mongoid, 'fabrication/generator/mongoid'
16
- autoload :Sequel, 'fabrication/generator/sequel'
17
+ autoload :Sequel, 'fabrication/generator/sequel'
17
18
  autoload :Base, 'fabrication/generator/base'
18
19
  end
19
20
 
@@ -22,6 +23,10 @@ module Fabrication
22
23
  Sequencer.sequences.clear
23
24
  end
24
25
 
26
+ def self.configure(&block)
27
+ Fabrication::Config.configure(&block)
28
+ end
29
+
25
30
  end
26
31
 
27
32
  def Fabricator(name, options={}, &block)
@@ -36,30 +41,20 @@ end
36
41
 
37
42
  class Fabricate
38
43
 
39
- class << self
40
-
41
- def attributes_for(name, options={}, &block)
42
- Fabrication::Fabricator.generate(name, {
43
- :save => false, :attributes => true
44
- }, options, &block)
45
- end
46
-
47
- def build(name, options={}, &block)
48
- Fabrication::Fabricator.generate(name, {
49
- :save => false
50
- }, options, &block)
51
- end
52
-
53
- def sequence(name, start=0, &block)
54
- Fabrication::Sequencer.sequence(name, start, &block)
55
- end
56
-
44
+ def self.attributes_for(name, options={}, &block)
45
+ Fabrication::Fabricator.generate(name, {
46
+ :save => false, :attributes => true
47
+ }, options, &block)
57
48
  end
58
49
 
59
- end
50
+ def self.build(name, options={}, &block)
51
+ Fabrication::Fabricator.generate(name, {
52
+ :save => false
53
+ }, options, &block)
54
+ end
60
55
 
61
- class Fabricator
62
- def self.name_for(name)
63
- Fabrication::Support.name_for(name)
56
+ def self.sequence(name, start=0, &block)
57
+ Fabrication::Sequencer.sequence(name, start, &block)
64
58
  end
59
+
65
60
  end
@@ -0,0 +1,29 @@
1
+ module Fabrication
2
+ module Config
3
+ extend self
4
+
5
+ def configure
6
+ yield self
7
+ end
8
+
9
+ def fabricator_dir
10
+ OPTIONS[:fabricator_dir]
11
+ end
12
+
13
+ def fabricator_dir=(folders)
14
+ OPTIONS[:fabricator_dir] = (Array.new << folders).flatten
15
+ end
16
+
17
+ def reset_defaults
18
+ OPTIONS.clear
19
+ OPTIONS.merge!(DEFAULTS)
20
+ end
21
+
22
+ private
23
+
24
+ DEFAULTS = {
25
+ :fabricator_dir => ['test', 'spec']
26
+ }
27
+ OPTIONS = {}.merge!(DEFAULTS)
28
+ end
29
+ end
@@ -13,7 +13,7 @@ class Fabrication::Generator::Base
13
13
 
14
14
  callbacks[:after_build].each { |callback| callback.call(instance) } if callbacks[:after_build]
15
15
  after_generation(options)
16
- callbacks[:after_create].each { |callback| callback.call(instance) } if callbacks[:after_create]
16
+ callbacks[:after_create].each { |callback| callback.call(instance) } if callbacks[:after_create] && options[:save]
17
17
 
18
18
  instance
19
19
  end
@@ -56,7 +56,7 @@ class Fabrication::Generator::Base
56
56
  assign(method_name, options, &block)
57
57
  end
58
58
  else
59
- assign(method_name, args.first)
59
+ assign(method_name, {}, args.first)
60
60
  end
61
61
  end
62
62
 
@@ -68,13 +68,13 @@ class Fabrication::Generator::Base
68
68
  instance.save! if options[:save] && instance.respond_to?(:save!)
69
69
  end
70
70
 
71
- def assign(method_name, param)
72
- if param.is_a?(Hash) && param.has_key?(:count)
73
- value = (1..param[:count]).map do |i|
74
- block_given? ? yield(instance, i) : param
71
+ def assign(method_name, options, raw_value=nil)
72
+ if options.has_key?(:count)
73
+ value = (1..options[:count]).map do |i|
74
+ block_given? ? yield(instance, i) : raw_value
75
75
  end
76
76
  else
77
- value = block_given? ? yield(instance) : param
77
+ value = block_given? ? yield(instance) : raw_value
78
78
  end
79
79
  instance.send("#{method_name}=", value)
80
80
  end
@@ -2,8 +2,6 @@ class Fabrication::Schematic
2
2
 
3
3
  GENERATORS = [
4
4
  Fabrication::Generator::ActiveRecord,
5
- Fabrication::Generator::Mongoid,
6
- Fabrication::Generator::Sequel,
7
5
  Fabrication::Generator::Base
8
6
  ]
9
7
 
@@ -105,6 +103,11 @@ class Fabrication::Schematic
105
103
  method_name
106
104
  end
107
105
 
106
+ def sequence(name, start=0, &block)
107
+ name = "#{self.klass.to_s.downcase.gsub(/::/, '_')}_#{name}"
108
+ Fabrication::Sequencer.sequence(name, start, &block)
109
+ end
110
+
108
111
  private
109
112
 
110
113
  def generate_value(name, params)
@@ -23,22 +23,14 @@ class Fabrication::Support
23
23
  end
24
24
 
25
25
  def find_definitions
26
- base_path = defined?(Rails) ? Rails.root : "."
27
- ['test', 'spec'].map do |folder|
28
- path = File.expand_path(File.join(base_path, folder, 'fabricators'))
29
-
30
- load("#{path}.rb") if File.exists?("#{path}.rb")
31
-
32
- File.directory? path and Dir[File.join(path, '*.rb')].each do |file|
26
+ path_prefix = defined?(Rails) ? Rails.root : "."
27
+ Fabrication::Config.fabricator_dir.each do |folder|
28
+ Dir.glob(File.join(path_prefix, folder, '**', '*fabricator.rb')).sort.each do |file|
33
29
  load file
34
30
  end
35
31
  end
36
32
  end
37
33
 
38
- def name_for(name)
39
- name.gsub(" ", "_").singularize.to_sym
40
- end
41
-
42
34
  end
43
35
 
44
36
  end
@@ -1,3 +1,3 @@
1
1
  module Fabrication
2
- VERSION = '0.9.5'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -1,31 +1,63 @@
1
1
  module FabricationMethods
2
+
2
3
  def create_from_table(model_name, table, extra = {})
4
+ model_name = dehumanize(model_name)
3
5
  fabricator_name = generate_fabricator_name(model_name)
4
6
  is_singular = model_name.to_s.singularize == model_name.to_s
5
7
  hashes = is_singular ? [table.rows_hash] : table.hashes
6
8
  @they = hashes.map do |hash|
7
- hash = hash.merge(extra).inject({}) {|h,(k,v)| h.update(k.gsub(/\W+/,'_').to_sym => v)}
9
+ hash = parameterize_hash(hash.merge(extra))
8
10
  Fabricate(fabricator_name, hash)
9
11
  end
10
- if is_singular
11
- @it = @they.last
12
- instance_variable_set("@#{fabricator_name}", @it)
13
- end
12
+ instantize(fabricator_name, is_singular)
14
13
  end
15
14
 
16
15
  def create_with_default_attributes(model_name, count, extra = {})
17
- fabricator_name = generate_fabricator_name(model_name)
16
+ fabricator_name = generate_fabricator_name(dehumanize(model_name))
18
17
  is_singular = count == 1
19
18
  @they = count.times.map { Fabricate(fabricator_name, extra) }
19
+ instantize(fabricator_name, is_singular)
20
+ end
21
+
22
+ def dehumanize(string)
23
+ string.gsub(/\W+/,'_').downcase
24
+ end
25
+
26
+ def generate_fabricator_name(model_name)
27
+ model_name.singularize.to_sym
28
+ end
29
+
30
+ def get_class(model_name)
31
+ fabricator_name = generate_fabricator_name(model_name)
32
+ Fabrication::Fabricator.schematics[fabricator_name].klass
33
+ end
34
+
35
+ def instantize(fabricator_name, is_singular)
20
36
  if is_singular
21
37
  @it = @they.last
22
38
  instance_variable_set("@#{fabricator_name}", @it)
39
+ else
40
+ instance_variable_set("@#{fabricator_name.to_s.pluralize}", @they)
23
41
  end
24
42
  end
25
43
 
26
- def generate_fabricator_name(model_name)
27
- model_name.gsub(/\W+/, '_').downcase.singularize.to_sym
44
+ def parameterize_hash(hash)
45
+ hash.inject({}) {|h,(k,v)| h.update(dehumanize(k).to_sym => v)}
46
+ end
47
+
48
+ def parentship(parent, child)
49
+ parent_instance = instance_variable_get("@#{dehumanize(parent)}")
50
+ parent_class_name = parent_instance.class.to_s.underscore
51
+ child_class = get_class(dehumanize(child))
52
+
53
+ if child_class && !child_class.new.respond_to?("#{parent_class_name}=")
54
+ parent_class_name = parent_class_name.pluralize
55
+ parent_instance = [parent_instance]
56
+ end
57
+
58
+ { parent_class_name => parent_instance }
28
59
  end
60
+
29
61
  end
30
62
 
31
63
  World(FabricationMethods)
@@ -39,15 +71,21 @@ Given /^the following ([^"]*):$/ do |model_name, table|
39
71
  end
40
72
 
41
73
  Given /^that ([^"]*) has the following ([^"]*):$/ do |parent, child, table|
42
- parent = parent.gsub(/\W+/,'_').downcase.sub(/^_/, '')
74
+ create_from_table(child, table, parentship(parent, child))
75
+ end
76
+
77
+ Given /^that ([^"]*) has (\d+) ([^"]*)$/ do |parent, count, child|
78
+ create_with_default_attributes(child, count.to_i, parentship(parent, child))
79
+ end
80
+
81
+ Given /^(?:that|those) (.*) belongs? to that (.*)$/ do |child_or_children, parent|
82
+ parent = dehumanize(parent)
43
83
  parent_instance = instance_variable_get("@#{parent}")
44
- child = child.gsub(/\W+/,'_').downcase
84
+ child_or_children = dehumanize(child_or_children)
45
85
 
46
- child_class = Fabrication::Support.class_for(child.singularize)
47
- if child_class && !child_class.new.respond_to?("#{parent}=")
48
- parent = parent.pluralize
49
- parent_instance = [parent_instance]
86
+ child_or_children_instance = instance_variable_get("@#{child_or_children}")
87
+ [child_or_children_instance].flatten.each do |child_instance|
88
+ child_instance.send("#{parent}=", parent_instance)
89
+ child_instance.save
50
90
  end
51
-
52
- create_from_table(child, table, parent => parent_instance)
53
91
  end
@@ -1,17 +1,19 @@
1
1
  require 'rails/generators/named_base'
2
2
 
3
- module Fabrication::Generators
4
- class ModelGenerator < Rails::Generators::NamedBase
5
- argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
6
- class_option :dir, :type => :string, :default => "spec/fabricators", :desc => "The directory where the fabricators should go"
7
- class_option :extension, :type => :string, :default => "rb", :desc => "file extension name"
3
+ module Fabrication
4
+ module Generators
5
+ class ModelGenerator < Rails::Generators::NamedBase
6
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
7
+ class_option :dir, :type => :string, :default => "spec/fabricators", :desc => "The directory where the fabricators should go"
8
+ class_option :extension, :type => :string, :default => "rb", :desc => "file extension name"
8
9
 
9
- def create_fabrication_file
10
- template 'fabricator.rb', File.join(options[:dir], "#{singular_table_name}_fabricator.#{options[:extension].to_s}")
11
- end
10
+ def create_fabrication_file
11
+ template 'fabricator.rb', File.join(options[:dir], "#{singular_table_name}_fabricator.#{options[:extension].to_s}")
12
+ end
12
13
 
13
- def self.source_root
14
- @_fabrication_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
14
+ def self.source_root
15
+ @_fabrication_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
16
+ end
15
17
  end
16
18
  end
17
19
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication::Config do
4
+ subject { Fabrication::Config }
5
+ after { Fabrication::Config.reset_defaults }
6
+
7
+ context "default configs" do
8
+ its(:fabricator_dir) { should == ['test', 'spec'] }
9
+ end
10
+
11
+ describe ".fabricator_dir" do
12
+ context "with a single folder" do
13
+ before do
14
+ Fabrication.configure do |config|
15
+ config.fabricator_dir = 'lib'
16
+ end
17
+ end
18
+
19
+ its(:fabricator_dir) { should == ['lib'] }
20
+ end
21
+
22
+ context "with multiple folders" do
23
+ before do
24
+ Fabrication.configure do |config|
25
+ config.fabricator_dir = %w(lib support)
26
+ end
27
+ end
28
+
29
+ its(:fabricator_dir) { should == ['lib', 'support'] }
30
+ end
31
+ end
32
+ end
@@ -69,6 +69,40 @@ describe Fabrication::Generator::Base do
69
69
  end
70
70
  end
71
71
 
72
+ context "using an after_create hook" do
73
+ let(:schematic) do
74
+ Fabrication::Schematic.new(Person) do
75
+ first_name "Guy"
76
+ after_create { |k| k.first_name.upcase! }
77
+ end
78
+ end
79
+
80
+ it "calls after_create when generated with saving" do
81
+ schematic.generate(:save => true).first_name.should == "GUY"
82
+ end
83
+
84
+ it "does not call after_create when generated without saving" do
85
+ schematic.generate(:save => false).first_name.should == "Guy"
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ describe "#after_generation" do
92
+ let(:instance) { mock(:instance) }
93
+ let(:generator) { Fabrication::Generator::Base.new(Object) }
94
+
95
+ before { generator.send(:instance=, instance) }
96
+
97
+ it "saves with a true save flag" do
98
+ instance.should_receive(:save!)
99
+ generator.send(:after_generation, {:save => true})
100
+ end
101
+
102
+ it "does not save without a true save flag" do
103
+ instance.should_not_receive(:save)
104
+ generator.send(:after_generation, {})
105
+ end
72
106
  end
73
107
 
74
108
  end
@@ -17,13 +17,13 @@ describe Fabrication::Schematic do
17
17
  end
18
18
  end
19
19
  context "for a mongoid object" do
20
- it "uses the mongoid generator" do
21
- Fabrication::Schematic.new(Author).generator.should == Fabrication::Generator::Mongoid
20
+ it "uses the base generator" do
21
+ Fabrication::Schematic.new(Author).generator.should == Fabrication::Generator::Base
22
22
  end
23
23
  end
24
24
  context "for a sequel object" do
25
- it "uses the sequel generator" do
26
- Fabrication::Schematic.new(Artist).generator.should == Fabrication::Generator::Sequel
25
+ it "uses the base generator" do
26
+ Fabrication::Schematic.new(Artist).generator.should == Fabrication::Generator::Base
27
27
  end
28
28
  end
29
29
  end
@@ -51,30 +51,4 @@ describe Fabrication::Support do
51
51
 
52
52
  end
53
53
 
54
- describe ".name_for" do
55
-
56
- context "whitespace delimited" do
57
- context "singular" do
58
- subject { Fabrication::Support.name_for("interesting location") }
59
- it { should == :interesting_location }
60
- end
61
- context "plural" do
62
- subject { Fabrication::Support.name_for("interesting locations") }
63
- it { should == :interesting_location }
64
- end
65
- end
66
-
67
- context "underscored" do
68
- context "singular" do
69
- subject { Fabrication::Support.name_for("interesting_location") }
70
- it { should == :interesting_location }
71
- end
72
- context "plural" do
73
- subject { Fabrication::Support.name_for("interesting_locations") }
74
- it { should == :interesting_location }
75
- end
76
- end
77
-
78
- end
79
-
80
54
  end
@@ -67,6 +67,11 @@ describe Fabrication do
67
67
  its(:state) { should == 'FL' }
68
68
  end
69
69
 
70
+ context 'with a class in a module' do
71
+ subject { Fabricate("Something::Amazing", :stuff => "things") }
72
+ its(:stuff) { should == "things" }
73
+ end
74
+
70
75
  context "when referring to other fabricators" do
71
76
 
72
77
  let(:person) { Fabricate(:person) }
@@ -175,20 +180,20 @@ describe Fabrication do
175
180
  after { TestMigration.down }
176
181
 
177
182
  before(:all) do
178
- Fabricator(:company) do
183
+ Fabricator(:main_company, :from => :company) do
179
184
  name { Faker::Company.name }
180
185
  divisions!(:count => 4)
181
186
  non_field { "hi" }
182
187
  after_create { |o| o.update_attribute(:city, "Jacksonville Beach") }
183
188
  end
184
189
 
185
- Fabricator(:other_company, :from => :company) do
190
+ Fabricator(:other_company, :from => :main_company) do
186
191
  divisions(:count => 2)
187
192
  after_build { |o| o.name = "Crazysauce" }
188
193
  end
189
194
  end
190
195
 
191
- let(:company) { Fabricate(:company, :name => "Hashrocket") }
196
+ let(:company) { Fabricate(:main_company, :name => "Hashrocket") }
192
197
  let(:other_company) { Fabricate(:other_company) }
193
198
 
194
199
  it 'generates field blocks immediately' do
@@ -388,4 +393,18 @@ describe Fabrication do
388
393
 
389
394
  end
390
395
 
396
+ describe "Fabricate with a sequence" do
397
+ subject { Fabricate(:sequencer) }
398
+
399
+ its(:simple_iterator) { should == 0 }
400
+ its(:param_iterator) { should == 10 }
401
+ its(:block_iterator) { should == "block2" }
402
+
403
+ context "when namespaced" do
404
+ subject { Fabricate("Sequencer::Namespaced") }
405
+
406
+ its(:iterator) { should == 0 }
407
+ end
408
+ end
409
+
391
410
  end
@@ -0,0 +1,9 @@
1
+ # ActiveRecord Objects
2
+ Fabricator(:division) do
3
+ name "Division Name"
4
+ end
5
+
6
+ Fabricator(:squadron, :from => :division)
7
+
8
+ Fabricator(:company)
9
+ Fabricator(:startup, :from => :company)
@@ -0,0 +1,19 @@
1
+ # Mongoid Documents
2
+ Fabricator(:author) do
3
+ name 'George Orwell'
4
+ books(:count => 4) do |author, i|
5
+ Fabricate.build(:book, :title => "book title #{i}", :author => author)
6
+ end
7
+ end
8
+
9
+ Fabricator(:hemingway, :from => :author) do
10
+ name 'Ernest Hemingway'
11
+ end
12
+
13
+ Fabricator(:book) do
14
+ title "book title"
15
+ end
16
+
17
+ Fabricator(:publishing_house)
18
+ Fabricator(:book_promoter)
19
+ Fabricator(:professional_affiliation)
@@ -34,23 +34,16 @@ Fabricator(:city) do
34
34
  on_init { init_with('Boulder', 'CO') }
35
35
  end
36
36
 
37
- # ActiveRecord Objects
38
- Fabricator(:division) do
39
- name "Division Name"
37
+ Fabricator("Something::Amazing") do
38
+ stuff "cool"
40
39
  end
41
40
 
42
- # Mongoid Documents
43
- Fabricator(:author) do
44
- name 'George Orwell'
45
- books(:count => 4) do |author, i|
46
- Fabricate.build(:book, :title => "book title #{i}", :author => author)
47
- end
41
+ Fabricator(:sequencer) do
42
+ simple_iterator { sequence(:simple_iterator) }
43
+ param_iterator { sequence(:param_iterator, 9) }
44
+ block_iterator { sequence(:block_iterator) { |i| "block#{i}" } }
48
45
  end
49
46
 
50
- Fabricator(:hemingway, :from => :author) do
51
- name 'Ernest Hemingway'
52
- end
53
-
54
- Fabricator(:book) do
55
- title "book title"
47
+ Fabricator("Sequencer::Namespaced") do
48
+ iterator { sequence(:iterator) }
56
49
  end
@@ -1,4 +1,3 @@
1
- require 'rubygems'
2
1
  require 'rspec'
3
2
  require 'fabrication'
4
3
  require 'ffaker'
@@ -7,7 +6,7 @@ require 'ffaker'
7
6
  # in ./support/ and its subdirectories.
8
7
  Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
9
8
 
10
- Rspec.configure do |config|
9
+ RSpec.configure do |config|
11
10
  config.before(:all) do
12
11
  clear_mongodb
13
12
  end
@@ -26,3 +26,17 @@ end
26
26
  class Contact
27
27
  attr_accessor :name, :address
28
28
  end
29
+
30
+ module Something
31
+ class Amazing
32
+ attr_accessor :stuff
33
+ end
34
+ end
35
+
36
+ class Sequencer
37
+ attr_accessor :simple_iterator, :param_iterator, :block_iterator
38
+
39
+ class Namespaced
40
+ attr_accessor :iterator
41
+ end
42
+ end
@@ -25,3 +25,26 @@ class Book
25
25
 
26
26
  embedded_in :author, :inverse_of => :books
27
27
  end
28
+
29
+ class PublishingHouse
30
+ include Mongoid::Document
31
+
32
+ referenced_in :professional_affiliation
33
+ embeds_many :book_promoters
34
+
35
+ field :name
36
+ end
37
+
38
+ class BookPromoter
39
+ include Mongoid::Document
40
+
41
+ embedded_in :publishing_house
42
+
43
+ field :name
44
+ end
45
+
46
+ class ProfessionalAffiliation
47
+ include Mongoid::Document
48
+
49
+ references_many :publishing_houses
50
+ end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabrication
3
3
  version: !ruby/object:Gem::Version
4
- hash: 49
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 9
9
- - 5
10
- version: 0.9.5
4
+ prerelease:
5
+ version: 1.0.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Paul Elliott
@@ -15,8 +10,7 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-01-17 00:00:00 -05:00
19
- default_executable:
13
+ date: 2011-06-15 00:00:00 Z
20
14
  dependencies:
21
15
  - !ruby/object:Gem::Dependency
22
16
  name: rspec
@@ -24,14 +18,9 @@ dependencies:
24
18
  requirement: &id001 !ruby/object:Gem::Requirement
25
19
  none: false
26
20
  requirements:
27
- - - ">="
21
+ - - ~>
28
22
  - !ruby/object:Gem::Version
29
- hash: 7
30
- segments:
31
- - 2
32
- - 2
33
- - 0
34
- version: 2.2.0
23
+ version: 2.6.0
35
24
  type: :development
36
25
  version_requirements: *id001
37
26
  - !ruby/object:Gem::Dependency
@@ -40,14 +29,9 @@ dependencies:
40
29
  requirement: &id002 !ruby/object:Gem::Requirement
41
30
  none: false
42
31
  requirements:
43
- - - ">="
32
+ - - ~>
44
33
  - !ruby/object:Gem::Version
45
- hash: 55
46
- segments:
47
- - 0
48
- - 10
49
- - 0
50
- version: 0.10.0
34
+ version: 0.10.6
51
35
  type: :development
52
36
  version_requirements: *id002
53
37
  - !ruby/object:Gem::Dependency
@@ -56,14 +40,9 @@ dependencies:
56
40
  requirement: &id003 !ruby/object:Gem::Requirement
57
41
  none: false
58
42
  requirements:
59
- - - ">="
43
+ - - ~>
60
44
  - !ruby/object:Gem::Version
61
- hash: 15
62
- segments:
63
- - 0
64
- - 4
65
- - 0
66
- version: 0.4.0
45
+ version: 1.8.0
67
46
  type: :development
68
47
  version_requirements: *id003
69
48
  - !ruby/object:Gem::Dependency
@@ -72,14 +51,9 @@ dependencies:
72
51
  requirement: &id004 !ruby/object:Gem::Requirement
73
52
  none: false
74
53
  requirements:
75
- - - ">="
54
+ - - ~>
76
55
  - !ruby/object:Gem::Version
77
- hash: 1
78
- segments:
79
- - 3
80
- - 0
81
- - 3
82
- version: 3.0.3
56
+ version: 3.0.8
83
57
  type: :development
84
58
  version_requirements: *id004
85
59
  - !ruby/object:Gem::Dependency
@@ -88,14 +62,9 @@ dependencies:
88
62
  requirement: &id005 !ruby/object:Gem::Requirement
89
63
  none: false
90
64
  requirements:
91
- - - "="
65
+ - - ~>
92
66
  - !ruby/object:Gem::Version
93
- hash: 25
94
- segments:
95
- - 1
96
- - 3
97
- - 1
98
- version: 1.3.1
67
+ version: 1.3.3
99
68
  type: :development
100
69
  version_requirements: *id005
101
70
  - !ruby/object:Gem::Dependency
@@ -104,14 +73,9 @@ dependencies:
104
73
  requirement: &id006 !ruby/object:Gem::Requirement
105
74
  none: false
106
75
  requirements:
107
- - - ">="
76
+ - - ~>
108
77
  - !ruby/object:Gem::Version
109
- hash: 25
110
- segments:
111
- - 1
112
- - 1
113
- - 5
114
- version: 1.1.5
78
+ version: 1.3.1
115
79
  type: :development
116
80
  version_requirements: *id006
117
81
  - !ruby/object:Gem::Dependency
@@ -120,16 +84,9 @@ dependencies:
120
84
  requirement: &id007 !ruby/object:Gem::Requirement
121
85
  none: false
122
86
  requirements:
123
- - - "="
87
+ - - ~>
124
88
  - !ruby/object:Gem::Version
125
- hash: 15424093
126
- segments:
127
- - 2
128
- - 0
129
- - 0
130
- - rc
131
- - 4
132
- version: 2.0.0.rc.4
89
+ version: 2.0.2
133
90
  type: :development
134
91
  version_requirements: *id007
135
92
  - !ruby/object:Gem::Dependency
@@ -138,16 +95,22 @@ dependencies:
138
95
  requirement: &id008 !ruby/object:Gem::Requirement
139
96
  none: false
140
97
  requirements:
141
- - - "="
98
+ - - ~>
142
99
  - !ruby/object:Gem::Version
143
- hash: 71
144
- segments:
145
- - 3
146
- - 16
147
- - 0
148
- version: 3.16.0
100
+ version: 3.24.1
149
101
  type: :development
150
102
  version_requirements: *id008
103
+ - !ruby/object:Gem::Dependency
104
+ name: rake
105
+ prerelease: false
106
+ requirement: &id009 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ version: 0.9.2
112
+ type: :development
113
+ version_requirements: *id009
151
114
  description: Fabrication is an object generation framework for ActiveRecord, Mongoid, and Sequel. It has a sensible syntax and lazily generates ActiveRecord associations!
152
115
  email:
153
116
  - paul@hashrocket.com
@@ -159,14 +122,13 @@ extra_rdoc_files: []
159
122
 
160
123
  files:
161
124
  - lib/fabrication/attribute.rb
125
+ - lib/fabrication/config.rb
162
126
  - lib/fabrication/errors/duplicate_fabricator_error.rb
163
127
  - lib/fabrication/errors/unfabricatable_error.rb
164
128
  - lib/fabrication/errors/unknown_fabricator_error.rb
165
129
  - lib/fabrication/fabricator.rb
166
130
  - lib/fabrication/generator/active_record.rb
167
131
  - lib/fabrication/generator/base.rb
168
- - lib/fabrication/generator/mongoid.rb
169
- - lib/fabrication/generator/sequel.rb
170
132
  - lib/fabrication/schematic.rb
171
133
  - lib/fabrication/sequencer.rb
172
134
  - lib/fabrication/support.rb
@@ -177,25 +139,24 @@ files:
177
139
  - lib/rails/generators/fabrication/model/model_generator.rb
178
140
  - lib/rails/generators/fabrication/model/templates/fabricator.rb
179
141
  - spec/fabrication/attribute_spec.rb
142
+ - spec/fabrication/config_spec.rb
180
143
  - spec/fabrication/fabricator_spec.rb
181
144
  - spec/fabrication/generator/active_record_spec.rb
182
145
  - spec/fabrication/generator/base_spec.rb
183
- - spec/fabrication/generator/mongoid_spec.rb
184
- - spec/fabrication/generator/sequel_spec.rb
185
146
  - spec/fabrication/schematic_spec.rb
186
147
  - spec/fabrication/sequence_spec.rb
187
148
  - spec/fabrication/support_spec.rb
188
149
  - spec/fabrication_spec.rb
189
- - spec/fabricator_spec.rb
150
+ - spec/fabricators/active_record_fabricator.rb
190
151
  - spec/fabricators/cool_object_fabricator.rb
191
- - spec/fabricators.rb
152
+ - spec/fabricators/mongoid_fabricator.rb
153
+ - spec/fabricators/plain_old_ruby_object_fabricator.rb
192
154
  - spec/spec_helper.rb
193
155
  - spec/support/active_record.rb
194
156
  - spec/support/helper_objects.rb
195
157
  - spec/support/mongoid.rb
196
158
  - spec/support/sequel.rb
197
159
  - README.markdown
198
- has_rdoc: true
199
160
  homepage: http://github.com/paulelliott/fabrication
200
161
  licenses: []
201
162
 
@@ -209,23 +170,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
209
170
  requirements:
210
171
  - - ">="
211
172
  - !ruby/object:Gem::Version
212
- hash: 3
213
- segments:
214
- - 0
215
173
  version: "0"
216
174
  required_rubygems_version: !ruby/object:Gem::Requirement
217
175
  none: false
218
176
  requirements:
219
177
  - - ">="
220
178
  - !ruby/object:Gem::Version
221
- hash: 3
222
- segments:
223
- - 0
224
179
  version: "0"
225
180
  requirements: []
226
181
 
227
182
  rubyforge_project:
228
- rubygems_version: 1.3.7
183
+ rubygems_version: 1.7.2
229
184
  signing_key:
230
185
  specification_version: 3
231
186
  summary: Fabrication provides a robust solution for test object generation.
@@ -1,7 +0,0 @@
1
- class Fabrication::Generator::Mongoid < Fabrication::Generator::Base
2
-
3
- def self.supports?(klass)
4
- defined?(Mongoid) && klass.ancestors.include?(Mongoid::Document)
5
- end
6
-
7
- end
@@ -1,7 +0,0 @@
1
- class Fabrication::Generator::Sequel < Fabrication::Generator::Base
2
-
3
- def self.supports?(klass)
4
- defined?(Sequel) && klass.ancestors.include?(Sequel::Model)
5
- end
6
-
7
- end
@@ -1,32 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Fabrication::Generator::Mongoid do
4
-
5
- describe ".supports?" do
6
- subject { Fabrication::Generator::Mongoid }
7
- it "returns true for mongoid objects" do
8
- subject.supports?(Author).should be_true
9
- end
10
- it "returns false for non-mongoid objects" do
11
- subject.supports?(Person).should be_false
12
- end
13
- end
14
-
15
- describe "#after_generation" do
16
- let(:instance) { mock(:instance) }
17
- let(:generator) { Fabrication::Generator::Mongoid.new(Object) }
18
-
19
- before { generator.send(:instance=, instance) }
20
-
21
- it "saves with a true save flag" do
22
- instance.should_receive(:save!)
23
- generator.send(:after_generation, {:save => true})
24
- end
25
-
26
- it "does not save without a true save flag" do
27
- instance.should_not_receive(:save)
28
- generator.send(:after_generation, {})
29
- end
30
- end
31
-
32
- end
@@ -1,32 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Fabrication::Generator::Sequel do
4
-
5
- describe ".supports?" do
6
- subject { Fabrication::Generator::Sequel }
7
- it "returns true for sequel objects" do
8
- subject.supports?(Artist).should be_true
9
- end
10
- it "returns false for non-sequel objects" do
11
- subject.supports?(Person).should be_false
12
- end
13
- end
14
-
15
- describe "#after_generation" do
16
- let(:instance) { mock(:instance) }
17
- let(:generator) { Fabrication::Generator::Sequel.new(Object) }
18
-
19
- before { generator.send(:instance=, instance) }
20
-
21
- it "saves with a true save flag" do
22
- instance.should_receive(:save!)
23
- generator.send(:after_generation, {:save => true})
24
- end
25
-
26
- it "does not save without a true save flag" do
27
- instance.should_not_receive(:save)
28
- generator.send(:after_generation, {})
29
- end
30
- end
31
-
32
- end
@@ -1,14 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Fabricator do
4
-
5
- describe ".name_for" do
6
-
7
- it "delegates to Fabrication::Support" do
8
- Fabrication::Support.should_receive(:name_for).with("interesting location")
9
- Fabricator.name_for("interesting location")
10
- end
11
-
12
- end
13
-
14
- end