ardb 0.27.3 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -1
  3. data/ardb.gemspec +3 -4
  4. data/lib/ardb.rb +135 -68
  5. data/lib/ardb/adapter/base.rb +39 -24
  6. data/lib/ardb/adapter/mysql.rb +1 -2
  7. data/lib/ardb/adapter/postgresql.rb +14 -12
  8. data/lib/ardb/adapter/sqlite.rb +3 -8
  9. data/lib/ardb/adapter_spy.rb +67 -87
  10. data/lib/ardb/cli.rb +11 -219
  11. data/lib/ardb/{clirb.rb → cli/clirb.rb} +2 -1
  12. data/lib/ardb/cli/commands.rb +275 -0
  13. data/lib/ardb/migration.rb +8 -6
  14. data/lib/ardb/migration_helpers.rb +1 -1
  15. data/lib/ardb/pg_json.rb +90 -0
  16. data/lib/ardb/version.rb +1 -1
  17. data/test/helper.rb +15 -3
  18. data/test/support/factory.rb +15 -0
  19. data/test/support/fake_schema.rb +5 -0
  20. data/test/support/postgresql/migrations/.gitkeep +0 -0
  21. data/test/support/postgresql/pg_json_migrations/20160519133432_create_pg_json_migrate_test.rb +13 -0
  22. data/test/support/postgresql/schema.rb +3 -0
  23. data/test/support/postgresql/setup_test_db.rb +51 -0
  24. data/test/support/relative_require_test_db_file.rb +2 -0
  25. data/test/support/require_test_db_file.rb +1 -0
  26. data/test/system/pg_json_tests.rb +85 -0
  27. data/test/unit/adapter/base_tests.rb +104 -39
  28. data/test/unit/adapter/mysql_tests.rb +2 -1
  29. data/test/unit/adapter/postgresql_tests.rb +10 -9
  30. data/test/unit/adapter/sqlite_tests.rb +8 -3
  31. data/test/unit/adapter_spy_tests.rb +57 -66
  32. data/test/unit/ardb_tests.rb +323 -36
  33. data/test/unit/cli_tests.rb +193 -146
  34. data/test/unit/has_slug_tests.rb +9 -9
  35. data/test/unit/migration_helpers_tests.rb +18 -12
  36. data/test/unit/migration_tests.rb +18 -11
  37. data/test/unit/pg_json_tests.rb +39 -0
  38. data/test/unit/record_spy_tests.rb +1 -1
  39. data/test/unit/test_helpers_tests.rb +2 -6
  40. data/test/unit/use_db_default_tests.rb +2 -2
  41. metadata +29 -34
  42. data/lib/ardb/root_path.rb +0 -15
  43. data/test/unit/config_tests.rb +0 -58
@@ -1,4 +1,5 @@
1
- module Ardb
1
+ module Ardb; end
2
+ class Ardb::CLI
2
3
 
3
4
  class CLIRB # Version 1.0.0, https://github.com/redding/cli.rb
4
5
  Error = Class.new(RuntimeError);
@@ -0,0 +1,275 @@
1
+ require 'ardb'
2
+ require 'ardb/cli/clirb'
3
+ require 'much-plugin'
4
+
5
+ module Ardb; end
6
+ class Ardb::CLI
7
+
8
+ InvalidCommandError = Class.new(ArgumentError)
9
+ CommandExitError = Class.new(RuntimeError)
10
+
11
+ class InvalidCommand
12
+
13
+ attr_reader :name, :clirb
14
+
15
+ def initialize(name)
16
+ @name = name
17
+ @clirb = CLIRB.new
18
+ end
19
+
20
+ def new; self; end
21
+
22
+ def run(argv)
23
+ @clirb.parse!([@name, argv].flatten.compact)
24
+ raise CLIRB::HelpExit if @name.to_s.empty?
25
+ raise InvalidCommandError, "'#{self.name}' is not a command."
26
+ end
27
+
28
+ def help
29
+ "Usage: ardb [COMMAND] [options]\n\n" \
30
+ "Options: #{@clirb}\n" \
31
+ "Commands:\n" \
32
+ "#{COMMANDS.to_s.split("\n").map{ |l| " #{l}" }.join("\n")}\n"
33
+ end
34
+
35
+ end
36
+
37
+ module ValidCommand
38
+ include MuchPlugin
39
+
40
+ plugin_included do
41
+ include InstanceMethods
42
+ end
43
+
44
+ module InstanceMethods
45
+
46
+ def initialize(&clirb_build)
47
+ @clirb = CLIRB.new(&clirb_build)
48
+ end
49
+
50
+ def clirb; @clirb; end
51
+
52
+ def run(argv, stdout = nil, stderr = nil)
53
+ @clirb.parse!(argv)
54
+ @stdout = stdout || $stdout
55
+ @stderr = stderr || $stderr
56
+ end
57
+
58
+ def summary
59
+ ''
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ class ConnectCommand
67
+ include ValidCommand
68
+
69
+ def run(argv, *args)
70
+ super
71
+
72
+ Ardb.init(false)
73
+ begin
74
+ Ardb.adapter.connect_db
75
+ @stdout.puts "connected to #{Ardb.config.adapter} db `#{Ardb.config.database}`"
76
+ rescue StandardError => e
77
+ @stderr.puts e
78
+ @stderr.puts e.backtrace.join("\n")
79
+ @stderr.puts "error connecting to #{Ardb.config.database.inspect} database " \
80
+ "with #{Ardb.config.activerecord_connect_hash.inspect}"
81
+ raise CommandExitError
82
+ end
83
+ end
84
+
85
+ def summary
86
+ "Connect to the configured DB"
87
+ end
88
+
89
+ def help
90
+ "Usage: ardb connect [options]\n\n" \
91
+ "Options: #{@clirb}\n" \
92
+ "Description:\n" \
93
+ " #{self.summary}"
94
+ end
95
+
96
+ end
97
+
98
+ class CreateCommand
99
+ include ValidCommand
100
+
101
+ def run(argv, *args)
102
+ super
103
+
104
+ Ardb.init(false)
105
+ begin
106
+ Ardb.adapter.create_db
107
+ @stdout.puts "created #{Ardb.config.adapter} db `#{Ardb.config.database}`"
108
+ rescue StandardError => e
109
+ @stderr.puts e
110
+ @stderr.puts "error creating #{Ardb.config.database.inspect} database"
111
+ raise CommandExitError
112
+ end
113
+ end
114
+
115
+ def summary
116
+ "Create the configured DB"
117
+ end
118
+
119
+ def help
120
+ "Usage: ardb create [options]\n\n" \
121
+ "Options: #{@clirb}\n" \
122
+ "Description:\n" \
123
+ " #{self.summary}"
124
+ end
125
+
126
+ end
127
+
128
+ class DropCommand
129
+ include ValidCommand
130
+
131
+ def run(argv, *args)
132
+ super
133
+
134
+ Ardb.init(true)
135
+ begin
136
+ Ardb.adapter.drop_db
137
+ @stdout.puts "dropped #{Ardb.config.adapter} db `#{Ardb.config.database}`"
138
+ rescue StandardError => e
139
+ @stderr.puts e
140
+ @stderr.puts "error dropping #{Ardb.config.database.inspect} database"
141
+ raise CommandExitError
142
+ end
143
+ end
144
+
145
+ def summary
146
+ "Drop the configured DB"
147
+ end
148
+
149
+ def help
150
+ "Usage: ardb drop [options]\n\n" \
151
+ "Options: #{@clirb}\n" \
152
+ "Description:\n" \
153
+ " #{self.summary}"
154
+ end
155
+
156
+ end
157
+
158
+ class MigrateCommand
159
+ include ValidCommand
160
+
161
+ def run(argv, *args)
162
+ super
163
+
164
+ Ardb.init(true)
165
+ begin
166
+ Ardb.adapter.migrate_db
167
+ Ardb.adapter.dump_schema unless ENV['ARDB_MIGRATE_NO_SCHEMA']
168
+ rescue StandardError => e
169
+ @stderr.puts e
170
+ @stderr.puts e.backtrace.join("\n")
171
+ @stderr.puts "error migrating #{Ardb.config.database.inspect} database"
172
+ raise CommandExitError
173
+ end
174
+ end
175
+
176
+ def summary
177
+ "Migrate the configured DB"
178
+ end
179
+
180
+ def help
181
+ "Usage: ardb migrate [options]\n\n" \
182
+ "Options: #{@clirb}\n" \
183
+ "Description:\n" \
184
+ " #{self.summary}"
185
+ end
186
+
187
+ end
188
+
189
+ class GenerateMigrationCommand
190
+ include ValidCommand
191
+
192
+ def run(argv, *args)
193
+ super
194
+
195
+ Ardb.init(false)
196
+ begin
197
+ require 'ardb/migration'
198
+ migration = Ardb::Migration.new(Ardb.config, @clirb.args.first)
199
+ migration.save!
200
+ @stdout.puts "generated #{migration.file_path}"
201
+ rescue Ardb::Migration::NoIdentifierError => exception
202
+ error = ArgumentError.new("MIGRATION-NAME must be provided")
203
+ error.set_backtrace(exception.backtrace)
204
+ raise error
205
+ rescue StandardError => e
206
+ @stderr.puts e
207
+ @stderr.puts e.backtrace.join("\n")
208
+ @stderr.puts "error generating migration"
209
+ raise CommandExitError
210
+ end
211
+ end
212
+
213
+ def summary
214
+ "Generate a migration file given a MIGRATION-NAME"
215
+ end
216
+
217
+ def help
218
+ "Usage: ardb generate-migration [options] MIGRATION-NAME\n\n" \
219
+ "Options: #{@clirb}\n" \
220
+ "Description:\n" \
221
+ " #{self.summary}"
222
+ end
223
+
224
+ end
225
+
226
+ class CommandSet
227
+
228
+ def initialize(&unknown_cmd_block)
229
+ @lookup = Hash.new{ |h,k| unknown_cmd_block.call(k) }
230
+ @names = []
231
+ @aliases = {}
232
+ @summaries = {}
233
+ end
234
+
235
+ def add(klass, name, *aliases)
236
+ begin
237
+ cmd = klass.new
238
+ rescue StandardError => err
239
+ # don't add any commands you can't init
240
+ else
241
+ ([name] + aliases).each{ |n| @lookup[n] = cmd }
242
+ @to_s = nil
243
+ @names << name
244
+ @aliases[name] = aliases.empty? ? '' : "(#{aliases.join(', ')})"
245
+ @summaries[name] = cmd.summary.to_s.empty? ? '' : "# #{cmd.summary}"
246
+ end
247
+ end
248
+
249
+ def remove(name)
250
+ @lookup.delete(name)
251
+ @names.delete(name)
252
+ @aliases.delete(name)
253
+ @to_s = nil
254
+ end
255
+
256
+ def [](name)
257
+ @lookup[name]
258
+ end
259
+
260
+ def size
261
+ @names.size
262
+ end
263
+
264
+ def to_s
265
+ max_name_size = @names.map{ |n| n.size }.max || 0
266
+ max_alias_size = @aliases.values.map{ |v| v.size }.max || 0
267
+
268
+ @to_s ||= @names.map do |n|
269
+ "#{n.ljust(max_name_size)} #{@aliases[n].ljust(max_alias_size)} #{@summaries[n]}"
270
+ end.join("\n")
271
+ end
272
+
273
+ end
274
+
275
+ end
@@ -4,16 +4,18 @@ module Ardb
4
4
 
5
5
  class Migration
6
6
 
7
- attr_reader :identifier, :class_name, :file_name, :file_path
8
- attr_reader :source
7
+ attr_reader :migrations_path, :identifier
8
+ attr_reader :class_name, :file_name, :file_path, :source
9
9
 
10
- def initialize(identifier)
10
+ def initialize(ardb_config, identifier)
11
11
  raise NoIdentifierError if identifier.to_s.empty?
12
12
 
13
- @identifier = identifier
13
+ @migrations_path = ardb_config.migrations_path
14
+ @identifier = identifier
15
+
14
16
  @class_name = @identifier.classify.pluralize
15
17
  @file_name = get_file_name(@identifier)
16
- @file_path = File.join(Ardb.config.migrations_path, "#{@file_name}.rb")
18
+ @file_path = File.join(self.migrations_path, "#{@file_name}.rb")
17
19
 
18
20
  @source = "require 'ardb/migration_helpers'\n\n" \
19
21
  "class #{@class_name} < ActiveRecord::Migration\n" \
@@ -24,7 +26,7 @@ module Ardb
24
26
  end
25
27
 
26
28
  def save!
27
- FileUtils.mkdir_p Ardb.config.migrations_path
29
+ FileUtils.mkdir_p self.migrations_path
28
30
  File.open(self.file_path, 'w'){ |f| f.write(self.source) }
29
31
  self
30
32
  end
@@ -32,7 +32,7 @@ module Ardb
32
32
  @to_table = to_table.to_s
33
33
  @to_column = (options[:to_column] || 'id').to_s
34
34
  @name = (options[:name] || "fk_#{@from_table}_#{@from_column}").to_s
35
- @adapter = Ardb::Adapter.send(Ardb.config.db.adapter)
35
+ @adapter = Ardb::Adapter.new(Ardb.config)
36
36
  end
37
37
 
38
38
  def add_sql
@@ -0,0 +1,90 @@
1
+ require 'active_record'
2
+ require 'active_support'
3
+
4
+ # Allow ActiveRecord to work with PostgreSQL json/jsonb fields, which aren't
5
+ # supported with ActiveRecord 3.2
6
+ # https://github.com/romanbsd/activerecord-postgres-json/blob/master/lib/activerecord-postgres-json/activerecord.rb
7
+ require 'active_record/connection_adapters/postgresql_adapter'
8
+
9
+ module ActiveRecord
10
+ module ConnectionAdapters
11
+ PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:json] = { :name => 'json' }
12
+ PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:jsonb] = { :name => 'jsonb' }
13
+
14
+ class PostgreSQLColumn < Column
15
+ # Adds the json type for the column.
16
+ def simplified_type_with_json(field_type)
17
+ case field_type
18
+ when 'json'
19
+ :json
20
+ when 'jsonb'
21
+ :jsonb
22
+ else
23
+ simplified_type_without_json(field_type)
24
+ end
25
+ end
26
+
27
+ alias_method_chain :simplified_type, :json
28
+
29
+ class << self
30
+ def extract_value_from_default_with_json(default)
31
+ case default
32
+ when "'{}'::json", "'{}'::jsonb"
33
+ '{}'
34
+ when "'[]'::json", "'[]'::jsonb"
35
+ '[]'
36
+ else
37
+ extract_value_from_default_without_json(default)
38
+ end
39
+ end
40
+
41
+ alias_method_chain :extract_value_from_default, :json
42
+ end
43
+
44
+ end
45
+
46
+ class TableDefinition
47
+ # Adds json type for migrations. So you can add columns to a table like:
48
+ # create_table :people do |t|
49
+ # ...
50
+ # t.json :info
51
+ # ...
52
+ # end
53
+ def json(*args)
54
+ options = args.extract_options!
55
+ column_names = args
56
+ column_names.each { |name| column(name, 'json', options) }
57
+ end
58
+
59
+ def jsonb(*args)
60
+ options = args.extract_options!
61
+ column_names = args
62
+ column_names.each { |name| column(name, 'jsonb', options) }
63
+ end
64
+
65
+ end
66
+
67
+ class Table
68
+ # Adds json type for migrations. So you can add columns to a table like:
69
+ # change_table :people do |t|
70
+ # ...
71
+ # t.json :info
72
+ # ...
73
+ # end
74
+ def json(*args)
75
+ options = args.extract_options!
76
+ column_names = args
77
+ column_names.each { |name| column(name, 'json', options) }
78
+ end
79
+
80
+ def jsonb(*args)
81
+ options = args.extract_options!
82
+ column_names = args
83
+ column_names.each { |name| column(name, 'jsonb', options) }
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -1,3 +1,3 @@
1
1
  module Ardb
2
- VERSION = "0.27.3"
2
+ VERSION = "0.28.0"
3
3
  end
@@ -4,10 +4,22 @@
4
4
  # add the root dir to the load path
5
5
  $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
6
6
 
7
+ TEST_SUPPORT_PATH = File.expand_path("../support", __FILE__)
8
+ TMP_PATH = File.expand_path("../../tmp", __FILE__)
9
+
10
+ require 'logger'
11
+ log_path = File.expand_path("../../log/test.log", __FILE__)
12
+ TEST_LOGGER = Logger.new(File.open(log_path, 'w'))
13
+
7
14
  # require pry for debugging (`binding.pry`)
8
15
  require 'pry'
9
16
  require 'test/support/factory'
10
17
 
11
- ENV['ARDB_DB_FILE'] = 'tmp/testdb/config/db'
12
- require 'ardb'
13
- Ardb.init(false)
18
+ # 1.8.7 backfills
19
+
20
+ # Array#sample
21
+ if !(a = Array.new).respond_to?(:sample) && a.respond_to?(:choice)
22
+ class Array
23
+ alias_method :sample, :choice
24
+ end
25
+ end
@@ -8,4 +8,19 @@ module Factory
8
8
  "#{Factory.string}_things"
9
9
  end
10
10
 
11
+ def self.ardb_config
12
+ Ardb::Config.new.tap do |c|
13
+ c.adapter = Factory.string
14
+ c.database = Factory.string
15
+ c.encoding = Factory.string
16
+ c.host = Factory.string
17
+ c.port = Factory.integer
18
+ c.username = Factory.string
19
+ c.password = Factory.string
20
+ c.pool = Factory.integer
21
+ c.checkout_timeout = Factory.integer
22
+ c.min_messages = Factory.string
23
+ end
24
+ end
25
+
11
26
  end