ardb 0.27.3 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
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