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 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 :instance, :options
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]) || 1
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} \> 1
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
@@ -1,7 +1,5 @@
1
1
  class Fabrication::Generator::Mongoid < Fabrication::Generator::Base
2
2
 
3
- attr_accessor :instance
4
-
5
3
  def generate(options)
6
4
  self.instance = super.tap { |t| t.save }
7
5
  end
@@ -1,3 +1,3 @@
1
1
  module Fabrication
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -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 be
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
- Fabrication::Generator::ActiveRecord.new(Company) do
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 == 1
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 == 1
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 == 1
60
+ company.reload.divisions.length.should == 2
48
61
  end
49
62
 
50
63
  end
@@ -2,12 +2,25 @@ require 'spec_helper'
2
2
 
3
3
  describe Fabrication::Generator::Base do
4
4
 
5
- let(:person) do
5
+ let(:generator) do
6
6
  Fabrication::Generator::Base.new(Person) do
7
7
  first_name 'Some'
8
- last_name { Faker::Name.last_name }
8
+ last_name { |person| person.first_name.reverse.capitalize }
9
9
  age 40
10
- end.generate({:first_name => 'Body'})
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 be
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
- before(:all) { TestMigration.up }
6
- after(:all) { TestMigration.down }
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
- let(:company) do
11
- Fabrication::Generator::Mongoid.new(Author) do
12
- name 'Name'
13
- end.generate({:name => 'Something'})
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
- before { company }
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
@@ -6,5 +6,6 @@ end
6
6
  class Author
7
7
  include Mongoid::Document
8
8
  field :name
9
+ field :handle
9
10
  field :books, :type => Array
10
11
  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: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
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-19 00:00:00 -04:00
18
+ date: 2010-06-20 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency