whiteprint 0.1.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.
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+
3
+ if ActiveSupport::TestCase.respond_to?(:test_order=)
4
+ # TODO: remove check once ActiveSupport dependency is at least 4.2
5
+ ActiveSupport::TestCase.test_order = :random
6
+ end
7
+
8
+ class MigratorTest < ActiveSupport::TestCase
9
+ def setup
10
+ Whiteprint.config do |c|
11
+ c.eager_load = true
12
+ c.eager_load_paths += ['models/**/*.rb']
13
+ c.migration_path = File.expand_path('../../db/migrate', __FILE__)
14
+ end
15
+ end
16
+
17
+ test 'models can be eager loaded by whiteprint' do
18
+ Object.send :remove_const, :Car
19
+ Object.send :remove_const, :User
20
+
21
+ Whiteprint.models = []
22
+
23
+ assert_raises(NameError) { Car }
24
+ assert_raises(NameError) { User }
25
+
26
+ Whiteprint::Migrator.eager_load!
27
+
28
+ assert_includes Whiteprint.models, Car
29
+ assert_includes Whiteprint.models, User
30
+ end
31
+
32
+ test 'whiteprint can write all changes to migration' do
33
+ expected_migration = <<-RUBY
34
+ class TestMigration < ActiveRecord::Migration
35
+ def change
36
+ create_table :cars do |t|
37
+ t.string :brand, {:default=>"BMW"}
38
+ t.decimal :price, {:precision=>5, :scale=>10}
39
+ t.timestamps
40
+ end
41
+
42
+ change_table :users do |t|
43
+ t.change :name, :string, {:default=>"Joe"}
44
+ t.change :age, :integer, {:default=>10}
45
+ t.remove :date_of_birth
46
+ end
47
+ end
48
+ end
49
+ RUBY
50
+
51
+ input = StringIO.new
52
+ input << '1' << "\n"
53
+ input.rewind
54
+
55
+ migrate_input = StringIO.new
56
+ migrate_input << 'test migration' << "\n"
57
+ migrate_input.rewind
58
+
59
+ Whiteprint::Migrator.interactive input: input, migrate_input: migrate_input
60
+
61
+ migration = File.read(Dir.glob('test/db/migrate/*_test_migration.rb').first)
62
+
63
+ assert_equal expected_migration, migration
64
+ end
65
+
66
+ def teardown
67
+ path = Dir.glob('test/db/migrate/*_test_migration.rb').first
68
+ File.delete(path) if path
69
+ end
70
+ end
@@ -0,0 +1,8 @@
1
+ class Car < ActiveRecord::Base
2
+ has_whiteprint
3
+
4
+ whiteprint do
5
+ string :brand, default: 'BMW'
6
+ decimal :price, precision: 5, scale: 10
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class User < ActiveRecord::Base
2
+ include Whiteprint::Model
3
+
4
+ whiteprint do
5
+ string :name, default: 'Joe'
6
+ integer :age, default: 10
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ ActiveRecord::Schema.define do
2
+ self.verbose = false
3
+
4
+ create_table :users, force: true do |t|
5
+ t.string :name, default: 'John'
6
+ t.integer :age, default: 0
7
+ t.date :date_of_birth
8
+
9
+ t.timestamps null: true
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ # require 'minitest/autorun'
4
+ require 'simplecov'
5
+ require 'bundler/setup'
6
+ require 'active_support'
7
+ require 'active_support/testing/autorun'
8
+
9
+ require 'active_record'
10
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
11
+ require 'schema'
12
+
13
+ require 'whiteprint'
14
+
15
+ require 'models/user'
16
+ require 'models/car'
17
+
18
+ if ActiveSupport::TestCase.respond_to?(:test_order=)
19
+ # TODO: remove check once ActiveSupport dependency is at least 4.2
20
+ ActiveSupport::TestCase.test_order = :random
21
+ end
@@ -0,0 +1,142 @@
1
+ module ActiveSupport
2
+ # A typical module looks like this:
3
+ #
4
+ # module M
5
+ # def self.included(base)
6
+ # base.extend ClassMethods
7
+ # base.class_eval do
8
+ # scope :disabled, -> { where(disabled: true) }
9
+ # end
10
+ # end
11
+ #
12
+ # module ClassMethods
13
+ # ...
14
+ # end
15
+ # end
16
+ #
17
+ # By using <tt>ActiveSupport::Concern</tt> the above module could instead be
18
+ # written as:
19
+ #
20
+ # require 'active_support/concern'
21
+ #
22
+ # module M
23
+ # extend ActiveSupport::Concern
24
+ #
25
+ # included do
26
+ # scope :disabled, -> { where(disabled: true) }
27
+ # end
28
+ #
29
+ # class_methods do
30
+ # ...
31
+ # end
32
+ # end
33
+ #
34
+ # Moreover, it gracefully handles module dependencies. Given a +Foo+ module
35
+ # and a +Bar+ module which depends on the former, we would typically write the
36
+ # following:
37
+ #
38
+ # module Foo
39
+ # def self.included(base)
40
+ # base.class_eval do
41
+ # def self.method_injected_by_foo
42
+ # ...
43
+ # end
44
+ # end
45
+ # end
46
+ # end
47
+ #
48
+ # module Bar
49
+ # def self.included(base)
50
+ # base.method_injected_by_foo
51
+ # end
52
+ # end
53
+ #
54
+ # class Host
55
+ # include Foo # We need to include this dependency for Bar
56
+ # include Bar # Bar is the module that Host really needs
57
+ # end
58
+ #
59
+ # But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
60
+ # could try to hide these from +Host+ directly including +Foo+ in +Bar+:
61
+ #
62
+ # module Bar
63
+ # include Foo
64
+ # def self.included(base)
65
+ # base.method_injected_by_foo
66
+ # end
67
+ # end
68
+ #
69
+ # class Host
70
+ # include Bar
71
+ # end
72
+ #
73
+ # Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
74
+ # is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
75
+ # module dependencies are properly resolved:
76
+ #
77
+ # require 'active_support/concern'
78
+ #
79
+ # module Foo
80
+ # extend ActiveSupport::Concern
81
+ # included do
82
+ # def self.method_injected_by_foo
83
+ # ...
84
+ # end
85
+ # end
86
+ # end
87
+ #
88
+ # module Bar
89
+ # extend ActiveSupport::Concern
90
+ # include Foo
91
+ #
92
+ # included do
93
+ # self.method_injected_by_foo
94
+ # end
95
+ # end
96
+ #
97
+ # class Host
98
+ # include Bar # It works, now Bar takes care of its dependencies
99
+ # end
100
+ module Concern
101
+ class MultipleIncludedBlocks < StandardError #:nodoc:
102
+ def initialize
103
+ super "Cannot define multiple 'included' blocks for a Concern"
104
+ end
105
+ end
106
+
107
+ def self.extended(base) #:nodoc:
108
+ base.instance_variable_set(:@_dependencies, [])
109
+ end
110
+
111
+ def append_features(base)
112
+ if base.instance_variable_defined?(:@_dependencies)
113
+ base.instance_variable_get(:@_dependencies) << self
114
+ return false
115
+ else
116
+ return false if base < self
117
+ @_dependencies.each { |dep| base.send(:include, dep) }
118
+ super
119
+ base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods)
120
+ base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block)
121
+ end
122
+ end
123
+
124
+ def included(base = nil, &block)
125
+ if base.nil?
126
+ raise MultipleIncludedBlocks if instance_variable_defined?(:@_included_block)
127
+
128
+ @_included_block = block
129
+ else
130
+ super
131
+ end
132
+ end
133
+
134
+ def class_methods(&class_methods_module_definition)
135
+ mod = const_defined?(:ClassMethods, false) ?
136
+ const_get(:ClassMethods) :
137
+ const_set(:ClassMethods, Module.new)
138
+
139
+ mod.module_eval(&class_methods_module_definition)
140
+ end
141
+ end
142
+ end
metadata ADDED
@@ -0,0 +1,270 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: whiteprint
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ewout Kleinsmann
8
+ - Roland Boon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-09-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: parslet
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.7'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.7'
28
+ - !ruby/object:Gem::Dependency
29
+ name: terminal-table
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.4'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.4'
42
+ - !ruby/object:Gem::Dependency
43
+ name: highline
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '1.7'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '1.7'
56
+ - !ruby/object:Gem::Dependency
57
+ name: bundler
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.9'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.9'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '10.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '10.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: activesupport
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '4.2'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '4.2'
98
+ - !ruby/object:Gem::Dependency
99
+ name: activerecord
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '4.2'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '4.2'
112
+ - !ruby/object:Gem::Dependency
113
+ name: sqlite3
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: flay
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: flog
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: brakeman
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ - !ruby/object:Gem::Dependency
169
+ name: rubocop
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ - !ruby/object:Gem::Dependency
183
+ name: simplecov
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ description: |2
197
+ Whiteprint allows you to define attributes within your models. This definition allows for
198
+ automatic migration generation. You can also use whiteprint for inheritance and composition
199
+ of your model's attributes.
200
+ email: info@10kb.nl
201
+ executables: []
202
+ extensions: []
203
+ extra_rdoc_files: []
204
+ files:
205
+ - README.md
206
+ - Rakefile
207
+ - lib/tasks/blueprint.rake
208
+ - lib/whiteprint.rb
209
+ - lib/whiteprint/adapters/active_record.rb
210
+ - lib/whiteprint/adapters/active_record/has_and_belongs_to_many.rb
211
+ - lib/whiteprint/adapters/active_record/migration.rb
212
+ - lib/whiteprint/adapters/test.rb
213
+ - lib/whiteprint/attributes.rb
214
+ - lib/whiteprint/base.rb
215
+ - lib/whiteprint/config.rb
216
+ - lib/whiteprint/explanation.rb
217
+ - lib/whiteprint/has_whiteprint.rb
218
+ - lib/whiteprint/migrator.rb
219
+ - lib/whiteprint/model.rb
220
+ - lib/whiteprint/railtie.rb
221
+ - lib/whiteprint/transform.rb
222
+ - lib/whiteprint/version.rb
223
+ - test/cases/active_record_test.rb
224
+ - test/cases/attributes_test.rb
225
+ - test/cases/blueprint_test.rb
226
+ - test/cases/changes_tree_test.rb
227
+ - test/cases/explanation_test.rb
228
+ - test/cases/migrator_test.rb
229
+ - test/models/car.rb
230
+ - test/models/user.rb
231
+ - test/schema.rb
232
+ - test/test_helper.rb
233
+ - vendor/active_support/concern.rb
234
+ homepage: http://10kb.nl/
235
+ licenses:
236
+ - MIT
237
+ metadata: {}
238
+ post_install_message:
239
+ rdoc_options: []
240
+ require_paths:
241
+ - lib
242
+ - vendor
243
+ required_ruby_version: !ruby/object:Gem::Requirement
244
+ requirements:
245
+ - - ">="
246
+ - !ruby/object:Gem::Version
247
+ version: '0'
248
+ required_rubygems_version: !ruby/object:Gem::Requirement
249
+ requirements:
250
+ - - ">="
251
+ - !ruby/object:Gem::Version
252
+ version: '0'
253
+ requirements: []
254
+ rubyforge_project:
255
+ rubygems_version: 2.4.5
256
+ signing_key:
257
+ specification_version: 4
258
+ summary: Define attributes within models for automatic migration generators, schema
259
+ composition and more
260
+ test_files:
261
+ - test/cases/attributes_test.rb
262
+ - test/cases/blueprint_test.rb
263
+ - test/cases/explanation_test.rb
264
+ - test/cases/active_record_test.rb
265
+ - test/cases/migrator_test.rb
266
+ - test/cases/changes_tree_test.rb
267
+ - test/test_helper.rb
268
+ - test/models/user.rb
269
+ - test/models/car.rb
270
+ - test/schema.rb