fabrication 0.0.1

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.
data/README.markdown ADDED
File without changes
@@ -0,0 +1,36 @@
1
+ module Fabrication
2
+
3
+ autoload :Fabricator, 'fabrication/fabricator'
4
+
5
+ module Generator
6
+ autoload :ActiveRecord, 'fabrication/generator/active_record'
7
+ autoload :Base, 'fabrication/generator/base'
8
+ end
9
+
10
+ class << self
11
+
12
+ def schematic(name, &block)
13
+ fabricators[name] = Fabricator.new(name, &block)
14
+ end
15
+
16
+ def generate(name, options)
17
+ fabricators[name].fabricate(options)
18
+ end
19
+
20
+ private
21
+
22
+ def fabricators
23
+ @@fabricators ||= {}
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ def Fabricator(name, &block)
31
+ Fabrication.schematic(name, &block)
32
+ end
33
+
34
+ def Fabricate(name, options={})
35
+ Fabrication.generate(name, options)
36
+ end
@@ -0,0 +1,33 @@
1
+ class Fabrication::Fabricator
2
+
3
+ def initialize(class_name, &block)
4
+ klass = class_for(class_name)
5
+ if klass.ancestors.include?(ActiveRecord::Base)
6
+ @fabricator = Fabrication::Generator::ActiveRecord.new(klass, &block)
7
+ else
8
+ @fabricator = Fabrication::Generator::Base.new(klass, &block)
9
+ end
10
+ end
11
+
12
+ def fabricate(options={})
13
+ @fabricator.generate(options)
14
+ end
15
+
16
+ #Stolen directly from factory_girl. Thanks thoughtbot!
17
+ def class_for(class_or_to_s)
18
+ if class_or_to_s.respond_to?(:to_sym)
19
+ class_name = variable_name_to_class_name(class_or_to_s)
20
+ class_name.split('::').inject(Object) do |object, string|
21
+ object.const_get(string)
22
+ end
23
+ else
24
+ class_or_to_s
25
+ end
26
+ end
27
+
28
+ #Stolen directly from factory_girl. Thanks thoughtbot!
29
+ def variable_name_to_class_name(name)
30
+ name.to_s.gsub(/\/(.?)/){"::#{$1.upcase}"}.gsub(/(?:^|_)(.)/){$1.upcase}
31
+ end
32
+
33
+ end
@@ -0,0 +1,42 @@
1
+ class Fabrication::Generator::ActiveRecord < Fabrication::Generator::Base
2
+
3
+ def generate(options)
4
+ @options = options
5
+ @instance = super
6
+ @instance.save
7
+ @instance
8
+ end
9
+
10
+ def method_missing(method_name, *args, &block)
11
+ method_name = method_name.to_s
12
+ unless @options.include?(method_name.to_sym)
13
+ if block_given?
14
+ unless @instance.class.columns.map(&:name).include?(method_name)
15
+ # copy the original getter
16
+ @instance.instance_variable_set("@__#{method_name}_original", @instance.method(method_name).clone)
17
+
18
+ # store the block for lazy generation
19
+ @instance.instance_variable_set("@__#{method_name}_block", block)
20
+
21
+ # redefine the getter
22
+ @instance.instance_eval %<
23
+ def #{method_name}
24
+ original_value = @__#{method_name}_original.call
25
+ if @__#{method_name}_block.present?
26
+ original_value = #{method_name}= @__#{method_name}_block.call(self)
27
+ @__#{method_name}_block = nil
28
+ @__#{method_name}_original.call
29
+ end
30
+ original_value
31
+ end
32
+ >
33
+ else
34
+ assign(@instance, method_name, yield)
35
+ end
36
+ else
37
+ assign(@instance, method_name, args.first)
38
+ end
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,25 @@
1
+ class Fabrication::Generator::Base
2
+
3
+ def initialize(klass, &block)
4
+ @klass = klass
5
+ @block = block
6
+ end
7
+
8
+ def generate(options)
9
+ @instance = @klass.new
10
+ instance_eval &@block
11
+ options.each { |k,v| assign(@instance, k, v) }
12
+ @instance
13
+ end
14
+
15
+ def method_missing(method_name, *args, &block)
16
+ assign(@instance, method_name.to_s, block_given? ? yield : args.first)
17
+ end
18
+
19
+ private
20
+
21
+ def assign(instance, method_name, value)
22
+ instance.send("#{method_name.to_s}=", value)
23
+ end
24
+
25
+ end
@@ -0,0 +1,3 @@
1
+ module Fabrication
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication do
4
+
5
+ context 'block generated fields' do
6
+
7
+ let(:person) do
8
+ Fabricate(:person)
9
+ end
10
+
11
+ before(:all) do
12
+ Fabricator(:person) do
13
+ first_name { Faker::Name.first_name }
14
+ last_name { Faker::Name.last_name }
15
+ age { rand(100) }
16
+ end
17
+ end
18
+
19
+ it 'has a first name' do
20
+ person.first_name.should be
21
+ end
22
+
23
+ it 'has a last name' do
24
+ person.last_name.should be
25
+ end
26
+
27
+ it 'has an age' do
28
+ person.age.should be
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication do
4
+
5
+ context 'with an active record object' do
6
+
7
+ before(:all) { TestMigration.up }
8
+ after(:all) { TestMigration.down }
9
+
10
+ before do
11
+ Fabricator(:company) do
12
+ name { Faker::Company.name }
13
+ end
14
+ end
15
+
16
+ let(:company) { Fabricate(:company) }
17
+
18
+ it 'generates field blocks immediately' do
19
+ company.name.should be
20
+ end
21
+ it 'overrides associations'
22
+ end
23
+
24
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication::Fabricator do
4
+
5
+ it 'generates a new object every time' do
6
+ f = Fabrication::Fabricator.new(:person) { first_name '1' }
7
+ f.fabricate.should_not == f.fabricate
8
+ end
9
+
10
+ context 'with a plain old ruby object' do
11
+
12
+ let(:fabricator) { Fabrication::Fabricator.new(:person) { first_name '1' } }
13
+
14
+ it 'fabricates a Person instance' do
15
+ fabricator.fabricate.instance_of?(Person).should be_true
16
+ end
17
+
18
+ it 'uses the base generator' do
19
+ fabricator.instance_variable_get(:@fabricator).instance_of?(Fabrication::Generator::Base).should be_true
20
+ end
21
+
22
+ end
23
+
24
+ context 'with an activerecord object' do
25
+
26
+ before(:all) { TestMigration.up }
27
+ after(:all) { TestMigration.down }
28
+
29
+ let(:fabricator) { Fabrication::Fabricator.new(:company) { name '1' } }
30
+
31
+ it 'fabricates a Company instance' do
32
+ fabricator.fabricate.instance_of?(Company).should be_true
33
+ end
34
+
35
+ it 'uses the activerecord generator' do
36
+ fabricator.instance_variable_get(:@fabricator).instance_of?(Fabrication::Generator::ActiveRecord).should be_true
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication::Generator::ActiveRecord do
4
+
5
+ before(:all) { TestMigration.up }
6
+ after(:all) { TestMigration.down }
7
+
8
+ context 'active record object' do
9
+
10
+ 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'})
15
+ end
16
+
17
+ before(:all) do
18
+ Fabricator(:division) do
19
+ name "Division Name"
20
+ end
21
+ end
22
+
23
+ before { company }
24
+
25
+ it 'persists the company upon creation' do
26
+ Company.find_by_name('Something').should be
27
+ end
28
+
29
+ it 'does not persist the divisions immediately' do
30
+ Division.count.should == 0
31
+ end
32
+
33
+ context 'upon accessing the divisions association' do
34
+
35
+ let(:divisions) { company.divisions }
36
+
37
+ it 'generates the divisions' do
38
+ divisions.length.should == 1
39
+ end
40
+
41
+ it 'persists the divisions' do
42
+ divisions
43
+ Division.find_all_by_company_id(company.id).count.should == 1
44
+ end
45
+
46
+ it 'can load the divisions from the database' do
47
+ company.reload.divisions.length.should == 1
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication::Generator::Base do
4
+
5
+ let(:person) do
6
+ Fabrication::Generator::Base.new(Person) do
7
+ first_name 'Some'
8
+ last_name { Faker::Name.last_name }
9
+ age 40
10
+ end.generate({:first_name => 'Body'})
11
+ end
12
+
13
+ it 'generates an instance' do
14
+ person.instance_of?(Person).should be_true
15
+ end
16
+
17
+ it 'generates the first name immediately' do
18
+ person.instance_variable_get(:@first_name).should == 'Body'
19
+ end
20
+
21
+ it 'generates the last name immediately' do
22
+ person.instance_variable_get(:@last_name).should be
23
+ end
24
+
25
+ it 'generates the age immediately' do
26
+ person.instance_variable_get(:@age).should == 40
27
+ end
28
+
29
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication do
4
+
5
+ context 'multiple instance' do
6
+
7
+ let(:person1) { Fabricate(:person, :first_name => 'Jane') }
8
+ let(:person2) { Fabricate(:person, :first_name => 'John') }
9
+
10
+ before(:all) do
11
+ Fabricator(:person) do
12
+ first_name { Faker::Name.first_name }
13
+ last_name { Faker::Name.last_name }
14
+ age { rand(100) }
15
+ end
16
+ end
17
+
18
+ it 'person1 is named Jane' do
19
+ person1.first_name.should == 'Jane'
20
+ end
21
+
22
+ it 'person2 is named John' do
23
+ person2.first_name.should == 'John'
24
+ end
25
+
26
+ it 'they have different last names' do
27
+ person1.last_name.should_not == person2.last_name
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fabrication do
4
+
5
+ context 'static fields' do
6
+
7
+ let(:person) do
8
+ Fabricate(:person, :last_name => 'Awesome')
9
+ end
10
+
11
+ before(:all) do
12
+ Fabricator(:person) do
13
+ first_name 'Joe'
14
+ last_name 'Schmoe'
15
+ age 78
16
+ end
17
+ end
18
+
19
+ it 'has the default first name' do
20
+ person.first_name.should == 'Joe'
21
+ end
22
+
23
+ it 'has an overridden last name' do
24
+ person.last_name.should == 'Awesome'
25
+ end
26
+
27
+ it 'has the default age' do
28
+ person.age.should == 78
29
+ end
30
+
31
+ it 'generates a fresh object every time' do
32
+ Fabricate(:person).should_not == person
33
+ end
34
+
35
+ end
36
+
37
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format nested
@@ -0,0 +1,9 @@
1
+ $:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
2
+ $:.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rubygems'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+ require 'fabrication'
8
+ require 'ffaker'
9
+ require 'active_record'
@@ -0,0 +1,34 @@
1
+ # change this if sqlite is unavailable
2
+ dbconfig = {
3
+ :adapter => 'sqlite3',
4
+ :database => ':memory:'
5
+ }
6
+
7
+ ActiveRecord::Base.establish_connection(dbconfig)
8
+ ActiveRecord::Migration.verbose = false
9
+
10
+ class TestMigration < ActiveRecord::Migration
11
+ def self.up
12
+ create_table :companies, :force => true do |t|
13
+ t.column :name, :string
14
+ end
15
+
16
+ create_table :divisions, :force => true do |t|
17
+ t.column :name, :string
18
+ t.references :company
19
+ end
20
+ end
21
+
22
+ def self.down
23
+ drop_table :companies
24
+ drop_table :divisions
25
+ end
26
+ end
27
+
28
+ class Company < ActiveRecord::Base
29
+ has_many :divisions
30
+ end
31
+
32
+ class Division < ActiveRecord::Base
33
+ belongs_to :company
34
+ end
@@ -0,0 +1 @@
1
+ class Person; attr_accessor :age, :first_name, :last_name end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fabrication
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Paul Elliott
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-15 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 1
32
+ - 2
33
+ - 9
34
+ version: 1.2.9
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: ffaker
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 15
46
+ segments:
47
+ - 0
48
+ - 4
49
+ - 0
50
+ version: 0.4.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: activerecord
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 9
62
+ segments:
63
+ - 2
64
+ - 3
65
+ - 5
66
+ version: 2.3.5
67
+ type: :development
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3-ruby
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 27
78
+ segments:
79
+ - 1
80
+ - 3
81
+ - 0
82
+ version: 1.3.0
83
+ type: :development
84
+ version_requirements: *id004
85
+ description: Fabrication is an object generation framework that lazily generated attributes as they are used
86
+ email:
87
+ - paul@hashrocket.com
88
+ executables: []
89
+
90
+ extensions: []
91
+
92
+ extra_rdoc_files: []
93
+
94
+ files:
95
+ - lib/fabrication/fabricator.rb
96
+ - lib/fabrication/generator/active_record.rb
97
+ - lib/fabrication/generator/base.rb
98
+ - lib/fabrication/version.rb
99
+ - lib/fabrication.rb
100
+ - spec/block_generated_fields_spec.rb
101
+ - spec/fabrication_spec.rb
102
+ - spec/fabricator_spec.rb
103
+ - spec/generator/active_record_spec.rb
104
+ - spec/generator/base_spec.rb
105
+ - spec/multiple_instance_spec.rb
106
+ - spec/simple_object_spec.rb
107
+ - spec/spec.opts
108
+ - spec/spec_helper.rb
109
+ - spec/support/database_setup.rb
110
+ - spec/support/helper_objects.rb
111
+ - README.markdown
112
+ has_rdoc: true
113
+ homepage: http://github.com/paulelliott/fabrication
114
+ licenses: []
115
+
116
+ post_install_message:
117
+ rdoc_options: []
118
+
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 3
136
+ segments:
137
+ - 0
138
+ version: "0"
139
+ requirements: []
140
+
141
+ rubyforge_project:
142
+ rubygems_version: 1.3.7
143
+ signing_key:
144
+ specification_version: 3
145
+ summary: Fabrication aims to provide a fast and simple solution for test object generation
146
+ test_files: []
147
+