fabrication 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +42 -0
- data/lib/fabrication/generator/active_record.rb +4 -4
- data/lib/fabrication/generator/base.rb +2 -2
- data/lib/fabrication/generator/mongoid.rb +0 -2
- data/lib/fabrication/version.rb +1 -1
- data/spec/fabrication_spec.rb +4 -4
- data/spec/generator/active_record_spec.rb +24 -11
- data/spec/generator/base_spec.rb +17 -4
- data/spec/generator/mongoid_spec.rb +14 -7
- data/spec/support/mongoid_setup.rb +1 -0
- metadata +4 -4
data/README.markdown
CHANGED
@@ -1,3 +1,45 @@
|
|
1
1
|
### Fabrication ###
|
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
4
|
|
5
|
+
Currently supported object types are...
|
6
|
+
|
7
|
+
* Plain old Ruby objects
|
8
|
+
* ActiveRecord objects
|
9
|
+
* Mongoid Documents
|
10
|
+
|
11
|
+
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 passing :force => true when defining the field in the Fabricator.
|
12
|
+
|
13
|
+
### Installation ###
|
14
|
+
|
15
|
+
Add this to your gemfile.
|
16
|
+
|
17
|
+
`gem 'fabrication'`
|
18
|
+
|
19
|
+
Now you can define fabricators in any of the following locations.
|
20
|
+
|
21
|
+
* `spec/fabricators.rb`
|
22
|
+
* `spec/fabricators/*.rb`
|
23
|
+
|
24
|
+
* `test/fabricators.rb`
|
25
|
+
* `test/fabricators/*.rb`
|
26
|
+
|
27
|
+
They are automatically loaded, so no additional requires are necessary.
|
28
|
+
|
29
|
+
### Usage ###
|
30
|
+
|
31
|
+
Define your fabricators.
|
32
|
+
|
33
|
+
Fabricator(:company) do
|
34
|
+
name "Fun Factory"
|
35
|
+
employees(:count => 20) { |company, i| Fabricate(:drone, :company => company, :name => "Drone #{i}") }
|
36
|
+
location(:force => true) { Fabricate(:location) }
|
37
|
+
after_create { |company| company.update_attribute(:ceo, Fabricate(:drone, :name => 'Lead Drone') }
|
38
|
+
end
|
39
|
+
|
40
|
+
Breaking down the above, we are defining a "company" fabricator, which will generate Company model objects.
|
41
|
+
|
42
|
+
* The object has a name field, which is statically filled with "Fun Factory".
|
43
|
+
* 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.
|
44
|
+
* It has a belongs_to association to location and this will be generated immediately with the company object. This is because of the :force => true parameter being passed in.
|
45
|
+
* After the object is created, it will update the "ceo" association with a new "drone" record.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Fabrication::Generator::ActiveRecord < Fabrication::Generator::Base
|
2
2
|
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :options
|
4
4
|
|
5
5
|
def generate(options)
|
6
6
|
self.options = options
|
@@ -13,7 +13,7 @@ class Fabrication::Generator::ActiveRecord < Fabrication::Generator::Base
|
|
13
13
|
|
14
14
|
def method_missing(method_name, *args, &block)
|
15
15
|
method_name = method_name.to_s
|
16
|
-
count = (args && args.first && args.first[:count]) ||
|
16
|
+
count = (args && args.first && args.first[:count]) || 0
|
17
17
|
unless options.include?(method_name.to_sym)
|
18
18
|
if block_given?
|
19
19
|
unless (args.first && args.first[:force]) || instance.class.columns.map(&:name).include?(method_name)
|
@@ -28,7 +28,7 @@ class Fabrication::Generator::ActiveRecord < Fabrication::Generator::Base
|
|
28
28
|
def #{method_name}
|
29
29
|
original_value = @__#{method_name}_original.call
|
30
30
|
if @__#{method_name}_block.present?
|
31
|
-
if #{count}
|
31
|
+
if #{count} \>= 1
|
32
32
|
original_value = #{method_name}= (1..#{count}).map { |i| @__#{method_name}_block.call(self, i) }
|
33
33
|
else
|
34
34
|
original_value = #{method_name}= @__#{method_name}_block.call(self)
|
@@ -43,7 +43,7 @@ class Fabrication::Generator::ActiveRecord < Fabrication::Generator::Base
|
|
43
43
|
assign(instance, method_name, args.first, &block)
|
44
44
|
end
|
45
45
|
else
|
46
|
-
assign(instance, method_name, args)
|
46
|
+
assign(instance, method_name, args.first)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -26,10 +26,10 @@ class Fabrication::Generator::Base
|
|
26
26
|
value = nil
|
27
27
|
if param.is_a?(Hash) && param[:count] && param[:count] > 1
|
28
28
|
value = (1..param[:count]).map do |i|
|
29
|
-
block_given? ? yield(i) : param
|
29
|
+
block_given? ? yield(instance, i) : param
|
30
30
|
end
|
31
31
|
else
|
32
|
-
value = block_given? ? yield : param
|
32
|
+
value = block_given? ? yield(instance) : param
|
33
33
|
end
|
34
34
|
instance.send("#{method_name.to_s}=", value)
|
35
35
|
end
|
data/lib/fabrication/version.rb
CHANGED
data/spec/fabrication_spec.rb
CHANGED
@@ -45,7 +45,7 @@ describe Fabrication do
|
|
45
45
|
first_name { Faker::Name.first_name }
|
46
46
|
last_name { Faker::Name.last_name }
|
47
47
|
age { rand(100) }
|
48
|
-
shoes(:count => 10) { |i| "shoe #{i}" }
|
48
|
+
shoes(:count => 10) { |person, i| "shoe #{i}" }
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -111,10 +111,10 @@ describe Fabrication do
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
let(:company) { Fabricate(:company) }
|
114
|
+
let(:company) { Fabricate(:company, :name => "Hashrocket") }
|
115
115
|
|
116
116
|
it 'generates field blocks immediately' do
|
117
|
-
company.name.should
|
117
|
+
company.name.should == "Hashrocket"
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'generates associations immediately when forced' do
|
@@ -136,7 +136,7 @@ describe Fabrication do
|
|
136
136
|
let(:author) do
|
137
137
|
Fabricator(:author) do
|
138
138
|
name "George Orwell"
|
139
|
-
books(:count => 4) { |i| "book title #{i}" }
|
139
|
+
books(:count => 4) { |author, i| "book title #{i}" }
|
140
140
|
end.fabricate
|
141
141
|
end
|
142
142
|
|
@@ -5,13 +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
|
10
|
+
name 'Company Name'
|
11
|
+
city { |c| c.name.reverse.downcase.titleize }
|
12
|
+
divisions(:count => 2) { |c, i| Fabricate(:division, :company => c, :name => "Division #{i}") }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
8
16
|
context 'active record object' do
|
9
17
|
|
10
18
|
let(:company) do
|
11
|
-
|
12
|
-
name 'Company Name'
|
13
|
-
divisions { |c| [Fabricate(:division, :company => c)] }
|
14
|
-
end.generate({:name => 'Something'})
|
19
|
+
generator.generate({})
|
15
20
|
end
|
16
21
|
|
17
22
|
before(:all) do
|
@@ -22,29 +27,37 @@ describe Fabrication::Generator::ActiveRecord do
|
|
22
27
|
|
23
28
|
before { company }
|
24
29
|
|
25
|
-
it 'persists the company upon creation' do
|
26
|
-
Company.find_by_name('Something').should be
|
27
|
-
end
|
28
|
-
|
29
30
|
it 'does not persist the divisions immediately' do
|
30
31
|
Division.count.should == 0
|
31
32
|
end
|
32
33
|
|
34
|
+
it 'passes the object to blocks' do
|
35
|
+
company.city.should == 'Eman Ynapmoc'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'passes the object and count to blocks' do
|
39
|
+
company.divisions.map(&:name).should == ["Division 1", "Division 2"]
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'persists the company upon creation' do
|
43
|
+
Company.find_by_name('Company Name').should be
|
44
|
+
end
|
45
|
+
|
33
46
|
context 'upon accessing the divisions association' do
|
34
47
|
|
35
48
|
let(:divisions) { company.divisions }
|
36
49
|
|
37
50
|
it 'generates the divisions' do
|
38
|
-
divisions.length.should ==
|
51
|
+
divisions.length.should == 2
|
39
52
|
end
|
40
53
|
|
41
54
|
it 'persists the divisions' do
|
42
55
|
divisions
|
43
|
-
Division.find_all_by_company_id(company.id).count.should ==
|
56
|
+
Division.find_all_by_company_id(company.id).count.should == 2
|
44
57
|
end
|
45
58
|
|
46
59
|
it 'can load the divisions from the database' do
|
47
|
-
company.reload.divisions.length.should ==
|
60
|
+
company.reload.divisions.length.should == 2
|
48
61
|
end
|
49
62
|
|
50
63
|
end
|
data/spec/generator/base_spec.rb
CHANGED
@@ -2,12 +2,25 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Fabrication::Generator::Base do
|
4
4
|
|
5
|
-
let(:
|
5
|
+
let(:generator) do
|
6
6
|
Fabrication::Generator::Base.new(Person) do
|
7
7
|
first_name 'Some'
|
8
|
-
last_name {
|
8
|
+
last_name { |person| person.first_name.reverse.capitalize }
|
9
9
|
age 40
|
10
|
-
|
10
|
+
shoes(:count => 4) { |person, index| "shoe #{index}" }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:person) do
|
15
|
+
generator.generate({:first_name => 'Body'})
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'passes the object to blocks' do
|
19
|
+
person.last_name.should == 'Emos'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'passes the object and count to blocks' do
|
23
|
+
person.shoes.should == (1..4).map { |i| "shoe #{i}" }
|
11
24
|
end
|
12
25
|
|
13
26
|
it 'generates an instance' do
|
@@ -19,7 +32,7 @@ describe Fabrication::Generator::Base do
|
|
19
32
|
end
|
20
33
|
|
21
34
|
it 'generates the last name immediately' do
|
22
|
-
person.instance_variable_get(:@last_name).should
|
35
|
+
person.instance_variable_get(:@last_name).should == 'Emos'
|
23
36
|
end
|
24
37
|
|
25
38
|
it 'generates the age immediately' do
|
@@ -2,18 +2,25 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Fabrication::Generator::Mongoid do
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
let(:generator) do
|
6
|
+
Fabrication::Generator::Mongoid.new(Author) do
|
7
|
+
name 'Name'
|
8
|
+
handle { |author| author.name.downcase }
|
9
|
+
books(:count => 3) { |author, index| "#{author.name} #{index}" }
|
10
|
+
end
|
11
|
+
end
|
7
12
|
|
8
13
|
context 'mongoid object' do
|
9
14
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
15
|
+
before { generator.generate(:name => 'Something') }
|
16
|
+
|
17
|
+
it 'passes the object to blocks' do
|
18
|
+
generator.generate({}).handle.should == "name"
|
14
19
|
end
|
15
20
|
|
16
|
-
|
21
|
+
it 'passes the object and count to blocks' do
|
22
|
+
generator.generate({}).books.should == ["Name 1","Name 2","Name 3"]
|
23
|
+
end
|
17
24
|
|
18
25
|
it 'persists the author upon creation' do
|
19
26
|
Author.where(:name => 'Something').first.should be
|
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:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
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-06-
|
18
|
+
date: 2010-06-20 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|