fabrication 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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