ardb 0.27.3 → 0.29.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 (54) hide show
  1. checksums.yaml +7 -7
  2. data/Gemfile +4 -5
  3. data/README.md +252 -3
  4. data/ardb.gemspec +8 -8
  5. data/bin/ardb +1 -1
  6. data/lib/ardb.rb +155 -72
  7. data/lib/ardb/adapter/base.rb +67 -47
  8. data/lib/ardb/adapter/mysql.rb +3 -19
  9. data/lib/ardb/adapter/postgresql.rb +33 -37
  10. data/lib/ardb/adapter/sqlite.rb +7 -16
  11. data/lib/ardb/adapter_spy.rb +58 -92
  12. data/lib/ardb/cli.rb +18 -226
  13. data/lib/ardb/{clirb.rb → cli/clirb.rb} +16 -18
  14. data/lib/ardb/cli/commands.rb +365 -0
  15. data/lib/ardb/db_tests.rb +2 -4
  16. data/lib/ardb/default_order_by.rb +3 -13
  17. data/lib/ardb/migration.rb +18 -20
  18. data/lib/ardb/record_spy.rb +7 -26
  19. data/lib/ardb/relation_spy.rb +0 -6
  20. data/lib/ardb/require_autoloaded_active_record_files.rb +103 -58
  21. data/lib/ardb/test_helpers.rb +2 -5
  22. data/lib/ardb/use_db_default.rb +4 -15
  23. data/lib/ardb/version.rb +1 -1
  24. data/script/determine_autoloaded_active_record_files.rb +11 -8
  25. data/test/helper.rb +9 -6
  26. data/test/support/factory.rb +17 -2
  27. data/test/support/fake_schema.rb +5 -0
  28. data/test/support/postgresql/migrations/.keep +0 -0
  29. data/test/support/postgresql/schema.rb +2 -0
  30. data/test/support/postgresql/setup_test_db.rb +51 -0
  31. data/test/support/relative_require_test_db_file.rb +2 -0
  32. data/test/support/require_test_db_file.rb +1 -0
  33. data/test/system/.keep +0 -0
  34. data/test/unit/adapter/base_tests.rb +163 -75
  35. data/test/unit/adapter/mysql_tests.rb +4 -20
  36. data/test/unit/adapter/postgresql_tests.rb +20 -28
  37. data/test/unit/adapter/sqlite_tests.rb +9 -12
  38. data/test/unit/adapter_spy_tests.rb +48 -71
  39. data/test/unit/ardb_tests.rb +338 -38
  40. data/test/unit/cli_tests.rb +334 -225
  41. data/test/unit/db_tests_tests.rb +3 -6
  42. data/test/unit/default_order_by_tests.rb +4 -8
  43. data/test/unit/migration_tests.rb +20 -17
  44. data/test/unit/record_spy_tests.rb +18 -23
  45. data/test/unit/relation_spy_tests.rb +17 -46
  46. data/test/unit/test_helpers_tests.rb +5 -20
  47. data/test/unit/use_db_default_tests.rb +9 -13
  48. metadata +111 -100
  49. data/lib/ardb/has_slug.rb +0 -107
  50. data/lib/ardb/migration_helpers.rb +0 -77
  51. data/lib/ardb/root_path.rb +0 -15
  52. data/test/unit/config_tests.rb +0 -58
  53. data/test/unit/has_slug_tests.rb +0 -341
  54. data/test/unit/migration_helpers_tests.rb +0 -59
@@ -1,77 +0,0 @@
1
- require 'ardb'
2
-
3
- module Ardb
4
-
5
- module MigrationHelpers
6
- module_function
7
-
8
- def foreign_key(from_table, from_column, to_table, options={})
9
- fk = ForeignKey.new(from_table, from_column, to_table, options)
10
- execute(fk.add_sql)
11
- end
12
-
13
- def drop_foreign_key(*args)
14
- from_table, from_column = args[0..1]
15
- options = args.last.kind_of?(Hash) ? args.last : {}
16
- fk = ForeignKey.new(from_table, from_column, nil, options)
17
- execute(fk.drop_sql)
18
- end
19
-
20
- def remove_column_with_fk(table, column)
21
- drop_foreign_key(table, column)
22
- remove_column(table, column)
23
- end
24
-
25
- class ForeignKey
26
- attr_reader :from_table, :from_column, :to_table, :to_column, :name, :adapter
27
-
28
- def initialize(from_table, from_column, to_table, options=nil)
29
- options ||= {}
30
- @from_table = from_table.to_s
31
- @from_column = from_column.to_s
32
- @to_table = to_table.to_s
33
- @to_column = (options[:to_column] || 'id').to_s
34
- @name = (options[:name] || "fk_#{@from_table}_#{@from_column}").to_s
35
- @adapter = Ardb::Adapter.send(Ardb.config.db.adapter)
36
- end
37
-
38
- def add_sql
39
- apply_data(@adapter.foreign_key_add_sql)
40
- end
41
-
42
- def drop_sql
43
- apply_data(@adapter.foreign_key_drop_sql)
44
- end
45
-
46
- private
47
-
48
- def apply_data(template_sql)
49
- template_sql.
50
- gsub(':from_table', @from_table).
51
- gsub(':from_column', @from_column).
52
- gsub(':to_table', @to_table).
53
- gsub(':to_column', @to_column).
54
- gsub(':name', @name)
55
- end
56
- end
57
-
58
- # This file will setup the AR migration command recorder for being able to
59
- # change our stuff, require it in an initializer
60
-
61
- module RecorderMixin
62
-
63
- def foreign_key(*args)
64
- record(:foreign_key, args)
65
- end
66
-
67
- protected
68
-
69
- def invert_foreign_key(args)
70
- [ :drop_foreign_key, args ]
71
- end
72
-
73
- end
74
-
75
- end
76
-
77
- end
@@ -1,15 +0,0 @@
1
- # This takes a path string relative to the configured root path and tranforms
2
- # to the full qualifed root path. The goal here is to specify path options
3
- # with root-relative path strings.
4
-
5
- module Ardb
6
-
7
- class RootPath < String
8
-
9
- def initialize(path_string)
10
- super(Ardb.config.root_path.join(path_string).to_s)
11
- end
12
-
13
- end
14
-
15
- end
@@ -1,58 +0,0 @@
1
- require 'assert'
2
- require 'ardb'
3
-
4
- require 'ns-options/assert_macros'
5
-
6
- class Ardb::Config
7
-
8
- class UnitTests < Assert::Context
9
- include NsOptions::AssertMacros
10
-
11
- desc "Ardb::Config"
12
- subject{ Ardb::Config }
13
-
14
- should have_namespace :db
15
- should have_option :db_file, Pathname, :default => ENV['ARDB_DB_FILE']
16
- should have_option :root_path, Pathname, :required => true
17
- should have_option :logger, :required => true
18
- should have_options :migrations_path, :schema_path
19
- should have_imeth :db_settings
20
-
21
- should "should use `db/migrations` as the default migrations path" do
22
- exp_path = Pathname.new(TESTDB_PATH).join("db/migrations").to_s
23
- assert_equal exp_path, subject.migrations_path
24
- end
25
-
26
- should "should use `db/schema` as the default schema path" do
27
- exp_path = Pathname.new(TESTDB_PATH).join("db/schema").to_s
28
- assert_equal exp_path, subject.schema_path
29
- end
30
-
31
- should "build the db connection settings from the db configs" do
32
- # returns only non-nil values with string keys
33
- exp = {
34
- 'adapter' => "postgresql",
35
- 'database' => "ardbtest"
36
- }
37
- assert_equal exp, subject.db_settings
38
- end
39
-
40
- end
41
-
42
- class DbTests < UnitTests
43
- desc "db namespace"
44
- subject{ Ardb::Config.db }
45
-
46
- should have_option :adapter, String, :required => true
47
- should have_option :database, String, :required => true
48
- should have_option :encoding, String, :required => false
49
- should have_option :host, String, :required => false
50
- should have_option :port, Integer, :required => false
51
- should have_option :username, String, :required => false
52
- should have_option :password, String, :required => false
53
- should have_option :pool, Integer, :required => false
54
- should have_option :checkout_timeout, Integer, :required => false
55
-
56
- end
57
-
58
- end
@@ -1,341 +0,0 @@
1
- require 'assert'
2
- require 'ardb/has_slug'
3
-
4
- require 'much-plugin'
5
- require 'ardb/record_spy'
6
-
7
- module Ardb::HasSlug
8
-
9
- class UnitTests < Assert::Context
10
- desc "Ardb::HasSlug"
11
- setup do
12
- source_attribute = @source_attribute = Factory.string.to_sym
13
- slug_attribute = @slug_attribute = Factory.string.to_sym
14
- @record_class = Ardb::RecordSpy.new do
15
- include Ardb::HasSlug
16
- attr_accessor source_attribute, slug_attribute, DEFAULT_ATTRIBUTE
17
- attr_reader :slug_db_column_updates
18
-
19
- def update_column(*args)
20
- @slug_db_column_updates ||= []
21
- @slug_db_column_updates << args
22
- end
23
- end
24
- end
25
- subject{ @record_class }
26
-
27
- NON_WORD_CHARS = ((' '..'/').to_a + (':'..'@').to_a + ('['..'`').to_a +
28
- ('{'..'~').to_a - ['-', '_']).freeze
29
-
30
- should have_imeths :has_slug
31
- should have_imeths :ardb_has_slug_configs
32
-
33
- should "use much-plugin" do
34
- assert_includes MuchPlugin, Ardb::HasSlug
35
- end
36
-
37
- should "know its default attribute, preprocessor and separator" do
38
- assert_equal :slug, DEFAULT_ATTRIBUTE
39
- assert_equal :downcase, DEFAULT_PREPROCESSOR
40
- assert_equal '-', DEFAULT_SEPARATOR
41
- end
42
-
43
- should "not have any has-slug configs by default" do
44
- assert_equal({}, subject.ardb_has_slug_configs)
45
- end
46
-
47
- should "default the has slug config using `has_slug`" do
48
- subject.has_slug :source => @source_attribute
49
- string = Factory.string
50
- record = subject.new.tap{ |r| r.send("#{@source_attribute}=", string) }
51
-
52
- config = subject.ardb_has_slug_configs[DEFAULT_ATTRIBUTE]
53
- assert_equal DEFAULT_SEPARATOR, config[:separator]
54
- assert_false config[:allow_underscores]
55
-
56
- source_proc = config[:source_proc]
57
- assert_instance_of Proc, source_proc
58
- exp = record.send(@source_attribute)
59
- assert_equal exp, record.instance_eval(&source_proc)
60
-
61
- upcase_string = string.upcase
62
- preprocessor_proc = config[:preprocessor_proc]
63
- assert_instance_of Proc, preprocessor_proc
64
- exp = upcase_string.send(DEFAULT_PREPROCESSOR)
65
- assert_equal exp, preprocessor_proc.call(upcase_string)
66
- end
67
-
68
- should "allow customizing the has slug config using `has_slug`" do
69
- separator = NON_WORD_CHARS.choice
70
- allow_underscore = Factory.boolean
71
- subject.has_slug({
72
- :attribute => @slug_attribute,
73
- :source => @source_attribute,
74
- :preprocessor => :upcase,
75
- :separator => separator,
76
- :allow_underscores => allow_underscore
77
- })
78
-
79
- config = subject.ardb_has_slug_configs[@slug_attribute]
80
- assert_equal separator, config[:separator]
81
- assert_equal allow_underscore, config[:allow_underscores]
82
-
83
- value = Factory.string.downcase
84
- preprocessor_proc = config[:preprocessor_proc]
85
- assert_instance_of Proc, preprocessor_proc
86
- assert_equal value.upcase, preprocessor_proc.call(value)
87
- end
88
-
89
- should "add validations using `has_slug`" do
90
- subject.has_slug :source => @source_attribute
91
- exp_attr_name = DEFAULT_ATTRIBUTE
92
-
93
- validation = subject.validations.find{ |v| v.type == :presence }
94
- assert_not_nil validation
95
- assert_equal [exp_attr_name], validation.columns
96
- assert_equal :update, validation.options[:on]
97
-
98
- validation = subject.validations.find{ |v| v.type == :uniqueness }
99
- assert_not_nil validation
100
- assert_equal [exp_attr_name], validation.columns
101
- assert_equal true, validation.options[:case_sensitive]
102
- assert_nil validation.options[:scope]
103
- end
104
-
105
- should "not add a unique validation if skipping unique validation" do
106
- subject.has_slug({
107
- :source => @source_attribute,
108
- :skip_unique_validation => true
109
- })
110
-
111
- validation = subject.validations.find{ |v| v.type == :uniqueness }
112
- assert_nil validation
113
- end
114
-
115
- should "allow customizing its validations using `has_slug`" do
116
- unique_scope = Factory.string.to_sym
117
- subject.has_slug({
118
- :source => @source_attribute,
119
- :unique_scope => unique_scope
120
- })
121
-
122
- validation = subject.validations.find{ |v| v.type == :uniqueness }
123
- assert_not_nil validation
124
- assert_equal unique_scope, validation.options[:scope]
125
- end
126
-
127
- should "add callbacks using `has_slug`" do
128
- subject.has_slug :source => @source_attribute
129
-
130
- callback = subject.callbacks.find{ |v| v.type == :after_create }
131
- assert_not_nil callback
132
- assert_equal [:ardb_has_slug_generate_slugs], callback.args
133
-
134
- callback = subject.callbacks.find{ |v| v.type == :after_update }
135
- assert_not_nil callback
136
- assert_equal [:ardb_has_slug_generate_slugs], callback.args
137
- end
138
-
139
- should "raise an argument error if `has_slug` isn't passed a source" do
140
- assert_raises(ArgumentError){ subject.has_slug }
141
- end
142
-
143
- end
144
-
145
- class InitTests < UnitTests
146
- desc "when init"
147
- setup do
148
- @preprocessor = [:downcase, :upcase, :capitalize].choice
149
- @separator = NON_WORD_CHARS.choice
150
- @allow_underscores = Factory.boolean
151
-
152
- @record_class.has_slug(:source => @source_attribute)
153
- @record_class.has_slug({
154
- :attribute => @slug_attribute,
155
- :source => @source_attribute,
156
- :preprocessor => @preprocessor,
157
- :separator => @separator,
158
- :allow_underscores => @allow_underscores,
159
- })
160
-
161
- @record = @record_class.new
162
-
163
- # create a string that has mixed case and an underscore so we can test
164
- # that it uses the preprocessor and allow underscores options when
165
- # generating a slug
166
- @source_value = "#{Factory.string.downcase}_#{Factory.string.upcase}"
167
- @record.send("#{@source_attribute}=", @source_value)
168
-
169
- @exp_default_slug = Slug.new(@source_value, {
170
- :preprocessor => DEFAULT_PREPROCESSOR.to_proc,
171
- :separator => DEFAULT_SEPARATOR
172
- })
173
- @exp_custom_slug = Slug.new(@source_value, {
174
- :preprocessor => @preprocessor.to_proc,
175
- :separator => @separator,
176
- :allow_underscores => @allow_underscores
177
- })
178
- end
179
- subject{ @record }
180
-
181
- should "reset its slug using `reset_slug`" do
182
- # reset the default attribute
183
- subject.send("#{DEFAULT_ATTRIBUTE}=", Factory.slug)
184
- assert_not_nil subject.send(DEFAULT_ATTRIBUTE)
185
- subject.instance_eval{ reset_slug }
186
- assert_nil subject.send(DEFAULT_ATTRIBUTE)
187
-
188
- # reset a custom attribute
189
- subject.send("#{@slug_attribute}=", Factory.slug)
190
- assert_not_nil subject.send(@slug_attribute)
191
- sa = @slug_attribute
192
- subject.instance_eval{ reset_slug(sa) }
193
- assert_nil subject.send(@slug_attribute)
194
- end
195
-
196
- should "default its slug attribute" do
197
- subject.instance_eval{ ardb_has_slug_generate_slugs }
198
- assert_equal 2, subject.slug_db_column_updates.size
199
-
200
- exp = @exp_default_slug
201
- assert_equal exp, subject.send(DEFAULT_ATTRIBUTE)
202
- assert_includes [DEFAULT_ATTRIBUTE, exp], subject.slug_db_column_updates
203
-
204
- exp = @exp_custom_slug
205
- assert_equal exp, subject.send(@slug_attribute)
206
- assert_includes [@slug_attribute, exp], subject.slug_db_column_updates
207
- end
208
-
209
- should "not set its slug if it hasn't changed" do
210
- @record.send("#{DEFAULT_ATTRIBUTE}=", @exp_default_slug)
211
- @record.send("#{@slug_attribute}=", @exp_custom_slug)
212
-
213
- subject.instance_eval{ ardb_has_slug_generate_slugs }
214
- assert_nil subject.slug_db_column_updates
215
- end
216
-
217
- should "slug its slug attribute value if set" do
218
- @record.send("#{@slug_attribute}=", @source_value)
219
- # change the source attr to some random value, to avoid a false positive
220
- @record.send("#{@source_attribute}=", Factory.string)
221
- subject.instance_eval{ ardb_has_slug_generate_slugs }
222
-
223
- exp = @exp_custom_slug
224
- assert_equal exp, subject.send(@slug_attribute)
225
- assert_includes [@slug_attribute, exp], subject.slug_db_column_updates
226
- end
227
-
228
- should "slug its source even if its already a valid slug" do
229
- slug_source = Factory.slug
230
- @record.send("#{@source_attribute}=", slug_source)
231
- # ensure the preprocessor doesn't change our source
232
- Assert.stub(slug_source, @preprocessor){ slug_source }
233
-
234
- subject.instance_eval{ ardb_has_slug_generate_slugs }
235
-
236
- exp = Slug.new(slug_source, {
237
- :preprocessor => @preprocessor.to_proc,
238
- :separator => @separator,
239
- :allow_underscores => @allow_underscores
240
- })
241
- assert_equal exp, subject.send(@slug_attribute)
242
- assert_includes [@slug_attribute, exp], subject.slug_db_column_updates
243
- end
244
-
245
- end
246
-
247
- class SlugTests < UnitTests
248
- desc "Slug"
249
- setup do
250
- @no_op_pp = proc{ |slug| slug }
251
- @args = {
252
- :preprocessor => @no_op_pp,
253
- :separator => '-'
254
- }
255
- end
256
- subject{ Slug }
257
-
258
- should have_imeths :new
259
-
260
- should "always dup the given string" do
261
- string = Factory.string
262
- assert_not_same string, subject.new(string, @args)
263
- end
264
-
265
- should "not change strings that are made up of valid chars" do
266
- string = Factory.string
267
- assert_equal string, subject.new(string, @args)
268
-
269
- string = "#{Factory.string}-#{Factory.string.upcase}"
270
- assert_equal string, subject.new(string, @args)
271
- end
272
-
273
- should "turn invalid chars into a separator" do
274
- string = Factory.integer(3).times.map do
275
- "#{Factory.string(3)}#{NON_WORD_CHARS.choice}#{Factory.string(3)}"
276
- end.join(NON_WORD_CHARS.choice)
277
- assert_equal string.gsub(/[^\w]+/, '-'), subject.new(string, @args)
278
- end
279
-
280
- should "allow passing a custom preprocessor proc" do
281
- string = "#{Factory.string}-#{Factory.string.upcase}"
282
- exp = string.downcase
283
- assert_equal exp, subject.new(string, @args.merge(:preprocessor => :downcase.to_proc))
284
-
285
- preprocessor = proc{ |s| s.gsub(/[A-Z]/, 'a') }
286
- exp = preprocessor.call(string)
287
- assert_equal exp, subject.new(string, @args.merge(:preprocessor => preprocessor))
288
- end
289
-
290
- should "allow passing a custom separator" do
291
- separator = NON_WORD_CHARS.choice
292
-
293
- invalid_char = (NON_WORD_CHARS - [separator]).choice
294
- string = "#{Factory.string}#{invalid_char}#{Factory.string}"
295
- exp = string.gsub(/[^\w]+/, separator)
296
- assert_equal exp, subject.new(string, @args.merge(:separator => separator))
297
-
298
- # it won't change the separator in the strings
299
- string = "#{Factory.string}#{separator}#{Factory.string}"
300
- exp = string
301
- assert_equal string, subject.new(string, @args.merge(:separator => separator))
302
-
303
- # it will change the default separator now
304
- string = "#{Factory.string}-#{Factory.string}"
305
- exp = string.gsub('-', separator)
306
- assert_equal exp, subject.new(string, @args.merge(:separator => separator))
307
- end
308
-
309
- should "change underscores into its separator unless allowed" do
310
- string = "#{Factory.string}_#{Factory.string}"
311
- assert_equal string.gsub('_', '-'), subject.new(string, @args)
312
-
313
- exp = string.gsub('_', '-')
314
- assert_equal exp, subject.new(string, @args.merge(:allow_underscores => false))
315
-
316
- assert_equal string, subject.new(string, @args.merge(:allow_underscores => true))
317
- end
318
-
319
- should "not allow multiple separators in a row" do
320
- string = "#{Factory.string}--#{Factory.string}"
321
- assert_equal string.gsub(/-{2,}/, '-'), subject.new(string, @args)
322
-
323
- # remove separators that were added from changing invalid chars
324
- invalid_chars = (Factory.integer(3) + 1).times.map{ NON_WORD_CHARS.choice }.join
325
- string = "#{Factory.string}#{invalid_chars}#{Factory.string}"
326
- assert_equal string.gsub(/[^\w]+/, '-'), subject.new(string, @args)
327
- end
328
-
329
- should "remove leading and trailing separators" do
330
- string = "-#{Factory.string}-#{Factory.string}-"
331
- assert_equal string[1..-2], subject.new(string, @args)
332
-
333
- # remove separators that were added from changing invalid chars
334
- invalid_char = NON_WORD_CHARS.choice
335
- string = "#{invalid_char}#{Factory.string}-#{Factory.string}#{invalid_char}"
336
- assert_equal string[1..-2], subject.new(string, @args)
337
- end
338
-
339
- end
340
-
341
- end