machinist_redux 3.0.0

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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +17 -0
  3. data/.gitignore +24 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +60 -0
  6. data/.rubocop_todo.yml +92 -0
  7. data/.travis.yml +23 -0
  8. data/Appraisals +11 -0
  9. data/Gemfile +32 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +307 -0
  12. data/Rakefile +20 -0
  13. data/gemfiles/rails_4.2.gemfile +38 -0
  14. data/gemfiles/rails_4.2.gemfile.lock +232 -0
  15. data/gemfiles/rails_5.0.gemfile +38 -0
  16. data/gemfiles/rails_5.0.gemfile.lock +232 -0
  17. data/gemfiles/rails_5.1.gemfile +34 -0
  18. data/gemfiles/rails_5.1.gemfile.lock +231 -0
  19. data/lib/generators/machinist/install/USAGE +2 -0
  20. data/lib/generators/machinist/install/install_generator.rb +46 -0
  21. data/lib/generators/machinist/install/templates/blueprints.rb +9 -0
  22. data/lib/generators/machinist/install/templates/machinist.rb.erb +7 -0
  23. data/lib/generators/machinist/model/model_generator.rb +11 -0
  24. data/lib/machinist.rb +5 -0
  25. data/lib/machinist/active_record.rb +14 -0
  26. data/lib/machinist/active_record/blueprint.rb +14 -0
  27. data/lib/machinist/active_record/lathe.rb +21 -0
  28. data/lib/machinist/blueprint.rb +84 -0
  29. data/lib/machinist/exceptions.rb +30 -0
  30. data/lib/machinist/lathe.rb +65 -0
  31. data/lib/machinist/machinable.rb +100 -0
  32. data/lib/machinist/version.rb +3 -0
  33. data/machinist.gemspec +23 -0
  34. data/spec/machinist/active_record_spec.rb +106 -0
  35. data/spec/machinist/blueprint_inheritance_spec.rb +101 -0
  36. data/spec/machinist/blueprint_spec.rb +76 -0
  37. data/spec/machinist/exceptions_spec.rb +16 -0
  38. data/spec/machinist/machinable_spec.rb +91 -0
  39. data/spec/spec_helper.rb +110 -0
  40. data/spec/support/active_record_environment.rb +62 -0
  41. metadata +94 -0
@@ -0,0 +1,34 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ ruby RUBY_VERSION
6
+
7
+ gem "activerecord", "~> 5.1.1", group: :test, require: false
8
+
9
+ group :development do
10
+ gem 'appraisal', require: false
11
+ gem 'gem-release', require: false
12
+ gem 'github_changelog_generator', require: false
13
+ gem 'guard', require: false
14
+ gem 'guard-rspec', require: false
15
+ gem 'guard-rubocop', require: false
16
+ gem 'guard-rubycritic', require: false
17
+ gem 'rdoc', require: false
18
+ gem 'rubocop-rspec', require: false
19
+ end
20
+
21
+ group :test do
22
+ gem "codeclimate-test-reporter", require: false
23
+ gem "coveralls", require: false
24
+ gem "fuubar", require: false
25
+ gem "rspec", require: false
26
+ gem "rspec_junit_formatter", require: false
27
+ gem "simplecov", "~> 0.14", require: false
28
+ end
29
+
30
+ platforms :ruby do
31
+ gem "sqlite3"
32
+ end
33
+
34
+ gemspec path: "../"
@@ -0,0 +1,231 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ machinist_redux (3.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ activemodel (5.1.1)
10
+ activesupport (= 5.1.1)
11
+ activerecord (5.1.1)
12
+ activemodel (= 5.1.1)
13
+ activesupport (= 5.1.1)
14
+ arel (~> 8.0)
15
+ activesupport (5.1.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (~> 0.7)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ addressable (2.5.1)
21
+ public_suffix (~> 2.0, >= 2.0.2)
22
+ appraisal (2.2.0)
23
+ bundler
24
+ rake
25
+ thor (>= 0.14.0)
26
+ arel (8.0.0)
27
+ ast (2.3.0)
28
+ axiom-types (0.1.1)
29
+ descendants_tracker (~> 0.0.4)
30
+ ice_nine (~> 0.11.0)
31
+ thread_safe (~> 0.3, >= 0.3.1)
32
+ builder (3.2.3)
33
+ codeclimate-engine-rb (0.4.0)
34
+ virtus (~> 1.0)
35
+ codeclimate-test-reporter (1.0.7)
36
+ simplecov
37
+ coderay (1.1.1)
38
+ coercible (1.0.0)
39
+ descendants_tracker (~> 0.0.1)
40
+ concurrent-ruby (1.0.5)
41
+ coveralls (0.8.21)
42
+ json (>= 1.8, < 3)
43
+ simplecov (~> 0.14.1)
44
+ term-ansicolor (~> 1.3)
45
+ thor (~> 0.19.4)
46
+ tins (~> 1.6)
47
+ descendants_tracker (0.0.4)
48
+ thread_safe (~> 0.3, >= 0.3.1)
49
+ diff-lcs (1.3)
50
+ docile (1.1.5)
51
+ equalizer (0.0.11)
52
+ erubis (2.7.0)
53
+ faraday (0.12.1)
54
+ multipart-post (>= 1.2, < 3)
55
+ faraday-http-cache (2.0.0)
56
+ faraday (~> 0.8)
57
+ ffi (1.9.18)
58
+ flay (2.9.0)
59
+ erubis (~> 2.7.0)
60
+ path_expander (~> 1.0)
61
+ ruby_parser (~> 3.0)
62
+ sexp_processor (~> 4.0)
63
+ flog (4.6.1)
64
+ path_expander (~> 1.0)
65
+ ruby_parser (~> 3.1, > 3.1.0)
66
+ sexp_processor (~> 4.8)
67
+ formatador (0.2.5)
68
+ fuubar (2.2.0)
69
+ rspec-core (~> 3.0)
70
+ ruby-progressbar (~> 1.4)
71
+ gem-release (1.0.0)
72
+ github_changelog_generator (1.14.3)
73
+ activesupport
74
+ faraday-http-cache
75
+ multi_json
76
+ octokit (~> 4.6)
77
+ rainbow (>= 2.1)
78
+ rake (>= 10.0)
79
+ retriable (~> 2.1)
80
+ guard (2.14.1)
81
+ formatador (>= 0.2.4)
82
+ listen (>= 2.7, < 4.0)
83
+ lumberjack (~> 1.0)
84
+ nenv (~> 0.1)
85
+ notiffany (~> 0.0)
86
+ pry (>= 0.9.12)
87
+ shellany (~> 0.0)
88
+ thor (>= 0.18.1)
89
+ guard-compat (1.2.1)
90
+ guard-rspec (4.7.3)
91
+ guard (~> 2.1)
92
+ guard-compat (~> 1.1)
93
+ rspec (>= 2.99.0, < 4.0)
94
+ guard-rubocop (1.2.0)
95
+ guard (~> 2.0)
96
+ rubocop (~> 0.20)
97
+ guard-rubycritic (2.9.3)
98
+ guard (~> 2.6)
99
+ rubycritic (>= 2.9.3)
100
+ i18n (0.8.1)
101
+ ice_nine (0.11.2)
102
+ json (2.1.0)
103
+ launchy (2.4.3)
104
+ addressable (~> 2.3)
105
+ listen (3.1.5)
106
+ rb-fsevent (~> 0.9, >= 0.9.4)
107
+ rb-inotify (~> 0.9, >= 0.9.7)
108
+ ruby_dep (~> 1.2)
109
+ lumberjack (1.0.12)
110
+ method_source (0.8.2)
111
+ minitest (5.10.2)
112
+ multi_json (1.12.1)
113
+ multipart-post (2.0.0)
114
+ nenv (0.3.0)
115
+ notiffany (0.1.1)
116
+ nenv (~> 0.1)
117
+ shellany (~> 0.0)
118
+ octokit (4.7.0)
119
+ sawyer (~> 0.8.0, >= 0.5.3)
120
+ parser (2.4.0.0)
121
+ ast (~> 2.2)
122
+ path_expander (1.0.2)
123
+ powerpack (0.1.1)
124
+ pry (0.10.4)
125
+ coderay (~> 1.1.0)
126
+ method_source (~> 0.8.1)
127
+ slop (~> 3.4)
128
+ public_suffix (2.0.5)
129
+ rainbow (2.2.2)
130
+ rake
131
+ rake (12.0.0)
132
+ rb-fsevent (0.9.8)
133
+ rb-inotify (0.9.8)
134
+ ffi (>= 0.5.0)
135
+ rdoc (5.1.0)
136
+ reek (4.6.2)
137
+ codeclimate-engine-rb (~> 0.4.0)
138
+ parser (>= 2.4.0.0, < 2.5)
139
+ rainbow (~> 2.0)
140
+ retriable (2.1.0)
141
+ rspec (3.6.0)
142
+ rspec-core (~> 3.6.0)
143
+ rspec-expectations (~> 3.6.0)
144
+ rspec-mocks (~> 3.6.0)
145
+ rspec-core (3.6.0)
146
+ rspec-support (~> 3.6.0)
147
+ rspec-expectations (3.6.0)
148
+ diff-lcs (>= 1.2.0, < 2.0)
149
+ rspec-support (~> 3.6.0)
150
+ rspec-mocks (3.6.0)
151
+ diff-lcs (>= 1.2.0, < 2.0)
152
+ rspec-support (~> 3.6.0)
153
+ rspec-support (3.6.0)
154
+ rspec_junit_formatter (0.2.3)
155
+ builder (< 4)
156
+ rspec-core (>= 2, < 4, != 2.12.0)
157
+ rubocop (0.48.1)
158
+ parser (>= 2.3.3.1, < 3.0)
159
+ powerpack (~> 0.1)
160
+ rainbow (>= 1.99.1, < 3.0)
161
+ ruby-progressbar (~> 1.7)
162
+ unicode-display_width (~> 1.0, >= 1.0.1)
163
+ rubocop-rspec (1.15.1)
164
+ rubocop (>= 0.42.0)
165
+ ruby-progressbar (1.8.1)
166
+ ruby_dep (1.5.0)
167
+ ruby_parser (3.9.0)
168
+ sexp_processor (~> 4.1)
169
+ rubycritic (3.2.1)
170
+ flay (~> 2.8)
171
+ flog (~> 4.4)
172
+ launchy (= 2.4.3)
173
+ parser (= 2.4.0)
174
+ rainbow (~> 2.1)
175
+ reek (~> 4.4)
176
+ ruby_parser (~> 3.8)
177
+ virtus (~> 1.0)
178
+ sawyer (0.8.1)
179
+ addressable (>= 2.3.5, < 2.6)
180
+ faraday (~> 0.8, < 1.0)
181
+ sexp_processor (4.9.0)
182
+ shellany (0.0.1)
183
+ simplecov (0.14.1)
184
+ docile (~> 1.1.0)
185
+ json (>= 1.8, < 3)
186
+ simplecov-html (~> 0.10.0)
187
+ simplecov-html (0.10.0)
188
+ slop (3.6.0)
189
+ sqlite3 (1.3.13)
190
+ term-ansicolor (1.6.0)
191
+ tins (~> 1.0)
192
+ thor (0.19.4)
193
+ thread_safe (0.3.6)
194
+ tins (1.14.0)
195
+ tzinfo (1.2.3)
196
+ thread_safe (~> 0.1)
197
+ unicode-display_width (1.2.1)
198
+ virtus (1.0.5)
199
+ axiom-types (~> 0.1)
200
+ coercible (~> 1.0)
201
+ descendants_tracker (~> 0.0, >= 0.0.3)
202
+ equalizer (~> 0.0, >= 0.0.9)
203
+
204
+ PLATFORMS
205
+ ruby
206
+
207
+ DEPENDENCIES
208
+ activerecord (~> 5.1.1)
209
+ appraisal
210
+ codeclimate-test-reporter
211
+ coveralls
212
+ fuubar
213
+ gem-release
214
+ github_changelog_generator
215
+ guard
216
+ guard-rspec
217
+ guard-rubocop
218
+ guard-rubycritic
219
+ machinist_redux!
220
+ rdoc
221
+ rspec
222
+ rspec_junit_formatter
223
+ rubocop-rspec
224
+ simplecov (~> 0.14)
225
+ sqlite3
226
+
227
+ RUBY VERSION
228
+ ruby 2.3.4p301
229
+
230
+ BUNDLED WITH
231
+ 1.14.6
@@ -0,0 +1,2 @@
1
+ Description:
2
+ Copy Machinist files to your application.
@@ -0,0 +1,46 @@
1
+ module Machinist
2
+ module Generators #:nodoc:
3
+ class InstallGenerator < Rails::Generators::Base #:nodoc:
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ class_option :test_framework, type: :string, aliases: '-t', desc: 'Test framework to use Machinist with'
7
+ class_option :cucumber, type: :boolean, desc: 'Set up access to Machinist from Cucumber'
8
+
9
+ def blueprints_file
10
+ if rspec?
11
+ copy_file 'blueprints.rb', 'spec/support/blueprints.rb'
12
+ else
13
+ copy_file 'blueprints.rb', 'test/blueprints.rb'
14
+ end
15
+ end
16
+
17
+ def test_helper
18
+ if test_unit?
19
+ inject_into_file('test/test_helper.rb', after: "require 'rails/test_help'\n") do
20
+ "require File.expand_path(File.dirname(__FILE__) + '/blueprints')\n"
21
+ end
22
+ end
23
+ end
24
+
25
+ def cucumber_support
26
+ if cucumber?
27
+ template 'machinist.rb.erb', 'features/support/machinist.rb'
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def rspec?
34
+ options[:test_framework].to_sym == :rspec
35
+ end
36
+
37
+ def test_unit?
38
+ options[:test_framework].to_sym == :test_unit
39
+ end
40
+
41
+ def cucumber?
42
+ options[:cucumber]
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ require 'machinist/active_record'
2
+
3
+ # Add your blueprints here.
4
+ #
5
+ # e.g.
6
+ # Post.blueprint do
7
+ # title { "Post #{sn}" }
8
+ # body { "Lorem ipsum..." }
9
+ # end
@@ -0,0 +1,7 @@
1
+ <%- if rspec? -%>
2
+ # Load the blueprints from over in spec support.
3
+ require "#{Rails.root}/spec/support/blueprints"
4
+ <%- else -%>
5
+ # Load the blueprints from over in test.
6
+ require "#{Rails.root}/test/blueprints"
7
+ <%- end -%>
@@ -0,0 +1,11 @@
1
+ module Machinist
2
+ module Generators #:nodoc:
3
+ class ModelGenerator < Rails::Generators::NamedBase #:nodoc:
4
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
5
+
6
+ def create_blueprint
7
+ append_file 'spec/support/blueprints.rb', "\n#{class_name}.blueprint do\n # Attributes here\nend\n"
8
+ end
9
+ end
10
+ end
11
+ end
data/lib/machinist.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'machinist/version'
2
+ require 'machinist/blueprint'
3
+ require 'machinist/exceptions'
4
+ require 'machinist/lathe'
5
+ require 'machinist/machinable'
@@ -0,0 +1,14 @@
1
+ require 'active_record'
2
+ require 'machinist'
3
+ require 'machinist/active_record/blueprint'
4
+ require 'machinist/active_record/lathe'
5
+
6
+ module ActiveRecord #:nodoc:
7
+ class Base #:nodoc:
8
+ extend Machinist::Machinable
9
+
10
+ def self.blueprint_class
11
+ Machinist::ActiveRecord::Blueprint
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Machinist::ActiveRecord
2
+ class Blueprint < Machinist::Blueprint
3
+ # Make and save an object.
4
+ def make!(attributes = {})
5
+ object = make(attributes)
6
+ object.save!
7
+ object.reload
8
+ end
9
+
10
+ def lathe_class #:nodoc:
11
+ Machinist::ActiveRecord::Lathe
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module Machinist::ActiveRecord
2
+ class Lathe < Machinist::Lathe
3
+ def make_one_value(attribute, args) #:nodoc:
4
+ if block_given?
5
+ raise_argument_error(attribute) unless args.empty?
6
+ yield
7
+ else
8
+ make_association(attribute, args)
9
+ end
10
+ end
11
+
12
+ def make_association(attribute, args) #:nodoc:
13
+ association = @klass.reflect_on_association(attribute)
14
+ if association
15
+ association.klass.make(*args)
16
+ else
17
+ raise_argument_error(attribute)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,84 @@
1
+ module Machinist
2
+ # A Blueprint defines a method of constructing objects of a particular class.
3
+ class Blueprint
4
+ # Construct a blueprint for the given +klass+.
5
+ #
6
+ # Pass in the +:parent+ option to define a parent blueprint to apply after
7
+ # this one. You can supply another blueprint, or a class in which to look
8
+ # for a blueprint. In the latter case, make will walk up the superclass
9
+ # chain looking for blueprints to apply.
10
+ def initialize(klass, options = {}, &block)
11
+ @klass = klass
12
+ @parent = options[:parent]
13
+ @block = block
14
+ end
15
+
16
+ attr_reader :klass, :parent, :block
17
+
18
+ # Generate an object from this blueprint.
19
+ #
20
+ # Pass in attributes to override values defined in the blueprint.
21
+ def make(attributes = {})
22
+ lathe = lathe_class.new(@klass, new_serial_number, attributes)
23
+
24
+ lathe.instance_eval(&@block)
25
+ each_ancestor { |blueprint| lathe.instance_eval(&blueprint.block) }
26
+
27
+ lathe.object
28
+ end
29
+
30
+ # Returns the Lathe class used to make objects for this blueprint.
31
+ #
32
+ # Subclasses can override this to substitute a custom lathe class.
33
+ def lathe_class
34
+ Lathe
35
+ end
36
+
37
+ # Returns the parent blueprint for this blueprint.
38
+ def parent_blueprint
39
+ case @parent
40
+ when nil
41
+ nil
42
+ when Blueprint
43
+ # @parent references the parent blueprint directly.
44
+ @parent
45
+ else
46
+ # @parent is a class in which we should look for a blueprint.
47
+ find_blueprint_in_superclass_chain(@parent)
48
+ end
49
+ end
50
+
51
+ # Yields the parent blueprint, its parent blueprint, etc.
52
+ def each_ancestor
53
+ ancestor = parent_blueprint
54
+ while ancestor
55
+ yield ancestor
56
+ ancestor = ancestor.parent_blueprint
57
+ end
58
+ end
59
+
60
+ protected
61
+
62
+ def new_serial_number #:nodoc:
63
+ parent_blueprint = self.parent_blueprint # Cache this for speed.
64
+ if parent_blueprint
65
+ parent_blueprint.new_serial_number
66
+ else
67
+ @serial_number ||= 0
68
+ @serial_number += 1
69
+ sprintf('%04d', @serial_number)
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def find_blueprint_in_superclass_chain(klass)
76
+ klass = klass.superclass until has_blueprint?(klass) || klass.nil?
77
+ klass && klass.blueprint
78
+ end
79
+
80
+ def has_blueprint?(klass)
81
+ klass.respond_to?(:blueprint) && !klass.blueprint.nil?
82
+ end
83
+ end
84
+ end