fabrication 0.2.3 → 0.2.4

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