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,18 +1,26 @@
1
- module Ardb; end
2
- class Ardb::Adapter
1
+ require "ardb"
3
2
 
3
+ module Ardb; end
4
+ module Ardb::Adapter
4
5
  class Base
6
+ attr_reader :config
7
+
8
+ def initialize(config)
9
+ @config = config
10
+ validate!
11
+ end
12
+
13
+ def connect_hash; self.config.activerecord_connect_hash; end
14
+ def database; self.config.database; end
15
+ def migrations_path; self.config.migrations_path; end
16
+ def schema_format; self.config.schema_format; end
5
17
 
6
- attr_reader :config_settings, :database
7
- attr_reader :schema_format, :ruby_schema_path, :sql_schema_path
18
+ def ruby_schema_path
19
+ @ruby_schema_path ||= "#{self.config.schema_path}.rb"
20
+ end
8
21
 
9
- def initialize
10
- @config_settings = Ardb.config.db_settings
11
- @database = Ardb.config.db.database
12
- @schema_format = Ardb.config.schema_format
13
- schema_path = Ardb.config.schema_path
14
- @ruby_schema_path = "#{schema_path}.rb"
15
- @sql_schema_path = "#{schema_path}.sql"
22
+ def sql_schema_path
23
+ @sql_schema_path ||= "#{self.config.schema_path}.sql"
16
24
  end
17
25
 
18
26
  def escape_like_pattern(pattern, escape_char = nil)
@@ -21,50 +29,51 @@ class Ardb::Adapter
21
29
  pattern.gsub!(escape_char){ escape_char * 2 }
22
30
  # don't allow custom wildcards
23
31
  pattern.gsub!(/%|_/){ |wildcard_char| "#{escape_char}#{wildcard_char}" }
32
+ pattern
24
33
  end
25
34
 
26
- def foreign_key_add_sql(*args); raise NotImplementedError; end
27
- def foreign_key_drop_sql(*args); raise NotImplementedError; end
28
-
29
35
  def create_db(*args); raise NotImplementedError; end
30
36
  def drop_db(*args); raise NotImplementedError; end
31
37
 
38
+ def drop_tables(*args); raise NotImplementedError; end
39
+
32
40
  def connect_db
33
- ActiveRecord::Base.connection
41
+ ActiveRecord::Base.establish_connection(self.connect_hash)
42
+ # checkout a connection to ensure we can connect to the DB, we don"t do
43
+ # anything with the connection and immediately check it back in
44
+ ActiveRecord::Base.connection_pool.with_connection{ }
34
45
  end
35
46
 
36
47
  def migrate_db
37
- verbose = ENV["MIGRATE_QUIET"].nil?
38
- version = ENV["MIGRATE_VERSION"] ? ENV["MIGRATE_VERSION"].to_i : nil
39
- migrations_path = Ardb.config.migrations_path
40
-
41
- if defined?(ActiveRecord::Migration::CommandRecorder)
42
- require 'ardb/migration_helpers'
43
- ActiveRecord::Migration::CommandRecorder.class_eval do
44
- include Ardb::MigrationHelpers::RecorderMixin
45
- end
46
- end
48
+ migrate_db_up
49
+ end
47
50
 
48
- ActiveRecord::Migrator.migrations_path = migrations_path
49
- ActiveRecord::Migration.verbose = verbose
50
- ActiveRecord::Migrator.migrate(migrations_path, version) do |migration|
51
- ENV["MIGRATE_SCOPE"].blank? || (ENV["MIGRATE_SCOPE"] == migration.scope)
52
- end
51
+ def migrate_db_up(target_version = nil)
52
+ migration_context.up(target_version)
53
53
  end
54
54
 
55
- def drop_tables(*args); raise NotImplementedError; end
55
+ def migrate_db_down(target_version = nil)
56
+ migration_context.down(target_version)
57
+ end
58
+
59
+ def migrate_db_forward(steps = 1)
60
+ migration_context.forward(steps)
61
+ end
62
+
63
+ def migrate_db_backward(steps = 1)
64
+ migration_context.rollback(steps)
65
+ end
56
66
 
57
67
  def load_schema
58
- # silence STDOUT
59
- current_stdout = $stdout.dup
60
- $stdout = File.new('/dev/null', 'w')
61
- load_ruby_schema if @schema_format == :ruby
62
- load_sql_schema if @schema_format == :sql
68
+ current_stdout = $stdout.dup # silence STDOUT
69
+ $stdout = File.new("/dev/null", "w")
70
+ load_ruby_schema if self.schema_format == Ardb::Config::RUBY_SCHEMA_FORMAT
71
+ load_sql_schema if self.schema_format == Ardb::Config::SQL_SCHEMA_FORMAT
63
72
  $stdout = current_stdout
64
73
  end
65
74
 
66
75
  def load_ruby_schema
67
- load @ruby_schema_path
76
+ load self.ruby_schema_path
68
77
  end
69
78
 
70
79
  def load_sql_schema
@@ -72,18 +81,17 @@ class Ardb::Adapter
72
81
  end
73
82
 
74
83
  def dump_schema
75
- # silence STDOUT
76
- current_stdout = $stdout.dup
77
- $stdout = File.new('/dev/null', 'w')
84
+ current_stdout = $stdout.dup # silence STDOUT
85
+ $stdout = File.new("/dev/null", "w")
78
86
  dump_ruby_schema
79
- dump_sql_schema if @schema_format == :sql
87
+ dump_sql_schema if self.schema_format == Ardb::Config::SQL_SCHEMA_FORMAT
80
88
  $stdout = current_stdout
81
89
  end
82
90
 
83
91
  def dump_ruby_schema
84
- require 'active_record/schema_dumper'
85
- FileUtils.mkdir_p File.dirname(@ruby_schema_path)
86
- File.open(@ruby_schema_path, 'w:utf-8') do |file|
92
+ require "active_record/schema_dumper"
93
+ FileUtils.mkdir_p File.dirname(self.ruby_schema_path)
94
+ File.open(self.ruby_schema_path, "w:utf-8") do |file|
87
95
  ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
88
96
  end
89
97
  end
@@ -92,10 +100,22 @@ class Ardb::Adapter
92
100
  raise NotImplementedError
93
101
  end
94
102
 
95
- def ==(other_adapter)
96
- self.class == other_adapter.class
103
+ def ==(other)
104
+ if other.kind_of?(self.class)
105
+ self.config == other.config
106
+ else
107
+ super
108
+ end
97
109
  end
98
110
 
99
- end
111
+ private
112
+
113
+ def validate!
114
+ # override as needed
115
+ end
100
116
 
117
+ def migration_context
118
+ ActiveRecord::MigrationContext.new(migrations_path)
119
+ end
120
+ end
101
121
  end
@@ -1,22 +1,6 @@
1
- require 'ardb'
2
- require 'ardb/adapter/base'
3
-
4
- class Ardb::Adapter
5
-
6
- class Mysql < Base
7
-
8
- def foreign_key_add_sql
9
- "ALTER TABLE :from_table"\
10
- " ADD CONSTRAINT :name"\
11
- " FOREIGN KEY (:from_column)"\
12
- " REFERENCES :to_table (:to_column)"
13
- end
14
-
15
- def foreign_key_drop_sql
16
- "ALTER TABLE :from_table"\
17
- " DROP FOREIGN KEY :name"
18
- end
1
+ require "ardb/adapter/base"
19
2
 
3
+ module Ardb::Adapter
4
+ class Mysql < Ardb::Adapter::Base
20
5
  end
21
-
22
6
  end
@@ -1,26 +1,26 @@
1
- require 'ardb'
2
- require 'ardb/adapter/base'
1
+ require "ardb/adapter/base"
3
2
 
4
- class Ardb::Adapter
5
-
6
- class Postgresql < Base
7
-
8
- def public_schema_settings
9
- self.config_settings.merge({
10
- 'database' => 'postgres',
11
- 'schema_search_path' => 'public'
3
+ module Ardb::Adapter
4
+ class Postgresql < Ardb::Adapter::Base
5
+ # the "postgres" db is a "public" (doesn"t typically require auth/grants to
6
+ # connect to) db that typically exists for all postgres installations; the
7
+ # adapter uses it to create/drop other databases
8
+ def public_connect_hash
9
+ @public_connect_hash ||= self.connect_hash.merge({
10
+ "database" => "postgres",
11
+ "schema_search_path" => "public"
12
12
  })
13
13
  end
14
14
 
15
15
  def create_db
16
- ActiveRecord::Base.establish_connection(self.public_schema_settings)
17
- ActiveRecord::Base.connection.create_database(self.database, self.config_settings)
18
- ActiveRecord::Base.establish_connection(self.config_settings)
16
+ ActiveRecord::Base.establish_connection(self.public_connect_hash)
17
+ ActiveRecord::Base.connection.create_database(self.database, self.connect_hash)
18
+ ActiveRecord::Base.establish_connection(self.connect_hash)
19
19
  end
20
20
 
21
21
  def drop_db
22
22
  begin
23
- ActiveRecord::Base.establish_connection(self.public_schema_settings)
23
+ ActiveRecord::Base.establish_connection(self.public_connect_hash)
24
24
  ActiveRecord::Base.connection.tap do |conn|
25
25
  conn.execute "UPDATE pg_catalog.pg_database"\
26
26
  " SET datallowconn=false WHERE datname='#{self.database}'"
@@ -40,47 +40,43 @@ class Ardb::Adapter
40
40
  tables = conn.execute "SELECT table_name"\
41
41
  " FROM information_schema.tables"\
42
42
  " WHERE table_schema = 'public';"
43
- tables.each{ |row| conn.execute "DROP TABLE #{row['table_name']} CASCADE" }
43
+ tables.each{ |row| conn.execute "DROP TABLE #{row["table_name"]} CASCADE" }
44
44
  end
45
45
  end
46
46
 
47
- def foreign_key_add_sql
48
- "ALTER TABLE :from_table"\
49
- " ADD CONSTRAINT :name"\
50
- " FOREIGN KEY (:from_column)"\
51
- " REFERENCES :to_table (:to_column)"
52
- end
53
-
54
- def foreign_key_drop_sql
55
- "ALTER TABLE :from_table"\
56
- " DROP CONSTRAINT :name"
57
- end
58
-
59
47
  def load_sql_schema
60
- require 'scmd'
48
+ require "scmd"
61
49
  cmd_str = "psql -f \"#{self.sql_schema_path}\" #{self.database}"
62
50
  cmd = Scmd.new(cmd_str, :env => env_var_hash).tap(&:run)
63
- raise 'Error loading database' unless cmd.success?
51
+ raise "Error loading database" unless cmd.success?
64
52
  end
65
53
 
66
54
  def dump_sql_schema
67
- require 'scmd'
55
+ require "scmd"
68
56
  cmd_str = "pg_dump -i -s -x -O -f \"#{self.sql_schema_path}\" #{self.database}"
69
57
  cmd = Scmd.new(cmd_str, :env => env_var_hash).tap(&:run)
70
- raise 'Error dumping database' unless cmd.success?
58
+ raise "Error dumping database" unless cmd.success?
71
59
  end
72
60
 
73
61
  private
74
62
 
63
+ def validate!
64
+ if self.database =~ /\W/
65
+ raise(
66
+ Ardb::ConfigurationError,
67
+ "database value must not contain non-word characters. "\
68
+ "Given: #{self.database.inspect}."
69
+ )
70
+ end
71
+ end
72
+
75
73
  def env_var_hash
76
74
  @env_var_hash ||= {
77
- 'PGHOST' => self.config_settings['host'],
78
- 'PGPORT' => self.config_settings['port'],
79
- 'PGUSER' => self.config_settings['username'],
80
- 'PGPASSWORD' => self.config_settings['password']
75
+ "PGHOST" => self.connect_hash["host"],
76
+ "PGPORT" => self.connect_hash["port"],
77
+ "PGUSER" => self.connect_hash["username"],
78
+ "PGPASSWORD" => self.connect_hash["password"]
81
79
  }
82
80
  end
83
-
84
81
  end
85
-
86
82
  end
@@ -1,18 +1,11 @@
1
- require 'pathname'
2
- require 'fileutils'
3
- require 'ardb'
4
- require 'ardb/adapter/base'
5
-
6
- class Ardb::Adapter
7
-
8
- class Sqlite < Base
1
+ require "fileutils"
2
+ require "ardb"
3
+ require "ardb/adapter/base"
9
4
 
5
+ module Ardb::Adapter
6
+ class Sqlite < Ardb::Adapter::Base
10
7
  def db_file_path
11
- if (path = Pathname.new(self.database)).absolute?
12
- path.to_s
13
- else
14
- Ardb.config.root_path.join(path).to_s
15
- end
8
+ File.expand_path(self.database, self.config.root_path)
16
9
  end
17
10
 
18
11
  def validate!
@@ -24,13 +17,11 @@ class Ardb::Adapter
24
17
  def create_db
25
18
  validate!
26
19
  FileUtils.mkdir_p File.dirname(self.db_file_path)
27
- ActiveRecord::Base.establish_connection(self.config_settings)
20
+ ActiveRecord::Base.establish_connection(self.connect_hash)
28
21
  end
29
22
 
30
23
  def drop_db
31
24
  FileUtils.rm(self.db_file_path) if File.exist?(self.db_file_path)
32
25
  end
33
-
34
26
  end
35
-
36
27
  end
@@ -1,114 +1,80 @@
1
- require 'much-plugin'
1
+ require "ardb"
2
+ require "ardb/adapter/base"
2
3
 
3
4
  module Ardb
4
-
5
- module AdapterSpy
6
- include MuchPlugin
7
-
8
- def self.new(&block)
9
- block ||= proc{ }
10
- record_spy = Class.new{ include Ardb::AdapterSpy }
11
- record_spy.class_eval(&block)
12
- record_spy
5
+ class AdapterSpy < Ardb::Adapter::Base
6
+ attr_accessor :drop_tables_called_count
7
+ attr_accessor :dump_schema_called_count, :load_schema_called_count
8
+ attr_accessor :drop_db_called_count, :create_db_called_count
9
+ attr_accessor :connect_db_called_count, :migrate_db_called_count
10
+
11
+ def initialize(config = nil)
12
+ super(config || Ardb::Config.new)
13
+ @drop_tables_called_count = 0
14
+ @dump_schema_called_count = 0
15
+ @load_schema_called_count = 0
16
+ @drop_db_called_count = 0
17
+ @create_db_called_count = 0
18
+ @connect_db_called_count = 0
19
+ @migrate_db_called_count = 0
13
20
  end
14
21
 
15
- plugin_included do
16
- include InstanceMethods
22
+ def create_db_called?
23
+ self.create_db_called_count > 0
17
24
  end
18
25
 
19
- module InstanceMethods
20
-
21
- attr_accessor :drop_tables_called_count
22
- attr_accessor :dump_schema_called_count, :load_schema_called_count
23
- attr_accessor :drop_db_called_count, :create_db_called_count
24
- attr_accessor :connect_db_called_count, :migrate_db_called_count
25
-
26
- def drop_tables_called_count
27
- @drop_tables_called_count ||= 0
28
- end
29
-
30
- def drop_tables_called?
31
- self.drop_tables_called_count > 0
32
- end
33
-
34
- def drop_tables(*args, &block)
35
- self.drop_tables_called_count += 1
36
- end
37
-
38
- def dump_schema_called_count
39
- @dump_schema_called_count ||= 0
40
- end
41
-
42
- def dump_schema_called?
43
- self.dump_schema_called_count > 0
44
- end
45
-
46
- def dump_schema(*args, &block)
47
- self.dump_schema_called_count += 1
48
- end
49
-
50
- def load_schema_called_count
51
- @load_schema_called_count ||= 0
52
- end
53
-
54
- def load_schema_called?
55
- self.load_schema_called_count > 0
56
- end
57
-
58
- def load_schema(*args, &block)
59
- self.load_schema_called_count += 1
60
- end
61
-
62
- def drop_db_called_count
63
- @drop_db_called_count ||= 0
64
- end
26
+ def drop_db_called?
27
+ self.drop_db_called_count > 0
28
+ end
65
29
 
66
- def drop_db_called?
67
- self.drop_db_called_count > 0
68
- end
30
+ def drop_tables_called?
31
+ self.drop_tables_called_count > 0
32
+ end
69
33
 
70
- def drop_db(*args, &block)
71
- self.drop_db_called_count += 1
72
- end
34
+ def connect_db_called?
35
+ self.connect_db_called_count > 0
36
+ end
73
37
 
74
- def create_db_called_count
75
- @create_db_called_count ||= 0
76
- end
38
+ def migrate_db_called?
39
+ self.migrate_db_called_count > 0
40
+ end
77
41
 
78
- def create_db_called?
79
- self.create_db_called_count > 0
80
- end
42
+ def load_schema_called?
43
+ self.load_schema_called_count > 0
44
+ end
81
45
 
82
- def create_db(*args, &block)
83
- self.create_db_called_count += 1
84
- end
46
+ def dump_schema_called?
47
+ self.dump_schema_called_count > 0
48
+ end
85
49
 
86
- def connect_db_called_count
87
- @connect_db_called_count ||= 0
88
- end
50
+ # Overwritten `Adapter::Base` methods
89
51
 
90
- def connect_db_called?
91
- self.connect_db_called_count > 0
92
- end
52
+ def create_db(*args, &block)
53
+ self.create_db_called_count += 1
54
+ end
93
55
 
94
- def connect_db(*args, &block)
95
- self.connect_db_called_count += 1
96
- end
56
+ def drop_db(*args, &block)
57
+ self.drop_db_called_count += 1
58
+ end
97
59
 
98
- def migrate_db_called_count
99
- @migrate_db_called_count ||= 0
100
- end
60
+ def drop_tables(*args, &block)
61
+ self.drop_tables_called_count += 1
62
+ end
101
63
 
102
- def migrate_db_called?
103
- self.migrate_db_called_count > 0
104
- end
64
+ def connect_db(*args, &block)
65
+ self.connect_db_called_count += 1
66
+ end
105
67
 
106
- def migrate_db(*args, &block)
107
- self.migrate_db_called_count += 1
108
- end
68
+ def migrate_db(*args, &block)
69
+ self.migrate_db_called_count += 1
70
+ end
109
71
 
72
+ def load_schema(*args, &block)
73
+ self.load_schema_called_count += 1
110
74
  end
111
75
 
76
+ def dump_schema(*args, &block)
77
+ self.dump_schema_called_count += 1
78
+ end
112
79
  end
113
-
114
80
  end