machinist 1.0.6 → 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +7 -4
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +47 -0
  4. data/MIT-LICENSE +2 -1
  5. data/README.markdown +182 -204
  6. data/Rakefile +22 -29
  7. data/VERSION +1 -1
  8. data/lib/generators/machinist/install/USAGE +2 -0
  9. data/lib/generators/machinist/install/install_generator.rb +46 -0
  10. data/lib/generators/machinist/install/templates/blueprints.rb +9 -0
  11. data/lib/generators/machinist/install/templates/machinist.rb.erb +7 -0
  12. data/lib/generators/machinist/model/model_generator.rb +13 -0
  13. data/lib/machinist/active_record/blueprint.rb +16 -0
  14. data/lib/machinist/active_record/lathe.rb +24 -0
  15. data/lib/machinist/active_record.rb +8 -93
  16. data/lib/machinist/blueprint.rb +89 -0
  17. data/lib/machinist/exceptions.rb +32 -0
  18. data/lib/machinist/lathe.rb +68 -0
  19. data/lib/machinist/machinable.rb +95 -0
  20. data/lib/machinist/version.rb +3 -0
  21. data/lib/machinist.rb +4 -109
  22. data/machinist.gemspec +20 -65
  23. data/spec/active_record_spec.rb +85 -171
  24. data/spec/blueprint_spec.rb +76 -0
  25. data/spec/exceptions_spec.rb +20 -0
  26. data/spec/inheritance_spec.rb +104 -0
  27. data/spec/machinable_spec.rb +101 -0
  28. data/spec/spec_helper.rb +4 -6
  29. data/spec/support/active_record_environment.rb +65 -0
  30. metadata +125 -37
  31. data/.autotest +0 -7
  32. data/FAQ.markdown +0 -18
  33. data/init.rb +0 -2
  34. data/lib/machinist/blueprints.rb +0 -25
  35. data/lib/machinist/data_mapper.rb +0 -83
  36. data/lib/machinist/object.rb +0 -30
  37. data/lib/machinist/sequel.rb +0 -62
  38. data/lib/sham.rb +0 -77
  39. data/spec/data_mapper_spec.rb +0 -134
  40. data/spec/db/.gitignore +0 -1
  41. data/spec/db/schema.rb +0 -20
  42. data/spec/log/.gitignore +0 -1
  43. data/spec/machinist_spec.rb +0 -190
  44. data/spec/sequel_spec.rb +0 -146
  45. data/spec/sham_spec.rb +0 -95
@@ -0,0 +1,65 @@
1
+ require 'active_record'
2
+ require 'machinist/active_record'
3
+
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => "mysql",
6
+ :database => "machinist",
7
+ :username => "root",
8
+ :password => ""
9
+ )
10
+
11
+ ActiveRecord::Schema.define(:version => 0) do
12
+ create_table :users, :force => true do |t|
13
+ t.column :username, :string
14
+ end
15
+
16
+ create_table :posts, :force => true do |t|
17
+ t.column :title, :string
18
+ t.column :author_id, :integer
19
+ t.column :body, :text
20
+ end
21
+
22
+ create_table :comments, :force => true do |t|
23
+ t.column :post_id, :integer
24
+ t.column :body, :text
25
+ end
26
+
27
+ create_table :tags, :force => true do |t|
28
+ t.column :name, :string
29
+ end
30
+
31
+ create_table :posts_tags, :id => false, :force => true do |t|
32
+ t.column :post_id, :integer
33
+ t.column :tag_id, :integer
34
+ end
35
+ end
36
+
37
+ class User < ActiveRecord::Base
38
+ validates_presence_of :username
39
+ validates_uniqueness_of :username
40
+ end
41
+
42
+ class Post < ActiveRecord::Base
43
+ has_many :comments
44
+ belongs_to :author, :class_name => "User"
45
+ has_and_belongs_to_many :tags
46
+ end
47
+
48
+ class Comment < ActiveRecord::Base
49
+ belongs_to :post
50
+ end
51
+
52
+ class Tag < ActiveRecord::Base
53
+ has_and_belongs_to_many :posts
54
+ end
55
+
56
+ module ActiveRecordEnvironment
57
+
58
+ def empty_database!
59
+ [User, Post, Comment].each do |klass|
60
+ klass.delete_all
61
+ klass.clear_blueprints!
62
+ end
63
+ end
64
+
65
+ end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: machinist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ hash: 3
5
+ prerelease:
6
+ segments:
7
+ - 2
8
+ - 0
9
+ version: "2.0"
5
10
  platform: ruby
6
11
  authors:
7
12
  - Pete Yandell
@@ -9,86 +14,169 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-11-29 00:00:00 +11:00
13
- default_executable:
17
+ date: 2012-01-13 00:00:00 Z
14
18
  dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: activerecord
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: mysql
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ type: :development
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ type: :development
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: rcov
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ version_requirements: *id004
15
75
  - !ruby/object:Gem::Dependency
16
76
  name: rspec
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
17
87
  type: :development
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
88
+ version_requirements: *id005
89
+ - !ruby/object:Gem::Dependency
90
+ name: rdoc
91
+ prerelease: false
92
+ requirement: &id006 !ruby/object:Gem::Requirement
93
+ none: false
20
94
  requirements:
21
95
  - - ">="
22
96
  - !ruby/object:Gem::Version
23
- version: 1.2.8
24
- version:
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ type: :development
102
+ version_requirements: *id006
25
103
  description:
26
- email: pete@notahat.com
104
+ email:
105
+ - pete@notahat.com
27
106
  executables: []
28
107
 
29
108
  extensions: []
30
109
 
31
- extra_rdoc_files:
32
- - README.markdown
110
+ extra_rdoc_files: []
111
+
33
112
  files:
34
- - .autotest
35
113
  - .gitignore
36
- - FAQ.markdown
114
+ - Gemfile
115
+ - Gemfile.lock
37
116
  - MIT-LICENSE
38
117
  - README.markdown
39
118
  - Rakefile
40
119
  - VERSION
41
- - init.rb
120
+ - lib/generators/machinist/install/USAGE
121
+ - lib/generators/machinist/install/install_generator.rb
122
+ - lib/generators/machinist/install/templates/blueprints.rb
123
+ - lib/generators/machinist/install/templates/machinist.rb.erb
124
+ - lib/generators/machinist/model/model_generator.rb
42
125
  - lib/machinist.rb
43
126
  - lib/machinist/active_record.rb
44
- - lib/machinist/blueprints.rb
45
- - lib/machinist/data_mapper.rb
46
- - lib/machinist/object.rb
47
- - lib/machinist/sequel.rb
48
- - lib/sham.rb
127
+ - lib/machinist/active_record/blueprint.rb
128
+ - lib/machinist/active_record/lathe.rb
129
+ - lib/machinist/blueprint.rb
130
+ - lib/machinist/exceptions.rb
131
+ - lib/machinist/lathe.rb
132
+ - lib/machinist/machinable.rb
133
+ - lib/machinist/version.rb
49
134
  - machinist.gemspec
50
135
  - spec/active_record_spec.rb
51
- - spec/data_mapper_spec.rb
52
- - spec/db/.gitignore
53
- - spec/db/schema.rb
54
- - spec/log/.gitignore
55
- - spec/machinist_spec.rb
56
- - spec/sequel_spec.rb
57
- - spec/sham_spec.rb
136
+ - spec/blueprint_spec.rb
137
+ - spec/exceptions_spec.rb
138
+ - spec/inheritance_spec.rb
139
+ - spec/machinable_spec.rb
58
140
  - spec/spec_helper.rb
59
- has_rdoc: true
141
+ - spec/support/active_record_environment.rb
60
142
  homepage: http://github.com/notahat/machinist
61
143
  licenses: []
62
144
 
63
145
  post_install_message:
64
- rdoc_options:
65
- - --charset=UTF-8
146
+ rdoc_options: []
147
+
66
148
  require_paths:
67
149
  - lib
68
150
  required_ruby_version: !ruby/object:Gem::Requirement
151
+ none: false
69
152
  requirements:
70
153
  - - ">="
71
154
  - !ruby/object:Gem::Version
155
+ hash: 3
156
+ segments:
157
+ - 0
72
158
  version: "0"
73
- version:
74
159
  required_rubygems_version: !ruby/object:Gem::Requirement
160
+ none: false
75
161
  requirements:
76
162
  - - ">="
77
163
  - !ruby/object:Gem::Version
164
+ hash: 3
165
+ segments:
166
+ - 0
78
167
  version: "0"
79
- version:
80
168
  requirements: []
81
169
 
82
- rubyforge_project:
83
- rubygems_version: 1.3.5
170
+ rubyforge_project: machinist
171
+ rubygems_version: 1.8.10
84
172
  signing_key:
85
173
  specification_version: 3
86
174
  summary: Fixtures aren't fun. Machinist is.
87
175
  test_files:
88
176
  - spec/active_record_spec.rb
89
- - spec/data_mapper_spec.rb
90
- - spec/db/schema.rb
91
- - spec/machinist_spec.rb
92
- - spec/sequel_spec.rb
93
- - spec/sham_spec.rb
177
+ - spec/blueprint_spec.rb
178
+ - spec/exceptions_spec.rb
179
+ - spec/inheritance_spec.rb
180
+ - spec/machinable_spec.rb
94
181
  - spec/spec_helper.rb
182
+ - spec/support/active_record_environment.rb
data/.autotest DELETED
@@ -1,7 +0,0 @@
1
- Autotest.add_hook :initialize do |at|
2
- at.clear_mappings
3
-
4
- at.add_mapping(%r%^spec/(.*)_spec.rb$%) {|filename, _| filename }
5
- at.add_mapping(%r%^lib/(.*).rb$%) {|_, match| "spec/#{match[1]}_spec.rb" }
6
- at.add_mapping(%r%^spec/spec_helper.rb$%) { at.files_matching(%r%^spec/(.*)_spec.rb$%) }
7
- end
data/FAQ.markdown DELETED
@@ -1,18 +0,0 @@
1
- Machinist FAQ
2
- =============
3
-
4
- ### My blueprint is giving me really weird errors. Any ideas?
5
-
6
- If your object has an attribute that happens to correspond to a Ruby standard function, it won't work properly in a blueprint.
7
-
8
- For example:
9
-
10
- OpeningHours.blueprint do
11
- open { Time.now }
12
- end
13
-
14
- This will result in Machinist attempting to run ruby's open command. To work around this use self.open instead.
15
-
16
- OpeningHours.blueprint do
17
- self.open { Time.now }
18
- end
data/init.rb DELETED
@@ -1,2 +0,0 @@
1
- require 'machinist' if RAILS_ENV == 'test'
2
-
@@ -1,25 +0,0 @@
1
- module Machinist
2
- # Include this in a class to allow defining blueprints for that class.
3
- module Blueprints
4
- def self.included(base)
5
- base.extend(ClassMethods)
6
- end
7
-
8
- module ClassMethods
9
- def blueprint(name = :master, &blueprint)
10
- @blueprints ||= {}
11
- @blueprints[name] = blueprint if block_given?
12
- @blueprints[name]
13
- end
14
-
15
- def named_blueprints
16
- @blueprints.reject{|name,_| name == :master }.keys
17
- end
18
-
19
- def clear_blueprints!
20
- @blueprints = {}
21
- end
22
- end
23
-
24
- end
25
- end
@@ -1,83 +0,0 @@
1
- require 'machinist'
2
- require 'machinist/blueprints'
3
- require 'dm-core'
4
-
5
- module Machinist
6
-
7
- class DataMapperAdapter
8
- def self.has_association?(object, attribute)
9
- object.class.relationships.has_key?(attribute)
10
- end
11
-
12
- def self.class_for_association(object, attribute)
13
- association = object.class.relationships[attribute]
14
- association && association.parent_model
15
- end
16
-
17
- def self.association_is_many_to_one?(association)
18
- if defined?(DataMapper::Associations::ManyToOne::Relationship)
19
- # We're using the next branch of DM
20
- association.class == DataMapper::Associations::ManyToOne::Relationship
21
- else
22
- # We're using the 0.9 or less branch.
23
- association.options[:max].nil?
24
- end
25
- end
26
-
27
- # This method takes care of converting any associated objects,
28
- # in the hash returned by Lathe#assigned_attributes, into their
29
- # object ids.
30
- #
31
- # For example, let's say we have blueprints like this:
32
- #
33
- # Post.blueprint { }
34
- # Comment.blueprint { post }
35
- #
36
- # Lathe#assigned_attributes will return { :post => ... }, but
37
- # we want to pass { :post_id => 1 } to a controller.
38
- #
39
- # This method takes care of cleaning this up.
40
- def self.assigned_attributes_without_associations(lathe)
41
- attributes = {}
42
- lathe.assigned_attributes.each_pair do |attribute, value|
43
- association = lathe.object.class.relationships[attribute]
44
- if association && association_is_many_to_one?(association)
45
- # DataMapper child_key can have more than one property, but I'm not
46
- # sure in what circumstances this would be the case. I'm assuming
47
- # here that there's only one property.
48
- key = association.child_key.map(&:field).first.to_sym
49
- attributes[key] = value.id
50
- else
51
- attributes[attribute] = value
52
- end
53
- end
54
- attributes
55
- end
56
- end
57
-
58
- module DataMapperExtensions
59
- def make(*args, &block)
60
- lathe = Lathe.run(Machinist::DataMapperAdapter, self.new, *args)
61
- unless Machinist.nerfed?
62
- lathe.object.save || raise("Save failed")
63
- lathe.object.reload
64
- end
65
- lathe.object(&block)
66
- end
67
-
68
- def make_unsaved(*args)
69
- object = Machinist.with_save_nerfed { make(*args) }
70
- yield object if block_given?
71
- object
72
- end
73
-
74
- def plan(*args)
75
- lathe = Lathe.run(Machinist::DataMapperAdapter, self.new, *args)
76
- Machinist::DataMapperAdapter.assigned_attributes_without_associations(lathe)
77
- end
78
- end
79
-
80
- end
81
-
82
- DataMapper::Model.append_extensions(Machinist::Blueprints::ClassMethods)
83
- DataMapper::Model.append_extensions(Machinist::DataMapperExtensions)
@@ -1,30 +0,0 @@
1
- require 'machinist'
2
- require 'machinist/blueprints'
3
-
4
- module Machinist
5
-
6
- module ObjectExtensions
7
- def self.included(base)
8
- base.extend(ClassMethods)
9
- end
10
-
11
- module ClassMethods
12
- def make(*args, &block)
13
- lathe = Lathe.run(Machinist::ObjectAdapter, self.new, *args)
14
- lathe.object(&block)
15
- end
16
- end
17
- end
18
-
19
- class ObjectAdapter
20
- def self.has_association?(object, attribute)
21
- false
22
- end
23
- end
24
-
25
- end
26
-
27
- class Object
28
- include Machinist::Blueprints
29
- include Machinist::ObjectExtensions
30
- end
@@ -1,62 +0,0 @@
1
- require 'machinist'
2
- require 'machinist/blueprints'
3
- require 'sequel'
4
-
5
- module Machinist
6
- class SequelAdapter
7
- def self.has_association?(object, attribute)
8
- object.class.associations.include?(attribute)
9
- end
10
-
11
- def self.class_for_association(object, attribute)
12
- object.class.association_reflection(attribute).associated_class
13
- end
14
-
15
- def self.assigned_attributes_without_associations(lathe)
16
- attributes = {}
17
- lathe.assigned_attributes.each_pair do |attribute, value|
18
- association = lathe.object.class.association_reflection(attribute)
19
- if association && association[:type] == :many_to_one
20
- key = association[:key] || association.default_key
21
- attributes[key] = value.send(association.primary_key)
22
- else
23
- attributes[attribute] = value
24
- end
25
- end
26
- attributes
27
- end
28
- end
29
-
30
- module SequelExtensions
31
- def self.included(base)
32
- base.extend(ClassMethods)
33
- end
34
-
35
- module ClassMethods
36
- def make(*args, &block)
37
- lathe = Lathe.run(Machinist::SequelAdapter, self.new, *args)
38
- unless Machinist.nerfed?
39
- lathe.object.save
40
- lathe.object.refresh
41
- end
42
- lathe.object(&block)
43
- end
44
-
45
- def make_unsaved(*args)
46
- returning(Machinist.with_save_nerfed { make(*args) }) do |object|
47
- yield object if block_given?
48
- end
49
- end
50
-
51
- def plan(*args)
52
- lathe = Lathe.run(Machinist::SequelAdapter, self.new, *args)
53
- Machinist::SequelAdapter.assigned_attributes_without_associations(lathe)
54
- end
55
- end
56
- end
57
- end
58
-
59
- class Sequel::Model
60
- include Machinist::Blueprints
61
- include Machinist::SequelExtensions
62
- end
data/lib/sham.rb DELETED
@@ -1,77 +0,0 @@
1
- class Sham
2
- @@shams = {}
3
-
4
- # Over-ride module's built-in name method, so we can re-use it for
5
- # generating names. This is a bit of a no-no, but we get away with
6
- # it in this context.
7
- def self.name(*args, &block)
8
- method_missing(:name, *args, &block)
9
- end
10
-
11
- def self.method_missing(symbol, *args, &block)
12
- if block_given?
13
- @@shams[symbol] = Sham.new(symbol, args.pop || {}, &block)
14
- else
15
- sham = @@shams[symbol]
16
- raise "No sham defined for #{symbol}" if sham.nil?
17
- sham.fetch_value
18
- end
19
- end
20
-
21
- def self.clear
22
- @@shams = {}
23
- end
24
-
25
- def self.reset(scope = :before_all)
26
- @@shams.values.each { |sham| sham.reset(scope) }
27
- end
28
-
29
- def self.define(&block)
30
- Sham.instance_eval(&block)
31
- end
32
-
33
- def initialize(name, options = {}, &block)
34
- @name = name
35
- @generator = block
36
- @offset = 0
37
- @unique = options.has_key?(:unique) ? options[:unique] : true
38
- generate_values(12)
39
- end
40
-
41
- def reset(scope)
42
- if scope == :before_all
43
- @offset, @before_offset = 0, nil
44
- elsif @before_offset
45
- @offset = @before_offset
46
- else
47
- @before_offset = @offset
48
- end
49
- end
50
-
51
- def fetch_value
52
- # Generate more values if we need them.
53
- if @offset >= @values.length
54
- generate_values(2 * @values.length)
55
- raise "Can't generate more unique values for Sham.#{@name}" if @offset >= @values.length
56
- end
57
- result = @values[@offset]
58
- @offset += 1
59
- result
60
- end
61
-
62
- private
63
-
64
- def generate_values(count)
65
- @values = seeded { (1..count).map(&@generator) }
66
- @values.uniq! if @unique
67
- end
68
-
69
- def seeded
70
- begin
71
- srand(1)
72
- yield
73
- ensure
74
- srand
75
- end
76
- end
77
- end