fabrication 0.2.3 → 0.2.4

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.
@@ -53,3 +53,16 @@ So you already have a company fabricator, but you need one that specifically gen
53
53
  end
54
54
 
55
55
  Setting the :from option will inherit the class and all the attributes from the named Fabricator. Even if you haven't defined a :company Fabricator yet, it will still work as long as it references an actual class name.
56
+
57
+
58
+
59
+
60
+ Fabricator(:atlanta_hub, :from => :hub) do
61
+ city "Atlanta"
62
+ state "GA"
63
+ location [33.755, -84.39]
64
+ hardwares(:hardware, :as => :headend, :count => 4) {
65
+ name 'something'
66
+ }
67
+ end
68
+
@@ -1,7 +1,9 @@
1
1
  module Fabrication
2
2
 
3
3
  require 'fabrication/errors'
4
+
4
5
  autoload :Fabricator, 'fabrication/fabricator'
6
+ autoload :Schematic, 'fabrication/schematic'
5
7
 
6
8
  module Generator
7
9
  autoload :ActiveRecord, 'fabrication/generator/active_record'
@@ -6,14 +6,15 @@ class Fabrication::Fabricator
6
6
  Fabrication::Generator::Base
7
7
  ]
8
8
 
9
- attr_accessor :class_name
9
+ attr_accessor :class_name, :schematic
10
10
 
11
11
  def initialize(class_name, parent=nil, &block)
12
12
  self.class_name = class_name
13
13
  klass = class_for(class_name)
14
+ self.schematic = parent ? parent.schematic.clone.merge!(&block) : Fabrication::Schematic.new(&block)
14
15
  self.generator = GENERATORS.detect do |gen|
15
16
  gen.supports?(klass)
16
- end.new(klass, parent, &block)
17
+ end.new(klass, schematic)
17
18
  end
18
19
 
19
20
  def fabricate(options={})
@@ -6,38 +6,36 @@ class Fabrication::Generator::ActiveRecord < Fabrication::Generator::Base
6
6
 
7
7
  def method_missing(method_name, *args, &block)
8
8
  method_name = method_name.to_s
9
- unless options.include?(method_name.to_sym)
10
- if block_given?
11
- count = (args && args.first && args.first[:count]) || 0
12
- unless (args.first && args.first[:force]) || instance.class.columns.map(&:name).include?(method_name)
13
- # copy the original getter
14
- instance.instance_variable_set("@__#{method_name}_original", instance.method(method_name).clone)
9
+ if block_given?
10
+ count = (args && args.first && args.first[:count]) || 0
11
+ unless (args.first && args.first[:force]) || instance.class.columns.map(&:name).include?(method_name)
12
+ # copy the original getter
13
+ instance.instance_variable_set("@__#{method_name}_original", instance.method(method_name).clone)
15
14
 
16
- # store the block for lazy generation
17
- instance.instance_variable_set("@__#{method_name}_block", block)
15
+ # store the block for lazy generation
16
+ instance.instance_variable_set("@__#{method_name}_block", block)
18
17
 
19
- # redefine the getter
20
- instance.instance_eval %<
21
- def #{method_name}
22
- original_value = @__#{method_name}_original.call
23
- if @__#{method_name}_block.present?
24
- if #{count} \>= 1
25
- original_value = #{method_name}= (1..#{count}).map { |i| @__#{method_name}_block.call(self, i) }
26
- else
27
- original_value = #{method_name}= @__#{method_name}_block.call(self)
28
- end
29
- @__#{method_name}_block = nil
30
- @__#{method_name}_original.call
18
+ # redefine the getter
19
+ instance.instance_eval %<
20
+ def #{method_name}
21
+ original_value = @__#{method_name}_original.call
22
+ if @__#{method_name}_block.present?
23
+ if #{count} \>= 1
24
+ original_value = #{method_name}= (1..#{count}).map { |i| @__#{method_name}_block.call(self, i) }
25
+ else
26
+ original_value = #{method_name}= @__#{method_name}_block.call(self)
31
27
  end
32
- original_value
28
+ @__#{method_name}_block = nil
29
+ @__#{method_name}_original.call
33
30
  end
34
- >
35
- else
36
- assign(instance, method_name, args.first, &block)
37
- end
31
+ original_value
32
+ end
33
+ >
38
34
  else
39
- assign(instance, method_name, args.first)
35
+ assign(method_name, args.first, &block)
40
36
  end
37
+ else
38
+ assign(method_name, args.first)
41
39
  end
42
40
  end
43
41
 
@@ -7,23 +7,20 @@ class Fabrication::Generator::Base
7
7
  end
8
8
 
9
9
  def generate(options={})
10
- self.instance = parent ? parent.fabricate : klass.new
11
- self.options = options
12
- instance_eval(&block)
13
- options.each { |k,v| assign(instance, k, v) }
10
+ self.instance = klass.new
11
+ process_attributes(options)
14
12
  after_generation
15
13
  after_create_block.call(instance) if after_create_block
16
14
  instance
17
15
  end
18
16
 
19
- def initialize(klass, parent=nil, &block)
17
+ def initialize(klass, schematic=nil)
20
18
  self.klass = klass
21
- self.parent = parent
22
- self.block = block
19
+ self.schematic = schematic
23
20
  end
24
21
 
25
22
  def method_missing(method_name, *args, &block)
26
- assign(instance, method_name.to_s, args.first, &block)
23
+ assign(method_name.to_s, args.first, &block)
27
24
  end
28
25
 
29
26
  protected
@@ -32,9 +29,9 @@ class Fabrication::Generator::Base
32
29
 
33
30
  private
34
31
 
35
- attr_accessor :after_create_block, :block, :instance, :klass, :options, :parent
32
+ attr_accessor :after_create_block, :instance, :klass, :schematic
36
33
 
37
- def assign(instance, method_name, param)
34
+ def assign(method_name, param)
38
35
  value = nil
39
36
  if param.is_a?(Hash) && param[:count] && param[:count] > 1
40
37
  value = (1..param[:count]).map do |i|
@@ -46,4 +43,18 @@ class Fabrication::Generator::Base
46
43
  instance.send("#{method_name.to_s}=", value)
47
44
  end
48
45
 
46
+ def process_attributes(options)
47
+ schematic.merge(options).attributes.each do |attribute|
48
+ if attribute.name == :after_create
49
+ after_create(&attribute.value)
50
+ else
51
+ if Proc === attribute.value
52
+ method_missing(attribute.name, attribute.params, &attribute.value)
53
+ else
54
+ method_missing(attribute.name, attribute.value)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
49
60
  end
@@ -0,0 +1,70 @@
1
+ class Fabrication::Schematic
2
+
3
+ def initialize(&block)
4
+ instance_eval(&block) if block_given?
5
+ end
6
+
7
+ def attribute(name)
8
+ attributes.select { |a| a.name == name }.first
9
+ end
10
+
11
+ def clone
12
+ Fabrication::Schematic.new.tap do |dup|
13
+ dup.attributes = attributes.map do |a|
14
+ Attribute.new(a.name, a.params, a.value)
15
+ end
16
+ end
17
+ end
18
+
19
+ def merge(options)
20
+ schematic = clone
21
+ options.each do |name, value|
22
+ if attribute = schematic.attribute(name)
23
+ attribute.params = nil
24
+ attribute.value = value
25
+ else
26
+ schematic.attributes << Attribute.new(name, nil, value)
27
+ end
28
+ end
29
+ schematic
30
+ end
31
+
32
+ def merge!(&block)
33
+ instance_eval(&block)
34
+ self
35
+ end
36
+
37
+ def method_missing(method_name, *args, &block)
38
+ if (attr = attribute(method_name)).present?
39
+ if block_given?
40
+ attr.params = args.first
41
+ attr.value = block
42
+ else
43
+ attr.params = nil
44
+ attr.value = args.first
45
+ end
46
+ else
47
+ if block_given?
48
+ attributes.push(Attribute.new(method_name, args.first, block))
49
+ else
50
+ attributes.push(Attribute.new(method_name, nil, args.first))
51
+ end
52
+ end
53
+ end
54
+
55
+ class Attribute
56
+ attr_accessor :name, :params, :value
57
+
58
+ def initialize(name, params, value)
59
+ self.name = name
60
+ self.params = params
61
+ self.value = value
62
+ end
63
+ end
64
+
65
+ attr_writer :attributes
66
+ def attributes
67
+ @attributes ||= []
68
+ end
69
+
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Fabrication
2
- VERSION = '0.2.3'
2
+ VERSION = '0.2.4'
3
3
  end
@@ -114,9 +114,6 @@ describe Fabrication do
114
114
 
115
115
  context 'with an active record object' do
116
116
 
117
- before(:all) { TestMigration.up }
118
- after(:all) { TestMigration.down }
119
-
120
117
  before(:all) do
121
118
  Fabricator(:company) do
122
119
  name { Faker::Company.name }
@@ -124,11 +121,18 @@ describe Fabrication do
124
121
  after_create { |o| o.update_attribute(:city, "Jacksonville Beach") }
125
122
  end
126
123
 
124
+ Fabricator(:other_company, :from => :company) do
125
+ divisions(:count => 2) { Fabricate(:division) }
126
+ end
127
+
127
128
  Fabricator(:division) do
128
129
  name "Awesome Division"
129
130
  end
130
131
  end
131
132
 
133
+ before { TestMigration.up }
134
+ after { TestMigration.down }
135
+
132
136
  let(:company) { Fabricate(:company, :name => "Hashrocket") }
133
137
 
134
138
  it 'generates field blocks immediately' do
@@ -139,12 +143,17 @@ describe Fabrication do
139
143
  Division.find_all_by_company_id(company.id).count.should == 4
140
144
  end
141
145
 
146
+ it 'executes after create blocks' do
147
+ company.city.should == 'Jacksonville Beach'
148
+ end
149
+
142
150
  it 'overrides associations' do
143
151
  Fabricate(:company, :divisions => []).divisions.should == []
144
152
  end
145
153
 
146
- it 'executes after create blocks' do
147
- company.city.should == 'Jacksonville Beach'
154
+ it 'overrides inherited associations' do
155
+ Fabricate(:other_company).divisions.count.should == 2
156
+ Division.count.should == 2
148
157
  end
149
158
 
150
159
  end
@@ -154,7 +163,13 @@ describe Fabrication do
154
163
  before(:all) do
155
164
  Fabricator(:author) do
156
165
  name "George Orwell"
157
- books(:count => 4) { |author, i| "book title #{i}" }
166
+ books(:count => 4) do |author, i|
167
+ Fabricate(:book, :title => "book title #{i}", :author => author)
168
+ end
169
+ end
170
+
171
+ Fabricator(:book) do
172
+ title "1984"
158
173
  end
159
174
  end
160
175
 
@@ -165,7 +180,7 @@ describe Fabrication do
165
180
  end
166
181
 
167
182
  it 'generates four books' do
168
- author.books.should == (1..4).map { |i| "book title #{i}" }
183
+ author.books.map(&:title).should == (1..4).map { |i| "book title #{i}" }
169
184
  end
170
185
  end
171
186
 
@@ -176,9 +191,10 @@ describe Fabrication do
176
191
  let(:ernie) { Fabricate(:hemingway) }
177
192
 
178
193
  before(:all) do
194
+ Fabricator(:book)
179
195
  Fabricator(:author) do
180
196
  name 'George Orwell'
181
- books { ['1984'] }
197
+ books { |author| [Fabricate(:book, :title => '1984', :author => author)] }
182
198
  end
183
199
 
184
200
  Fabricator(:hemingway, :from => :author) do
@@ -187,7 +203,7 @@ describe Fabrication do
187
203
  end
188
204
 
189
205
  it 'has the values from the parent' do
190
- ernie.books.should == ['1984']
206
+ ernie.books.map(&:title).should == ['1984']
191
207
  end
192
208
 
193
209
  it 'overrides specified values from the parent' do
@@ -211,7 +227,7 @@ describe Fabrication do
211
227
  end
212
228
 
213
229
  it 'not have any books' do
214
- ernie.books.should be_nil
230
+ ernie.books.should == []
215
231
  end
216
232
 
217
233
  end
@@ -253,7 +269,11 @@ describe Fabrication do
253
269
 
254
270
  context 'defining a fabricator without a block' do
255
271
 
256
- it 'works fine'
272
+ before(:all) { Fabricator(:author) }
273
+
274
+ it 'works fine' do
275
+ Fabricate(:author).should be
276
+ end
257
277
 
258
278
  end
259
279
 
@@ -5,14 +5,18 @@ describe Fabrication::Generator::ActiveRecord do
5
5
  before(:all) { TestMigration.up }
6
6
  after(:all) { TestMigration.down }
7
7
 
8
- let(:generator) do
9
- Fabrication::Generator::ActiveRecord.new(Company) do
8
+ let(:schematic) do
9
+ Fabrication::Schematic.new do
10
10
  name 'Company Name'
11
11
  city { |c| c.name.reverse.downcase.titleize }
12
12
  divisions(:count => 2) { |c, i| Fabricate(:division, :company => c, :name => "Division #{i}") }
13
13
  end
14
14
  end
15
15
 
16
+ let(:generator) do
17
+ Fabrication::Generator::ActiveRecord.new(Company, schematic)
18
+ end
19
+
16
20
  context 'active record object' do
17
21
 
18
22
  let(:company) do
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Fabrication::Generator::Base do
4
4
 
5
- let(:generator) do
6
- Fabrication::Generator::Base.new(Person) do
5
+ let(:schematic) do
6
+ Fabrication::Schematic.new do
7
7
  first_name 'Some'
8
8
  last_name { |person| person.first_name.reverse.capitalize }
9
9
  age 40
@@ -11,12 +11,14 @@ describe Fabrication::Generator::Base do
11
11
  end
12
12
  end
13
13
 
14
+ let(:generator) { Fabrication::Generator::Base.new(Person, schematic) }
15
+
14
16
  let(:person) do
15
17
  generator.generate({:first_name => 'Body'})
16
18
  end
17
19
 
18
20
  it 'passes the object to blocks' do
19
- person.last_name.should == 'Emos'
21
+ person.last_name.should == 'Ydob'
20
22
  end
21
23
 
22
24
  it 'passes the object and count to blocks' do
@@ -32,7 +34,7 @@ describe Fabrication::Generator::Base do
32
34
  end
33
35
 
34
36
  it 'generates the last name immediately' do
35
- person.instance_variable_get(:@last_name).should == 'Emos'
37
+ person.instance_variable_get(:@last_name).should == 'Ydob'
36
38
  end
37
39
 
38
40
  it 'generates the age immediately' do
@@ -2,14 +2,20 @@ require 'spec_helper'
2
2
 
3
3
  describe Fabrication::Generator::Mongoid do
4
4
 
5
- let(:generator) do
6
- Fabrication::Generator::Mongoid.new(Author) do
5
+ before(:all) do
6
+ Fabricator(:book) { title "book title" }
7
+ end
8
+
9
+ let(:schematic) do
10
+ Fabrication::Schematic.new do
7
11
  name 'Name'
8
12
  handle { |author| author.name.downcase }
9
- books(:count => 3) { |author, index| "#{author.name} #{index}" }
13
+ books(:count => 3) { |author, index| Fabricate(:book, :title => "#{author.name} #{index}", :author => author) }
10
14
  end
11
15
  end
12
16
 
17
+ let(:generator) { Fabrication::Generator::Mongoid.new(Author, schematic) }
18
+
13
19
  context 'mongoid object' do
14
20
 
15
21
  before { generator.generate(:name => 'Something') }
@@ -19,7 +25,7 @@ describe Fabrication::Generator::Mongoid do
19
25
  end
20
26
 
21
27
  it 'passes the object and count to blocks' do
22
- generator.generate({}).books.should == ["Name 1","Name 2","Name 3"]
28
+ generator.generate({}).books.map(&:title).should == ["Name 1","Name 2","Name 3"]
23
29
  end
24
30
 
25
31
  it 'persists the author upon creation' do
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication::Schematic do
4
+
5
+ let(:schematic) do
6
+ Fabrication::Schematic.new do
7
+ name "Orgasmo"
8
+ something(:param => 2) { "hi!" }
9
+ another_thing { 25 }
10
+ end
11
+ end
12
+
13
+ context "without inheritance" do
14
+
15
+ subject { schematic }
16
+
17
+ it "stored 'name' correctly" do
18
+ attribute = subject.attribute(:name)
19
+ attribute.name.should == :name
20
+ attribute.params.should be_nil
21
+ attribute.value.should == "Orgasmo"
22
+ end
23
+
24
+ it "stored 'something' correctly" do
25
+ attribute = subject.attribute(:something)
26
+ attribute.name.should == :something
27
+ attribute.params.should == { :param => 2 }
28
+ Proc.should === attribute.value
29
+ attribute.value.call.should == "hi!"
30
+ end
31
+
32
+ it "stored 'another_thing' correctly" do
33
+ attribute = subject.attribute(:another_thing)
34
+ attribute.name.should == :another_thing
35
+ attribute.params.should be_nil
36
+ Proc.should === attribute.value
37
+ attribute.value.call.should == 25
38
+ end
39
+
40
+ end
41
+
42
+ context "with inheritance" do
43
+
44
+ subject do
45
+ schematic.merge! do
46
+ name { "Willis" }
47
+ something "Else!"
48
+ another_thing(:thats_what => 'she_said') { "Boo-ya!" }
49
+ end
50
+ end
51
+
52
+ it "stored 'name' correctly" do
53
+ attribute = subject.attribute(:name)
54
+ attribute.name.should == :name
55
+ attribute.params.should be_nil
56
+ Proc.should === attribute.value
57
+ attribute.value.call.should == "Willis"
58
+ end
59
+
60
+ it "stored 'something' correctly" do
61
+ attribute = subject.attribute(:something)
62
+ attribute.name.should == :something
63
+ attribute.params.should be_nil
64
+ attribute.value.should == "Else!"
65
+ end
66
+
67
+ it "stored 'another_thing' correctly" do
68
+ attribute = subject.attribute(:another_thing)
69
+ attribute.name.should == :another_thing
70
+ attribute.params.should == { :thats_what => 'she_said' }
71
+ Proc.should === attribute.value
72
+ attribute.value.call.should == "Boo-ya!"
73
+ end
74
+
75
+ end
76
+
77
+ it 'is deep clonable' do
78
+ schematic2 = schematic.clone
79
+ schematic.merge! do
80
+ name "Henry"
81
+ end
82
+ schematic.attribute(:name).value.should == 'Henry'
83
+ schematic2.attribute(:name).value.should == 'Orgasmo'
84
+ end
85
+
86
+ it 'allows temporary parameter overrides' do
87
+ schematic2 = schematic.merge(:name => 'Henry')
88
+ schematic.attribute(:name).value.should == 'Orgasmo'
89
+ schematic2.attribute(:name).value.should == 'Henry'
90
+ end
91
+
92
+ end
@@ -6,12 +6,9 @@ require 'spec'
6
6
  require 'spec/autorun'
7
7
  require 'fabrication'
8
8
  require 'ffaker'
9
- require 'active_record'
10
- require 'mongoid'
11
9
 
12
10
  Spec::Runner.configure do |config|
13
11
  config.before(:all) do
14
12
  Fabrication.clear_definitions
15
- Author.delete_all
16
13
  end
17
14
  end
@@ -1,3 +1,5 @@
1
+ require 'active_record'
2
+
1
3
  # change this if sqlite is unavailable
2
4
  dbconfig = {
3
5
  :adapter => 'sqlite3',
@@ -0,0 +1,33 @@
1
+ require 'mongoid'
2
+
3
+ Mongoid.configure do |config|
4
+ config.allow_dynamic_fields = true
5
+ config.master = Mongo::Connection.new.db("fabrication_test")
6
+ end
7
+
8
+ def clear_mongodb
9
+ Mongoid.master.collections.select {|c| c.name !~ /system/ }.each(&:drop)
10
+ end
11
+
12
+ Spec::Runner.configure do |config|
13
+ config.before(:all) do
14
+ clear_mongodb
15
+ end
16
+ end
17
+
18
+ class Author
19
+ include Mongoid::Document
20
+
21
+ embeds_many :books
22
+
23
+ field :name
24
+ field :handle
25
+ end
26
+
27
+ class Book
28
+ include Mongoid::Document
29
+
30
+ field :title
31
+
32
+ embedded_in :author, :inverse_of => :books
33
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fabrication
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 3
10
- version: 0.2.3
9
+ - 4
10
+ version: 0.2.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Paul Elliott
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-02 00:00:00 -04:00
18
+ date: 2010-07-18 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -113,6 +113,7 @@ files:
113
113
  - lib/fabrication/generator/active_record.rb
114
114
  - lib/fabrication/generator/base.rb
115
115
  - lib/fabrication/generator/mongoid.rb
116
+ - lib/fabrication/schematic.rb
116
117
  - lib/fabrication/version.rb
117
118
  - lib/fabrication.rb
118
119
  - spec/fabrication_spec.rb
@@ -120,11 +121,12 @@ files:
120
121
  - spec/generator/active_record_spec.rb
121
122
  - spec/generator/base_spec.rb
122
123
  - spec/generator/mongoid_spec.rb
124
+ - spec/schematic_spec.rb
123
125
  - spec/spec.opts
124
126
  - spec/spec_helper.rb
125
- - spec/support/active_record_setup.rb
127
+ - spec/support/active_record.rb
126
128
  - spec/support/helper_objects.rb
127
- - spec/support/mongoid_setup.rb
129
+ - spec/support/mongoid.rb
128
130
  - README.markdown
129
131
  has_rdoc: true
130
132
  homepage: http://github.com/paulelliott/fabrication
@@ -1,11 +0,0 @@
1
- Mongoid.configure do |config|
2
- config.allow_dynamic_fields = true
3
- config.master = Mongo::Connection.new.db("fabrication_test")
4
- end
5
-
6
- class Author
7
- include Mongoid::Document
8
- field :name
9
- field :handle
10
- field :books, :type => Array
11
- end