ardb 0.28.3 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -7
  2. data/.l.yml +9 -0
  3. data/.rubocop.yml +3 -0
  4. data/.ruby-version +1 -0
  5. data/.t.yml +6 -0
  6. data/Gemfile +24 -8
  7. data/README.md +252 -3
  8. data/ardb.gemspec +14 -10
  9. data/bin/ardb +3 -1
  10. data/lib/ardb/adapter/base.rb +72 -47
  11. data/lib/ardb/adapter/mysql.rb +4 -17
  12. data/lib/ardb/adapter/postgresql.rb +51 -46
  13. data/lib/ardb/adapter/sqlite.rb +11 -15
  14. data/lib/ardb/adapter_spy.rb +18 -30
  15. data/lib/ardb/cli/clirb.rb +16 -18
  16. data/lib/ardb/cli/commands.rb +308 -129
  17. data/lib/ardb/cli.rb +29 -24
  18. data/lib/ardb/db_tests.rb +4 -4
  19. data/lib/ardb/default_order_by.rb +13 -21
  20. data/lib/ardb/migration.rb +15 -16
  21. data/lib/ardb/record_spy.rb +46 -61
  22. data/lib/ardb/relation_spy.rb +28 -32
  23. data/lib/ardb/require_autoloaded_active_record_files.rb +258 -57
  24. data/lib/ardb/test_helpers.rb +33 -29
  25. data/lib/ardb/use_db_default.rb +13 -21
  26. data/lib/ardb/version.rb +3 -1
  27. data/lib/ardb.rb +105 -86
  28. data/script/determine_autoloaded_active_record_files.rb +31 -24
  29. data/test/helper.rb +6 -13
  30. data/test/support/factory.rb +4 -3
  31. data/test/support/fake_schema.rb +3 -1
  32. data/test/support/postgresql/migrations/{.gitkeep → .keep} +0 -0
  33. data/test/support/postgresql/schema.rb +2 -1
  34. data/test/support/postgresql/setup_test_db.rb +23 -21
  35. data/test/support/relative_require_test_db_file.rb +1 -0
  36. data/test/support/require_test_db_file.rb +1 -0
  37. data/test/system/.keep +0 -0
  38. data/test/unit/adapter/base_tests.rb +80 -55
  39. data/test/unit/adapter/mysql_tests.rb +4 -19
  40. data/test/unit/adapter/postgresql_tests.rb +21 -30
  41. data/test/unit/adapter/sqlite_tests.rb +5 -11
  42. data/test/unit/adapter_spy_tests.rb +6 -17
  43. data/test/unit/ardb_tests.rb +75 -53
  44. data/test/unit/cli_tests.rb +234 -158
  45. data/test/unit/db_tests_tests.rb +7 -7
  46. data/test/unit/default_order_by_tests.rb +26 -24
  47. data/test/unit/migration_tests.rb +17 -18
  48. data/test/unit/record_spy_tests.rb +45 -41
  49. data/test/unit/relation_spy_tests.rb +40 -63
  50. data/test/unit/test_helpers_tests.rb +7 -15
  51. data/test/unit/use_db_default_tests.rb +35 -27
  52. metadata +109 -87
  53. data/lib/ardb/has_slug.rb +0 -107
  54. data/lib/ardb/migration_helpers.rb +0 -77
  55. data/lib/ardb/pg_json.rb +0 -90
  56. data/test/support/postgresql/pg_json_migrations/20160519133432_create_pg_json_migrate_test.rb +0 -13
  57. data/test/system/pg_json_tests.rb +0 -85
  58. data/test/unit/has_slug_tests.rb +0 -341
  59. data/test/unit/migration_helpers_tests.rb +0 -65
  60. data/test/unit/pg_json_tests.rb +0 -39
@@ -1,69 +1,270 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # ActiveRecord makes use of autoload to load some of its components as-needed.
2
- # This doesn't work well with threaded environments, and causes uninitialized
4
+ # This doesn"t work well with threaded environments, and causes uninitialized
3
5
  # constants. To avoid this, this file manually requires the following files that
4
- # are not required using `require 'active_record'`. Trying to automatically
6
+ # are not required using `require "active_record"`. Trying to automatically
5
7
  # require every file in ActiveRecord is slow and inefficient. Many of the files
6
- # fail to require and there are some we don't want to require. Thus, this is a
8
+ # fail to require and there are some we don"t want to require. Thus, this is a
7
9
  # manual list of requires.
8
10
 
9
11
  # To re-build this list of requires, run the following:
10
12
  # bundle exec ruby script/determine_autoloaded_active_record_files.rb
11
13
 
12
14
  # For compatibility, we require active record first
13
- require 'active_record'
15
+ require "active_record"
14
16
 
15
- require 'active_record/aggregations'
16
- require 'active_record/associations'
17
- require 'active_record/associations/alias_tracker'
18
- require 'active_record/associations/association'
19
- require 'active_record/associations/association_scope'
20
- require 'active_record/associations/belongs_to_association'
21
- require 'active_record/associations/belongs_to_polymorphic_association'
22
- require 'active_record/associations/builder/association'
23
- require 'active_record/associations/builder/belongs_to'
24
- require 'active_record/associations/builder/collection_association'
25
- require 'active_record/associations/builder/has_and_belongs_to_many'
26
- require 'active_record/associations/builder/has_many'
27
- require 'active_record/associations/builder/has_one'
28
- require 'active_record/associations/collection_association'
29
- require 'active_record/associations/collection_proxy'
30
- require 'active_record/associations/has_and_belongs_to_many_association'
31
- require 'active_record/associations/has_many_association'
32
- require 'active_record/associations/has_many_through_association'
33
- require 'active_record/associations/has_one_association'
34
- require 'active_record/associations/has_one_through_association'
35
- require 'active_record/associations/join_dependency'
36
- require 'active_record/associations/join_dependency/join_association'
37
- require 'active_record/associations/join_dependency/join_base'
38
- require 'active_record/associations/preloader'
39
- require 'active_record/associations/preloader/association'
40
- require 'active_record/associations/preloader/belongs_to'
41
- require 'active_record/associations/preloader/collection_association'
42
- require 'active_record/associations/preloader/has_and_belongs_to_many'
43
- require 'active_record/associations/preloader/has_many'
44
- require 'active_record/associations/preloader/has_many_through'
45
- require 'active_record/associations/preloader/has_one'
46
- require 'active_record/associations/preloader/has_one_through'
47
- require 'active_record/attribute_assignment'
48
- require 'active_record/attribute_methods/before_type_cast'
49
- require 'active_record/attribute_methods/deprecated_underscore_read'
50
- require 'active_record/attribute_methods/dirty'
51
- require 'active_record/attribute_methods/primary_key'
52
- require 'active_record/attribute_methods/query'
53
- require 'active_record/attribute_methods/read'
54
- require 'active_record/attribute_methods/serialization'
55
- require 'active_record/attribute_methods/time_zone_conversion'
56
- require 'active_record/autosave_association'
57
- require 'active_record/base'
58
- require 'active_record/dynamic_finder_match'
59
- require 'active_record/dynamic_scope_match'
60
- require 'active_record/observer'
61
- require 'active_record/relation'
62
- require 'active_record/relation/predicate_builder'
63
- require 'active_record/result'
17
+ if (
18
+ ActiveRecord.version.segments[0] == 7 &&
19
+ ActiveRecord.version.segments[1] >= 0
20
+ )
21
+ require "active_record/aggregations"
22
+ require "active_record/association_relation"
23
+ require "active_record/associations"
24
+ require "active_record/associations/alias_tracker"
25
+ require "active_record/associations/association"
26
+ require "active_record/associations/association_scope"
27
+ require "active_record/associations/belongs_to_association"
28
+ require "active_record/associations/belongs_to_polymorphic_association"
29
+ require "active_record/associations/builder/association"
30
+ require "active_record/associations/builder/belongs_to"
31
+ require "active_record/associations/builder/collection_association"
32
+ require "active_record/associations/builder/has_and_belongs_to_many"
33
+ require "active_record/associations/builder/has_many"
34
+ require "active_record/associations/builder/has_one"
35
+ require "active_record/associations/collection_association"
36
+ require "active_record/associations/collection_proxy"
37
+ require "active_record/associations/disable_joins_association_scope"
38
+ require "active_record/associations/foreign_association"
39
+ require "active_record/associations/has_many_association"
40
+ require "active_record/associations/has_many_through_association"
41
+ require "active_record/associations/has_one_association"
42
+ require "active_record/associations/has_one_through_association"
43
+ require "active_record/associations/join_dependency"
44
+ require "active_record/associations/join_dependency/join_association"
45
+ require "active_record/associations/join_dependency/join_base"
46
+ require "active_record/associations/preloader"
47
+ require "active_record/associations/preloader/association"
48
+ require "active_record/associations/preloader/batch"
49
+ require "active_record/associations/preloader/branch"
50
+ require "active_record/associations/preloader/through_association"
51
+ require "active_record/asynchronous_queries_tracker"
52
+ require "active_record/attribute_assignment"
53
+ require "active_record/attribute_methods/before_type_cast"
54
+ require "active_record/attribute_methods/dirty"
55
+ require "active_record/attribute_methods/primary_key"
56
+ require "active_record/attribute_methods/query"
57
+ require "active_record/attribute_methods/read"
58
+ require "active_record/attribute_methods/serialization"
59
+ require "active_record/attribute_methods/time_zone_conversion"
60
+ require "active_record/attribute_methods/write"
61
+ require "active_record/attributes"
62
+ require "active_record/autosave_association"
63
+ require "active_record/base"
64
+ require "active_record/coders/json"
65
+ require "active_record/disable_joins_association_relation"
66
+ require "active_record/encryption/cipher/aes256_gcm"
67
+ require "active_record/encryption/derived_secret_key_provider"
68
+ require "active_record/encryption/deterministic_key_provider"
69
+ require "active_record/encryption/encrypted_attribute_type"
70
+ require "active_record/encryption/encrypted_fixtures"
71
+ require "active_record/encryption/encrypting_only_encryptor"
72
+ require "active_record/encryption/envelope_encryption_key_provider"
73
+ require "active_record/encryption/extended_deterministic_queries"
74
+ require "active_record/encryption/extended_deterministic_uniqueness_validator"
75
+ require "active_record/encryption/key"
76
+ require "active_record/encryption/message"
77
+ require "active_record/encryption/null_encryptor"
78
+ require "active_record/encryption/properties"
79
+ require "active_record/encryption/read_only_null_encryptor"
80
+ require "active_record/encryption/scheme"
81
+ require "active_record/future_result"
82
+ require "active_record/internal_metadata"
83
+ require "active_record/legacy_yaml_adapter"
84
+ require "active_record/middleware/database_selector"
85
+ require "active_record/middleware/shard_selector"
86
+ require "active_record/null_relation"
87
+ require "active_record/query_logs"
88
+ require "active_record/relation/predicate_builder"
89
+ require "active_record/relation/record_fetch_warning"
90
+ require "active_record/result"
91
+ require "active_record/runtime_registry"
92
+ require "active_record/statement_cache"
93
+ require "active_record/table_metadata"
94
+ require "active_record/tasks/database_tasks"
95
+ require "active_record/tasks/mysql_database_tasks"
96
+ require "active_record/tasks/postgresql_database_tasks"
97
+ require "active_record/tasks/sqlite_database_tasks"
98
+ require "arel/collectors/bind"
99
+ require "arel/collectors/composite"
100
+ require "arel/collectors/substitute_binds"
64
101
 
65
- # There are also issues with requiring ActiveSupport. This doesn't require every
66
- # ActiveSupport file though, only ones we've seen cause problems.
67
- require 'active_support'
102
+ elsif (
103
+ ActiveRecord.version.segments[0] == 6 &&
104
+ ActiveRecord.version.segments[1] > 0
105
+ )
106
+ require "active_record/aggregations"
107
+ require "active_record/association_relation"
108
+ require "active_record/associations"
109
+ require "active_record/associations/alias_tracker"
110
+ require "active_record/associations/association"
111
+ require "active_record/associations/association_scope"
112
+ require "active_record/associations/belongs_to_association"
113
+ require "active_record/associations/belongs_to_polymorphic_association"
114
+ require "active_record/associations/builder/association"
115
+ require "active_record/associations/builder/belongs_to"
116
+ require "active_record/associations/builder/collection_association"
117
+ require "active_record/associations/builder/has_and_belongs_to_many"
118
+ require "active_record/associations/builder/has_many"
119
+ require "active_record/associations/builder/has_one"
120
+ require "active_record/associations/collection_association"
121
+ require "active_record/associations/collection_proxy"
122
+ require "active_record/associations/foreign_association"
123
+ require "active_record/associations/has_many_association"
124
+ require "active_record/associations/has_many_through_association"
125
+ require "active_record/associations/has_one_association"
126
+ require "active_record/associations/has_one_through_association"
127
+ require "active_record/associations/join_dependency"
128
+ require "active_record/associations/join_dependency/join_association"
129
+ require "active_record/associations/join_dependency/join_base"
130
+ require "active_record/associations/preloader"
131
+ require "active_record/associations/preloader/association"
132
+ require "active_record/associations/preloader/through_association"
133
+ require "active_record/attribute_assignment"
134
+ require "active_record/attribute_methods/before_type_cast"
135
+ require "active_record/attribute_methods/dirty"
136
+ require "active_record/attribute_methods/primary_key"
137
+ require "active_record/attribute_methods/query"
138
+ require "active_record/attribute_methods/read"
139
+ require "active_record/attribute_methods/serialization"
140
+ require "active_record/attribute_methods/time_zone_conversion"
141
+ require "active_record/attribute_methods/write"
142
+ require "active_record/attributes"
143
+ require "active_record/autosave_association"
144
+ require "active_record/base"
145
+ require "active_record/coders/json"
146
+ require "active_record/internal_metadata"
147
+ require "active_record/legacy_yaml_adapter"
148
+ require "active_record/middleware/database_selector"
149
+ require "active_record/null_relation"
150
+ require "active_record/relation/predicate_builder"
151
+ require "active_record/relation/record_fetch_warning"
152
+ require "active_record/result"
153
+ require "active_record/runtime_registry"
154
+ require "active_record/statement_cache"
155
+ require "active_record/table_metadata"
156
+ require "active_record/tasks/database_tasks"
157
+ require "active_record/tasks/mysql_database_tasks"
158
+ require "active_record/tasks/postgresql_database_tasks"
159
+ require "active_record/tasks/sqlite_database_tasks"
160
+ require "arel/collectors/bind"
161
+ require "arel/collectors/composite"
162
+ require "arel/collectors/substitute_binds"
163
+ elsif (
164
+ ActiveRecord.version.segments[0] == 6 &&
165
+ ActiveRecord.version.segments[1] == 0
166
+ )
167
+ require "active_record/advisory_lock_base"
168
+ require "active_record/associations/alias_tracker"
169
+ require "active_record/associations/association"
170
+ require "active_record/associations/association_scope"
171
+ require "active_record/associations/belongs_to_association"
172
+ require "active_record/associations/belongs_to_polymorphic_association"
173
+ require "active_record/associations/builder/belongs_to"
174
+ require "active_record/associations/builder/collection_association"
175
+ require "active_record/associations/builder/has_and_belongs_to_many"
176
+ require "active_record/associations/builder/has_many"
177
+ require "active_record/associations/builder/has_one"
178
+ require "active_record/associations/collection_association"
179
+ require "active_record/associations/foreign_association"
180
+ require "active_record/associations/has_many_association"
181
+ require "active_record/associations/has_many_through_association"
182
+ require "active_record/associations/has_one_association"
183
+ require "active_record/associations/has_one_through_association"
184
+ require "active_record/associations/join_dependency"
185
+ require "active_record/associations/join_dependency/join_association"
186
+ require "active_record/associations/join_dependency/join_base"
187
+ require "active_record/associations/preloader"
188
+ require "active_record/associations/preloader/association"
189
+ require "active_record/associations/preloader/through_association"
190
+ require "active_record/coders/json"
191
+ require "active_record/internal_metadata"
192
+ require "active_record/legacy_yaml_adapter"
193
+ require "active_record/middleware/database_selector"
194
+ require "active_record/null_relation"
195
+ require "active_record/relation/predicate_builder"
196
+ require "active_record/relation/record_fetch_warning"
197
+ require "active_record/result"
198
+ require "active_record/runtime_registry"
199
+ require "active_record/statement_cache"
200
+ require "active_record/table_metadata"
201
+ require "active_record/tasks/database_tasks"
202
+ require "active_record/tasks/mysql_database_tasks"
203
+ require "active_record/tasks/postgresql_database_tasks"
204
+ require "active_record/tasks/sqlite_database_tasks"
205
+ elsif ActiveRecord.version.segments[0] == 5
206
+ require "active_record/aggregations"
207
+ require "active_record/association_relation"
208
+ require "active_record/associations"
209
+ require "active_record/associations/alias_tracker"
210
+ require "active_record/associations/association"
211
+ require "active_record/associations/association_scope"
212
+ require "active_record/associations/belongs_to_association"
213
+ require "active_record/associations/belongs_to_polymorphic_association"
214
+ require "active_record/associations/builder/association"
215
+ require "active_record/associations/builder/belongs_to"
216
+ require "active_record/associations/builder/collection_association"
217
+ require "active_record/associations/builder/has_and_belongs_to_many"
218
+ require "active_record/associations/builder/has_many"
219
+ require "active_record/associations/builder/has_one"
220
+ require "active_record/associations/collection_association"
221
+ require "active_record/associations/collection_proxy"
222
+ require "active_record/associations/foreign_association"
223
+ require "active_record/associations/has_many_association"
224
+ require "active_record/associations/has_many_through_association"
225
+ require "active_record/associations/has_one_association"
226
+ require "active_record/associations/has_one_through_association"
227
+ require "active_record/associations/join_dependency"
228
+ require "active_record/associations/join_dependency/join_association"
229
+ require "active_record/associations/join_dependency/join_base"
230
+ require "active_record/associations/preloader"
231
+ require "active_record/associations/preloader/association"
232
+ require "active_record/associations/preloader/through_association"
233
+ require "active_record/attribute_assignment"
234
+ require "active_record/attribute_decorators"
235
+ require "active_record/attribute_methods/before_type_cast"
236
+ require "active_record/attribute_methods/dirty"
237
+ require "active_record/attribute_methods/primary_key"
238
+ require "active_record/attribute_methods/query"
239
+ require "active_record/attribute_methods/read"
240
+ require "active_record/attribute_methods/serialization"
241
+ require "active_record/attribute_methods/time_zone_conversion"
242
+ require "active_record/attribute_methods/write"
243
+ require "active_record/attributes"
244
+ require "active_record/autosave_association"
245
+ require "active_record/base"
246
+ require "active_record/coders/json"
247
+ require "active_record/internal_metadata"
248
+ require "active_record/legacy_yaml_adapter"
249
+ require "active_record/null_relation"
250
+ require "active_record/relation/predicate_builder"
251
+ require "active_record/relation/record_fetch_warning"
252
+ require "active_record/result"
253
+ require "active_record/runtime_registry"
254
+ require "active_record/statement_cache"
255
+ require "active_record/table_metadata"
256
+ require "active_record/tasks/database_tasks"
257
+ require "active_record/tasks/mysql_database_tasks"
258
+ require "active_record/tasks/postgresql_database_tasks"
259
+ require "active_record/tasks/sqlite_database_tasks"
260
+ else
261
+ raise(
262
+ "ActiveRecord #{ActiveRecord.version} isn't supported. "\
263
+ "Switch to 5.X or 6.X",
264
+ )
265
+ end
68
266
 
69
- require 'active_support/multibyte/chars'
267
+ # There are also issues with requiring ActiveSupport. This doesn"t require every
268
+ # ActiveSupport file though, only ones we"ve seen cause problems.
269
+ require "active_support"
270
+ require "active_support/multibyte/chars"
@@ -1,13 +1,14 @@
1
- require 'active_record'
2
- require 'ardb'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "ardb"
3
5
 
4
6
  # Use theses helpers in your test suite. They all generally assume Ardb has
5
7
  # already been initialized by calling `Ardb.init`.
6
8
 
7
9
  module Ardb
8
-
9
10
  module TestHelpers
10
- module_function
11
+ extend self
11
12
 
12
13
  def drop_tables
13
14
  Ardb.adapter.drop_tables
@@ -22,10 +23,11 @@ module Ardb
22
23
  end
23
24
 
24
25
  def create_db
25
- @create_db ||= begin
26
- self.create_db!
27
- true
28
- end
26
+ @create_db ||=
27
+ begin
28
+ create_db!
29
+ true
30
+ end
29
31
  end
30
32
 
31
33
  def drop_db!
@@ -33,10 +35,11 @@ module Ardb
33
35
  end
34
36
 
35
37
  def drop_db
36
- @drop_db ||= begin
37
- self.drop_db!
38
- true
39
- end
38
+ @drop_db ||=
39
+ begin
40
+ drop_db!
41
+ true
42
+ end
40
43
  end
41
44
 
42
45
  def connect_db!
@@ -44,10 +47,11 @@ module Ardb
44
47
  end
45
48
 
46
49
  def connect_db
47
- @connect_db ||= begin
48
- self.connect_db!
49
- true
50
- end
50
+ @connect_db ||=
51
+ begin
52
+ connect_db!
53
+ true
54
+ end
51
55
  end
52
56
 
53
57
  def migrate_db!
@@ -55,25 +59,25 @@ module Ardb
55
59
  end
56
60
 
57
61
  def migrate_db
58
- @migrate_db ||= begin
59
- self.migrate_db!
60
- true
61
- end
62
+ @migrate_db ||=
63
+ begin
64
+ migrate_db!
65
+ true
66
+ end
62
67
  end
63
68
 
64
69
  def reset_db!
65
- self.drop_db!
66
- self.create_db!
67
- self.load_schema
70
+ drop_db!
71
+ create_db!
72
+ load_schema
68
73
  end
69
74
 
70
75
  def reset_db
71
- @reset_db ||= begin
72
- self.reset_db!
73
- true
74
- end
76
+ @reset_db ||=
77
+ begin
78
+ reset_db!
79
+ true
80
+ end
75
81
  end
76
-
77
82
  end
78
-
79
83
  end
@@ -1,22 +1,18 @@
1
- require 'much-plugin'
1
+ # frozen_string_literal: true
2
2
 
3
- module Ardb
3
+ require "much-mixin"
4
4
 
5
+ module Ardb
5
6
  module UseDbDefault
6
- include MuchPlugin
7
-
8
- plugin_included do
9
- extend ClassMethods
10
- include InstanceMethods
7
+ include MuchMixin
11
8
 
9
+ mixin_included do
12
10
  @ardb_use_db_default_attrs = []
13
11
 
14
12
  around_create :ardb_allow_db_to_default_attrs
15
-
16
13
  end
17
14
 
18
- module ClassMethods
19
-
15
+ mixin_class_methods do
20
16
  def ardb_use_db_default_attrs
21
17
  @ardb_use_db_default_attrs
22
18
  end
@@ -25,32 +21,28 @@ module Ardb
25
21
  @ardb_use_db_default_attrs += attrs.map(&:to_s)
26
22
  @ardb_use_db_default_attrs.uniq!
27
23
  end
28
-
29
24
  end
30
25
 
31
- module InstanceMethods
32
-
26
+ mixin_instance_methods do
33
27
  private
34
28
 
35
29
  def ardb_allow_db_to_default_attrs
36
30
  # this allows the attr to be defaulted by the DB, this keeps
37
31
  # activerecord from adding the attr into the sql `INSERT`, which will
38
32
  # make the DB default its value
39
- unchanged_names = self.class.ardb_use_db_default_attrs.reject do |name|
40
- self.send("#{name}_changed?")
41
- end
33
+ unchanged_names =
34
+ self.class.ardb_use_db_default_attrs.reject do |name|
35
+ send("#{name}_changed?")
36
+ end
42
37
  unchanged_names.each{ |name| @attributes.delete(name) }
43
38
  yield
44
39
  # we have to go and fetch the attr value from the DB, otherwise
45
- # activerecord doesn't know the value that the DB used
46
- scope = self.class.where(:id => self.id)
40
+ # activerecord doesn"t know the value that the DB used
41
+ scope = self.class.where(id: id)
47
42
  unchanged_names.each do |name|
48
43
  @attributes[name] = scope.pluck(name).first
49
44
  end
50
45
  end
51
-
52
46
  end
53
-
54
47
  end
55
-
56
48
  end
data/lib/ardb/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Ardb
2
- VERSION = "0.28.3"
4
+ VERSION = "0.30.0"
3
5
  end