fabrication 1.1.0 → 1.2.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.
@@ -0,0 +1,104 @@
1
+ module Fabrication
2
+ module Cucumber
3
+ class StepFabricator
4
+ attr_reader :model
5
+
6
+ def initialize(model_name, opts ={})
7
+ @model = dehumanize(model_name)
8
+ @fabricator = @model.singularize.to_sym
9
+ @parent_name = opts.delete(:parent)
10
+ end
11
+
12
+ def from_table(table, extra={})
13
+ hashes = singular? ? [table.rows_hash] : table.hashes
14
+ hashes.map do |hash|
15
+ make(parameterize_hash(hash).merge(extra))
16
+ end.tap {|o| remember(o) }
17
+ end
18
+
19
+ def n(count, attrs={})
20
+ count.times.map { make(attrs) }.tap {|o| remember(o) }
21
+ end
22
+
23
+ def has_many(children)
24
+ instance = Fabrications[@fabricator]
25
+ children = dehumanize(children)
26
+ [Fabrications[children]].flatten.each do |child|
27
+ child.send("#{klass.to_s.underscore.downcase}=", instance)
28
+ child.respond_to?(:save!) && child.save!
29
+ end
30
+ end
31
+
32
+ def parent
33
+ return unless @parent_name
34
+ Fabrications[dehumanize(@parent_name)]
35
+ end
36
+
37
+ def klass
38
+ schematic.klass
39
+ end
40
+
41
+ private
42
+
43
+ def remember(objects)
44
+ if singular?
45
+ Fabrications[@fabricator] = objects.last
46
+ else
47
+ Fabrications[@model.to_sym] = objects
48
+ end
49
+ end
50
+
51
+ def singular?
52
+ @model == @model.singularize
53
+ end
54
+
55
+ def schematic
56
+ Fabrication::Fabricator.schematics[@fabricator]
57
+ end
58
+
59
+ def dehumanize(string)
60
+ string.gsub(/\W+/,'_').downcase
61
+ end
62
+
63
+ def parameterize_hash(hash)
64
+ hash.inject({}) {|h,(k,v)| h.update(dehumanize(k).to_sym => v)}
65
+ end
66
+
67
+ def make(attrs={})
68
+ Fabricate(@fabricator, attrs.merge(parentship))
69
+ end
70
+
71
+ def parentship
72
+ return {} unless parent
73
+ parent_class_name = parent.class.to_s.underscore
74
+
75
+ parent_instance = parent
76
+ unless klass.new.respond_to?("#{parent_class_name}=")
77
+ parent_class_name = parent_class_name.pluralize
78
+ parent_instance = [parent]
79
+ end
80
+
81
+ { parent_class_name => parent_instance }
82
+ end
83
+
84
+ end
85
+
86
+ module Fabrications
87
+ @@fabrications = {}
88
+
89
+ def self.[](fabricator)
90
+ @@fabrications[fabricator.to_sym]
91
+ end
92
+
93
+ def self.[]=(fabricator, fabrication)
94
+ @@fabrications[fabricator.to_sym] = fabrication
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ module FabricationMethods
101
+ def fabrications
102
+ Fabrication::Cucumber::Fabrications
103
+ end
104
+ end
@@ -2,10 +2,13 @@ class Fabrication::Sequencer
2
2
 
3
3
  DEFAULT = :_default
4
4
 
5
- def self.sequence(name=DEFAULT, start=0)
5
+ def self.sequence(name=DEFAULT, start=0, &block)
6
6
  idx = sequences[name] ||= start
7
-
8
- (block_given? ? yield(idx) : idx).tap do
7
+ if block_given?
8
+ sequence_blocks[name] = block.to_proc
9
+ else
10
+ sequence_blocks[name] ||= lambda { |i| i }
11
+ end.call(idx).tap do
9
12
  sequences[name] += 1
10
13
  end
11
14
  end
@@ -14,4 +17,7 @@ class Fabrication::Sequencer
14
17
  @sequences ||= {}
15
18
  end
16
19
 
20
+ def self.sequence_blocks
21
+ @sequence_blocks ||= {}
22
+ end
17
23
  end
@@ -1,3 +1,3 @@
1
1
  module Fabrication
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -1,103 +1,47 @@
1
- module FabricationMethods
1
+ require 'fabrication/cucumber'
2
2
 
3
- def create_from_table(model_name, table, extra = {})
4
- model_name = dehumanize(model_name)
5
- fabricator_name = generate_fabricator_name(model_name)
6
- is_singular = model_name.to_s.singularize == model_name.to_s
7
- hashes = is_singular ? [table.rows_hash] : table.hashes
8
- @they = hashes.map do |hash|
9
- hash = parameterize_hash(hash.merge(extra))
10
- Fabricate(fabricator_name, hash)
11
- end
12
- instantize(fabricator_name, is_singular)
13
- end
14
-
15
- def create_with_default_attributes(model_name, count, extra = {})
16
- fabricator_name = generate_fabricator_name(dehumanize(model_name))
17
- is_singular = count == 1
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)
36
- if is_singular
37
- @it = @they.last
38
- instance_variable_set("@#{fabricator_name}", @it)
39
- else
40
- instance_variable_set("@#{fabricator_name.to_s.pluralize}", @they)
41
- end
42
- end
43
-
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 }
59
- end
60
-
61
- def class_from_model_name(model_name)
62
- eval(dehumanize(model_name).singularize.classify)
63
- end
3
+ World(FabricationMethods)
64
4
 
5
+ def with_ivars(fabricator)
6
+ @they = yield fabricator
7
+ instance_variable_set("@#{fabricator.model}", @they)
65
8
  end
66
9
 
67
- World(FabricationMethods)
68
-
69
10
  Given /^(\d+) ([^"]*)$/ do |count, model_name|
70
- create_with_default_attributes(model_name, count.to_i)
11
+ with_ivars Fabrication::Cucumber::StepFabricator.new(model_name) do |fab|
12
+ fab.n(count.to_i)
13
+ end
71
14
  end
72
15
 
73
16
  Given /^the following ([^"]*):$/ do |model_name, table|
74
- create_from_table(model_name, table)
17
+ with_ivars Fabrication::Cucumber::StepFabricator.new(model_name) do |fab|
18
+ fab.from_table(table)
19
+ end
75
20
  end
76
21
 
77
22
  Given /^that ([^"]*) has the following ([^"]*):$/ do |parent, child, table|
78
- create_from_table(child, table, parentship(parent, child))
23
+ with_ivars Fabrication::Cucumber::StepFabricator.new(child, :parent => parent) do |fab|
24
+ fab.from_table(table)
25
+ end
79
26
  end
80
27
 
81
28
  Given /^that ([^"]*) has (\d+) ([^"]*)$/ do |parent, count, child|
82
- create_with_default_attributes(child, count.to_i, parentship(parent, child))
29
+ with_ivars Fabrication::Cucumber::StepFabricator.new(child, :parent => parent) do |fab|
30
+ fab.n(count.to_i)
31
+ end
83
32
  end
84
33
 
85
- Given /^(?:that|those) (.*) belongs? to that (.*)$/ do |child_or_children, parent|
86
- parent = dehumanize(parent)
87
- parent_instance = instance_variable_get("@#{parent}")
88
- child_or_children = dehumanize(child_or_children)
89
-
90
- child_or_children_instance = instance_variable_get("@#{child_or_children}")
91
- [child_or_children_instance].flatten.each do |child_instance|
92
- child_instance.send("#{parent}=", parent_instance)
93
- child_instance.save
34
+ Given /^(?:that|those) (.*) belongs? to that (.*)$/ do |children, parent|
35
+ with_ivars Fabrication::Cucumber::StepFabricator.new(parent) do |fab|
36
+ fab.has_many(children)
94
37
  end
95
38
  end
96
39
 
97
40
  Then /^I should see (\d+) ([^"]*) in the database$/ do |count, model_name|
98
- get_class(dehumanize(model_name)).count.should == count.to_i
41
+ Fabrication::Cucumber::StepFabricator.new(model_name).klass.count.should == count.to_i
99
42
  end
100
43
 
101
44
  Then /^I should see the following (.*) in the database:$/ do |model_name, table|
102
- get_class(dehumanize(model_name)).where(table.rows_hash).count.should == 1
45
+ klass = Fabrication::Cucumber::StepFabricator.new(model_name).klass
46
+ klass.where(table.rows_hash).count.should == 1
103
47
  end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+ require 'fabrication/cucumber'
3
+
4
+ describe Fabrication::Cucumber do
5
+ include described_class
6
+
7
+ let(:name) { 'dogs' }
8
+
9
+ describe '#klass' do
10
+ context 'with a schematic for class "Boom"' do
11
+ subject { StepFabricator.new(name).klass }
12
+ let(:fabricator_name) { :dog }
13
+
14
+ before do
15
+ Fabrication::Fabricator.schematics.stub(:[])
16
+ .with(fabricator_name).and_return(stub(:klass => "Boom"))
17
+ end
18
+
19
+ it { should == "Boom" }
20
+
21
+ context "given a human name" do
22
+ let(:name) { "weiner dogs" }
23
+ let(:fabricator_name) { :weiner_dog }
24
+ it { should == "Boom" }
25
+ end
26
+
27
+ context "given a titlecase human name" do
28
+ let(:name) { "Weiner Dog" }
29
+ let(:fabricator_name) { :weiner_dog }
30
+ it { should == "Boom" }
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#n" do
36
+ let(:n) { 3 }
37
+ let(:fabricator) { StepFabricator.new(name) }
38
+
39
+ it "fabricates n times" do
40
+ Fabrication::Fabricator.should_receive(:generate).with(:dog, anything, {}).exactly(n).times
41
+ fabricator.n n
42
+ end
43
+
44
+ it "fabricates with attrs" do
45
+ Fabrication::Fabricator.should_receive(:generate)
46
+ .with(anything, anything, :collar => 'red').at_least(1)
47
+ fabricator.n n, :collar => 'red'
48
+ end
49
+
50
+ context 'with a plural subject' do
51
+ let(:name) { 'dogs' }
52
+ it 'remembers' do
53
+ Fabrication::Fabricator.stub(:generate).and_return("dog1", "dog2", "dog3")
54
+ fabricator.n n
55
+ Fabrications[name].should == ["dog1", "dog2", "dog3"]
56
+ end
57
+ end
58
+
59
+ context 'with a singular subject' do
60
+ let(:name) { 'dog' }
61
+ it 'remembers' do
62
+ Fabrication::Fabricator.stub(:generate).and_return("dog1")
63
+ fabricator.n 1
64
+ Fabrications[name].should == 'dog1'
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ describe '#from_table' do
71
+ it 'maps column names to attribute names' do
72
+ table = stub(:hashes => [{ 'Favorite Color' => 'pink' }])
73
+ Fabrication::Fabricator.should_receive(:generate)
74
+ .with(anything, anything, :favorite_color => 'pink')
75
+ StepFabricator.new('bears').from_table(table)
76
+ end
77
+
78
+ context 'with a plural subject' do
79
+ let(:table) { double("ASTable", :hashes => hashes) }
80
+ let(:hashes) do
81
+ [{'some' => 'thing'},
82
+ {'some' => 'panother'}]
83
+ end
84
+ it 'fabricates with each rows attributes' do
85
+ Fabrication::Fabricator.should_receive(:generate)
86
+ .with(:dog, anything, {:some => 'thing'})
87
+ Fabrication::Fabricator.should_receive(:generate)
88
+ .with(:dog, anything, {:some => 'panother'})
89
+ StepFabricator.new(name).from_table(table)
90
+ end
91
+ it 'remembers' do
92
+ Fabrication::Fabricator.stub(:generate).and_return('dog1', 'dog2')
93
+ StepFabricator.new(name).from_table(table)
94
+ Fabrications[name].should == ["dog1", "dog2"]
95
+ end
96
+ end
97
+
98
+ context 'singular' do
99
+ let(:name) { 'dog' }
100
+ let(:table) { double("ASTable", :rows_hash => rows_hash) }
101
+ let(:rows_hash) do
102
+ {'some' => 'thing'}
103
+ end
104
+ it 'fabricates with each row as an attribute' do
105
+ Fabrication::Fabricator.should_receive(:generate).with(:dog, anything, {:some => 'thing'})
106
+ StepFabricator.new(name).from_table(table)
107
+ end
108
+ it 'remembers' do
109
+ Fabrication::Fabricator.stub(:generate).and_return('dog1')
110
+ StepFabricator.new(name).from_table(table)
111
+ Fabrications[name].should == "dog1"
112
+ end
113
+ end
114
+ end
115
+
116
+ end
@@ -66,6 +66,33 @@ describe Fabrication::Sequencer do
66
66
  end.should == "user2@example.com"
67
67
  end
68
68
 
69
+ context 'and then without a block' do
70
+ it 'remembers the original block' do
71
+ Fabricate.sequence :ordinal, &:ordinalize
72
+ Fabricate.sequence(:ordinal).should == "1st"
73
+ end
74
+ context 'and then with a new block' do
75
+ it 'evaluates the new block' do
76
+ Fabricate.sequence(:ordinal) do |i|
77
+ i ** 2
78
+ end.should == 4
79
+ end
80
+ it 'remembers the new block' do
81
+ Fabricate.sequence(:ordinal).should == 9
82
+ end
83
+ end
84
+ end
85
+ end
86
+ context 'with two sequences declared with blocks' do
87
+ it 'remembers both blocks' do
88
+ Fabricate.sequence(:shapes) do |i|
89
+ %w[square circle rectangle][i % 3]
90
+ end
91
+ Fabricate.sequence(:colors) do |i|
92
+ %w[red green blue][i % 3]
93
+ end
94
+ Fabricate.sequence(:shapes).should == 'circle'
95
+ Fabricate.sequence(:colors).should == 'green'
96
+ end
69
97
  end
70
-
71
98
  end
data/spec/spec_helper.rb CHANGED
@@ -7,6 +7,6 @@ require 'ffaker'
7
7
  Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
8
8
 
9
9
  RSpec.configure do |config|
10
- config.before(:suite) { TestMigration.up }
10
+ config.before(:all) { TestMigration.up }
11
11
  config.before(:all) { clear_mongodb }
12
12
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: fabrication
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.1.0
5
+ version: 1.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Elliott
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-08-26 00:00:00 Z
13
+ date: 2011-09-26 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -145,6 +145,7 @@ extra_rdoc_files: []
145
145
  files:
146
146
  - lib/fabrication/attribute.rb
147
147
  - lib/fabrication/config.rb
148
+ - lib/fabrication/cucumber.rb
148
149
  - lib/fabrication/errors/duplicate_fabricator_error.rb
149
150
  - lib/fabrication/errors/unfabricatable_error.rb
150
151
  - lib/fabrication/errors/unknown_fabricator_error.rb
@@ -164,6 +165,7 @@ files:
164
165
  - lib/rails/generators/fabrication/model/templates/fabricator.rb
165
166
  - spec/fabrication/attribute_spec.rb
166
167
  - spec/fabrication/config_spec.rb
168
+ - spec/fabrication/cucumber_spec.rb
167
169
  - spec/fabrication/fabricator_spec.rb
168
170
  - spec/fabrication/generator/active_record_spec.rb
169
171
  - spec/fabrication/generator/base_spec.rb