ardb 0.28.3 → 0.30.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.
- checksums.yaml +7 -7
- data/.l.yml +9 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -0
- data/.t.yml +6 -0
- data/Gemfile +24 -8
- data/README.md +252 -3
- data/ardb.gemspec +14 -10
- data/bin/ardb +3 -1
- data/lib/ardb/adapter/base.rb +72 -47
- data/lib/ardb/adapter/mysql.rb +4 -17
- data/lib/ardb/adapter/postgresql.rb +51 -46
- data/lib/ardb/adapter/sqlite.rb +11 -15
- data/lib/ardb/adapter_spy.rb +18 -30
- data/lib/ardb/cli/clirb.rb +16 -18
- data/lib/ardb/cli/commands.rb +308 -129
- data/lib/ardb/cli.rb +29 -24
- data/lib/ardb/db_tests.rb +4 -4
- data/lib/ardb/default_order_by.rb +13 -21
- data/lib/ardb/migration.rb +15 -16
- data/lib/ardb/record_spy.rb +46 -61
- data/lib/ardb/relation_spy.rb +28 -32
- data/lib/ardb/require_autoloaded_active_record_files.rb +258 -57
- data/lib/ardb/test_helpers.rb +33 -29
- data/lib/ardb/use_db_default.rb +13 -21
- data/lib/ardb/version.rb +3 -1
- data/lib/ardb.rb +105 -86
- data/script/determine_autoloaded_active_record_files.rb +31 -24
- data/test/helper.rb +6 -13
- data/test/support/factory.rb +4 -3
- data/test/support/fake_schema.rb +3 -1
- data/test/support/postgresql/migrations/{.gitkeep → .keep} +0 -0
- data/test/support/postgresql/schema.rb +2 -1
- data/test/support/postgresql/setup_test_db.rb +23 -21
- data/test/support/relative_require_test_db_file.rb +1 -0
- data/test/support/require_test_db_file.rb +1 -0
- data/test/system/.keep +0 -0
- data/test/unit/adapter/base_tests.rb +80 -55
- data/test/unit/adapter/mysql_tests.rb +4 -19
- data/test/unit/adapter/postgresql_tests.rb +21 -30
- data/test/unit/adapter/sqlite_tests.rb +5 -11
- data/test/unit/adapter_spy_tests.rb +6 -17
- data/test/unit/ardb_tests.rb +75 -53
- data/test/unit/cli_tests.rb +234 -158
- data/test/unit/db_tests_tests.rb +7 -7
- data/test/unit/default_order_by_tests.rb +26 -24
- data/test/unit/migration_tests.rb +17 -18
- data/test/unit/record_spy_tests.rb +45 -41
- data/test/unit/relation_spy_tests.rb +40 -63
- data/test/unit/test_helpers_tests.rb +7 -15
- data/test/unit/use_db_default_tests.rb +35 -27
- metadata +109 -87
- data/lib/ardb/has_slug.rb +0 -107
- data/lib/ardb/migration_helpers.rb +0 -77
- data/lib/ardb/pg_json.rb +0 -90
- data/test/support/postgresql/pg_json_migrations/20160519133432_create_pg_json_migrate_test.rb +0 -13
- data/test/system/pg_json_tests.rb +0 -85
- data/test/unit/has_slug_tests.rb +0 -341
- data/test/unit/migration_helpers_tests.rb +0 -65
- data/test/unit/pg_json_tests.rb +0 -39
data/lib/ardb.rb
CHANGED
@@ -1,97 +1,109 @@
|
|
1
|
-
|
2
|
-
require 'logger'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
3
|
+
require "active_record"
|
4
|
+
require "logger"
|
5
5
|
|
6
|
-
|
6
|
+
require "ardb/version"
|
7
7
|
|
8
|
-
|
8
|
+
ENV["ARDB_DB_FILE"] ||= "config/db"
|
9
9
|
|
10
|
+
module Ardb
|
10
11
|
def self.config
|
11
12
|
@config ||= Config.new
|
12
13
|
end
|
13
14
|
|
14
15
|
def self.configure(&block)
|
15
|
-
|
16
|
+
config.tap(&block)
|
16
17
|
end
|
17
18
|
|
18
19
|
def self.adapter
|
19
20
|
@adapter || raise(NotInitializedError.new(caller))
|
20
21
|
end
|
21
22
|
|
22
|
-
def self.reset_adapter
|
23
|
+
def self.reset_adapter
|
24
|
+
@adapter = nil
|
25
|
+
end
|
23
26
|
|
24
27
|
def self.init(establish_connection = true)
|
25
|
-
require
|
28
|
+
require "ardb/require_autoloaded_active_record_files"
|
26
29
|
begin
|
27
30
|
require_db_file
|
28
|
-
rescue InvalidDBFileError =>
|
29
|
-
|
30
|
-
raise
|
31
|
+
rescue InvalidDBFileError => ex
|
32
|
+
ex.set_backtrace(caller)
|
33
|
+
raise ex
|
31
34
|
end
|
32
35
|
|
33
|
-
|
34
|
-
@adapter = Adapter.new(
|
36
|
+
config.validate!
|
37
|
+
@adapter = Adapter.new(config)
|
35
38
|
|
36
39
|
# setup AR
|
37
|
-
ActiveRecord
|
38
|
-
|
40
|
+
if ActiveRecord.respond_to?(:default_timezone=)
|
41
|
+
ActiveRecord.default_timezone = config.default_timezone
|
42
|
+
else
|
43
|
+
ActiveRecord::Base.default_timezone = config.default_timezone
|
44
|
+
end
|
45
|
+
ActiveRecord::Base.logger = config.logger
|
46
|
+
adapter.connect_db if establish_connection
|
39
47
|
end
|
40
48
|
|
41
49
|
def self.escape_like_pattern(pattern, escape_char = nil)
|
42
|
-
|
43
|
-
rescue NotInitializedError =>
|
44
|
-
|
45
|
-
raise
|
50
|
+
adapter.escape_like_pattern(pattern, escape_char)
|
51
|
+
rescue NotInitializedError => ex
|
52
|
+
ex.set_backtrace(caller)
|
53
|
+
raise ex
|
46
54
|
end
|
47
55
|
|
48
|
-
private
|
49
|
-
|
50
56
|
# try requiring the db file via the load path or as an absolute path, if
|
51
57
|
# that fails it tries requiring relative to the current working directory
|
52
58
|
def self.require_db_file
|
53
59
|
begin
|
54
|
-
|
60
|
+
begin
|
61
|
+
require ENV["ARDB_DB_FILE"]
|
62
|
+
rescue LoadError
|
63
|
+
require File.expand_path(ENV["ARDB_DB_FILE"], ENV["PWD"])
|
64
|
+
end
|
55
65
|
rescue LoadError
|
56
|
-
|
66
|
+
raise(
|
67
|
+
InvalidDBFileError,
|
68
|
+
"can't require `#{ENV["ARDB_DB_FILE"]}`, check that the ARDB_DB_FILE "\
|
69
|
+
"env var is set to the file path of your db file",
|
70
|
+
)
|
57
71
|
end
|
58
|
-
rescue LoadError
|
59
|
-
raise InvalidDBFileError, "can't require `#{ENV['ARDB_DB_FILE']}`, " \
|
60
|
-
"check that the ARDB_DB_FILE env var is set to " \
|
61
|
-
"the file path of your db file"
|
62
72
|
end
|
63
73
|
|
64
74
|
class Config
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
ACTIVERECORD_ATTRS =
|
76
|
+
[
|
77
|
+
:adapter,
|
78
|
+
:database,
|
79
|
+
:encoding,
|
80
|
+
:host,
|
81
|
+
:port,
|
82
|
+
:username,
|
83
|
+
:password,
|
84
|
+
:pool,
|
85
|
+
:checkout_timeout,
|
86
|
+
:min_messages,
|
87
|
+
].freeze
|
88
|
+
|
89
|
+
DEFAULT_MIGRATIONS_PATH = "db/migrations"
|
90
|
+
DEFAULT_SCHEMA_PATH = "db/schema"
|
91
|
+
RUBY_SCHEMA_FORMAT = :ruby
|
92
|
+
SQL_SCHEMA_FORMAT = :sql
|
82
93
|
VALID_SCHEMA_FORMATS = [RUBY_SCHEMA_FORMAT, SQL_SCHEMA_FORMAT].freeze
|
83
94
|
|
84
|
-
attr_accessor
|
85
|
-
attr_accessor :logger, :root_path
|
95
|
+
attr_accessor(*ACTIVERECORD_ATTRS)
|
96
|
+
attr_accessor :default_timezone, :logger, :root_path
|
86
97
|
attr_reader :schema_format
|
87
98
|
attr_writer :migrations_path, :schema_path
|
88
99
|
|
89
100
|
def initialize
|
90
|
-
@
|
91
|
-
@
|
92
|
-
@
|
93
|
-
@
|
94
|
-
@
|
101
|
+
@default_timezone = :utc
|
102
|
+
@logger = Logger.new(STDOUT)
|
103
|
+
@root_path = ENV["PWD"]
|
104
|
+
@migrations_path = DEFAULT_MIGRATIONS_PATH
|
105
|
+
@schema_path = DEFAULT_SCHEMA_PATH
|
106
|
+
@schema_format = RUBY_SCHEMA_FORMAT
|
95
107
|
end
|
96
108
|
|
97
109
|
def migrations_path
|
@@ -103,84 +115,92 @@ module Ardb
|
|
103
115
|
end
|
104
116
|
|
105
117
|
def schema_format=(new_value)
|
106
|
-
@schema_format =
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
118
|
+
@schema_format =
|
119
|
+
begin
|
120
|
+
new_value.to_sym
|
121
|
+
rescue NoMethodError
|
122
|
+
raise ArgumentError, "schema format must be a `Symbol`", caller
|
123
|
+
end
|
111
124
|
end
|
112
125
|
|
113
126
|
def activerecord_connect_hash
|
114
|
-
ACTIVERECORD_ATTRS.
|
115
|
-
value =
|
127
|
+
ACTIVERECORD_ATTRS.reduce({}) do |h, attr_name|
|
128
|
+
value = send(attr_name)
|
116
129
|
!value.nil? ? h.merge!(attr_name.to_s => value) : h
|
117
130
|
end
|
118
131
|
end
|
119
132
|
|
120
133
|
def validate!
|
121
|
-
if
|
134
|
+
if adapter.to_s.empty? || database.to_s.empty?
|
122
135
|
raise ConfigurationError, "an adapter and database must be provided"
|
123
|
-
|
136
|
+
end
|
137
|
+
|
138
|
+
unless VALID_SCHEMA_FORMATS.include?(schema_format)
|
124
139
|
raise ConfigurationError, "schema format must be one of: " \
|
125
|
-
"#{VALID_SCHEMA_FORMATS.join(
|
140
|
+
"#{VALID_SCHEMA_FORMATS.join(", ")}"
|
126
141
|
end
|
142
|
+
|
127
143
|
true
|
128
144
|
end
|
129
145
|
|
130
146
|
def ==(other)
|
131
|
-
if other.
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
147
|
+
if other.is_a?(self.class)
|
148
|
+
activerecord_connect_hash == other.activerecord_connect_hash &&
|
149
|
+
default_timezone == other.default_timezone &&
|
150
|
+
logger == other.logger &&
|
151
|
+
root_path == other.root_path &&
|
152
|
+
schema_format == other.schema_format &&
|
153
|
+
migrations_path == other.migrations_path &&
|
154
|
+
schema_path == other.schema_path
|
138
155
|
else
|
139
156
|
super
|
140
157
|
end
|
141
158
|
end
|
142
|
-
|
143
159
|
end
|
144
160
|
|
145
161
|
module Adapter
|
146
|
-
|
147
162
|
VALID_ADAPTERS = [
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
163
|
+
"sqlite",
|
164
|
+
"sqlite3",
|
165
|
+
"postgresql",
|
166
|
+
"postgres",
|
167
|
+
"mysql",
|
168
|
+
"mysql2",
|
154
169
|
].freeze
|
155
170
|
|
156
171
|
def self.new(config)
|
157
|
-
|
172
|
+
unless VALID_ADAPTERS.include?(config.adapter)
|
158
173
|
raise InvalidAdapterError, "invalid adapter: `#{config.adapter}`"
|
159
174
|
end
|
160
|
-
|
175
|
+
send(config.adapter, config)
|
161
176
|
end
|
162
177
|
|
163
178
|
def self.sqlite(config)
|
164
|
-
require
|
179
|
+
require "ardb/adapter/sqlite"
|
165
180
|
Adapter::Sqlite.new(config)
|
166
181
|
end
|
167
182
|
|
168
|
-
def self.sqlite3(config)
|
183
|
+
def self.sqlite3(config)
|
184
|
+
sqlite(config)
|
185
|
+
end
|
169
186
|
|
170
187
|
def self.postgresql(config)
|
171
|
-
require
|
188
|
+
require "ardb/adapter/postgresql"
|
172
189
|
Adapter::Postgresql.new(config)
|
173
190
|
end
|
174
191
|
|
175
|
-
def self.postgres(config)
|
192
|
+
def self.postgres(config)
|
193
|
+
postgresql(config)
|
194
|
+
end
|
176
195
|
|
177
196
|
def self.mysql(config)
|
178
|
-
require
|
197
|
+
require "ardb/adapter/mysql"
|
179
198
|
Adapter::Mysql.new(config)
|
180
199
|
end
|
181
200
|
|
182
|
-
def self.mysql2(config)
|
183
|
-
|
201
|
+
def self.mysql2(config)
|
202
|
+
mysql(config)
|
203
|
+
end
|
184
204
|
end
|
185
205
|
|
186
206
|
InvalidDBFileError = Class.new(ArgumentError)
|
@@ -193,5 +213,4 @@ module Ardb
|
|
193
213
|
set_backtrace(backtrace)
|
194
214
|
end
|
195
215
|
end
|
196
|
-
|
197
216
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
# this can be slow, this is one of the reasons this shouldn"t be done during
|
4
6
|
# the startup of our apps
|
5
|
-
gemspec = Gem.loaded_specs[
|
7
|
+
gemspec = Gem.loaded_specs["activerecord"]
|
6
8
|
|
7
9
|
puts "Looking at files in: "
|
8
10
|
puts " #{gemspec.lib_dirs_glob.inspect}"
|
@@ -11,16 +13,21 @@ paths = Dir["#{gemspec.lib_dirs_glob}/**/*.rb"]
|
|
11
13
|
|
12
14
|
# these are regexs for files we want to ignore requiring. for example,
|
13
15
|
# generators fail when we try to require them. the others are pieces of active
|
14
|
-
# record we don
|
16
|
+
# record we don"t use in a production environment
|
15
17
|
ignored_regexes = [
|
16
|
-
/
|
17
|
-
/
|
18
|
-
/
|
19
|
-
/
|
20
|
-
/
|
21
|
-
/
|
22
|
-
/
|
23
|
-
|
18
|
+
%r{rails/generators},
|
19
|
+
%r{active_record/railtie},
|
20
|
+
%r{active_record/migration},
|
21
|
+
%r{active_record/fixtures},
|
22
|
+
%r{active_record/fixture_set},
|
23
|
+
%r{active_record/schema},
|
24
|
+
%r{active_record/connection_adapters},
|
25
|
+
%r{active_record/test_case},
|
26
|
+
%r{active_record/test_databases},
|
27
|
+
%r{active_record/test_fixtures},
|
28
|
+
%r{active_record/coders/yaml_column},
|
29
|
+
# `destroy_association_async_job` requires `ActiveJob` to be required.
|
30
|
+
%r{active_record/destroy_association_async_job},
|
24
31
|
]
|
25
32
|
|
26
33
|
Result = Struct.new(:file, :state, :reason)
|
@@ -31,18 +38,18 @@ ignored = []
|
|
31
38
|
errored = []
|
32
39
|
|
33
40
|
paths.sort.each do |full_path|
|
34
|
-
relative_path_with_rb = full_path.gsub("#{gemspec.lib_dirs_glob}/",
|
35
|
-
relative_path = relative_path_with_rb.gsub(/\.rb\z/,
|
41
|
+
relative_path_with_rb = full_path.gsub("#{gemspec.lib_dirs_glob}/", "")
|
42
|
+
relative_path = relative_path_with_rb.gsub(/\.rb\z/, "")
|
36
43
|
|
37
44
|
result = Result.new(relative_path)
|
38
45
|
|
39
|
-
# see if it
|
46
|
+
# see if it"s ignored
|
40
47
|
ignored_regexes.each do |regex|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
48
|
+
next unless relative_path =~ regex
|
49
|
+
|
50
|
+
result.state = :ignored
|
51
|
+
result.reason = "matched #{regex}"
|
52
|
+
break
|
46
53
|
end
|
47
54
|
if result.state == :ignored
|
48
55
|
ignored << result
|
@@ -51,14 +58,14 @@ paths.sort.each do |full_path|
|
|
51
58
|
|
52
59
|
# try requiring the file
|
53
60
|
begin
|
54
|
-
if result.state = require(relative_path)
|
61
|
+
if (result.state = require(relative_path))
|
55
62
|
needs_to_be_required << result
|
56
63
|
else
|
57
64
|
already_required << result
|
58
65
|
end
|
59
|
-
rescue LoadError, SyntaxError =>
|
66
|
+
rescue LoadError, SyntaxError => ex
|
60
67
|
result.state = :errored
|
61
|
-
result.reason = "#{
|
68
|
+
result.reason = "#{ex.class}: #{ex.message}"
|
62
69
|
errored << result
|
63
70
|
end
|
64
71
|
end
|
@@ -87,5 +94,5 @@ puts "\n"
|
|
87
94
|
|
88
95
|
puts "Needs To Be Required:\n"
|
89
96
|
needs_to_be_required.each do |result|
|
90
|
-
puts "require
|
97
|
+
puts "require \"#{result.file}\""
|
91
98
|
end
|
data/test/helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# this file is automatically required when you run `assert`
|
2
4
|
# put any test helpers here
|
3
5
|
|
@@ -7,19 +9,10 @@ $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
|
|
7
9
|
TEST_SUPPORT_PATH = File.expand_path("../support", __FILE__)
|
8
10
|
TMP_PATH = File.expand_path("../../tmp", __FILE__)
|
9
11
|
|
10
|
-
require
|
12
|
+
require "logger"
|
11
13
|
log_path = File.expand_path("../../log/test.log", __FILE__)
|
12
|
-
TEST_LOGGER = Logger.new(File.open(log_path,
|
14
|
+
TEST_LOGGER = Logger.new(File.open(log_path, "w"))
|
13
15
|
|
14
16
|
# require pry for debugging (`binding.pry`)
|
15
|
-
require
|
16
|
-
require
|
17
|
-
|
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
|
17
|
+
require "pry"
|
18
|
+
require "test/support/factory"
|
data/test/support/factory.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "assert/factory"
|
2
4
|
|
3
5
|
module Factory
|
4
6
|
extend Assert::Factory
|
5
7
|
|
6
8
|
def self.migration_id
|
7
|
-
# identifiers need to be plural b/c af activesupport
|
9
|
+
# identifiers need to be plural b/c af activesupport"s pluralize
|
8
10
|
"#{Factory.string}_things"
|
9
11
|
end
|
10
12
|
|
@@ -22,5 +24,4 @@ module Factory
|
|
22
24
|
c.min_messages = Factory.string
|
23
25
|
end
|
24
26
|
end
|
25
|
-
|
26
27
|
end
|
data/test/support/fake_schema.rb
CHANGED
File without changes
|
@@ -1,26 +1,29 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "assert"
|
4
|
+
require "ardb"
|
3
5
|
|
4
6
|
class PostgresqlDbTests < Assert::Context
|
5
7
|
setup do
|
6
|
-
@orig_env_ardb_db_file = ENV[
|
8
|
+
@orig_env_ardb_db_file = ENV["ARDB_DB_FILE"]
|
7
9
|
ActiveRecord::Base.logger = @orig_ar_loggerF
|
8
10
|
|
9
|
-
#
|
10
|
-
ENV[
|
11
|
-
|
12
|
-
@ardb_config =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
11
|
+
# we"re manually configuring ardb so we don"t need this to do anything
|
12
|
+
ENV["ARDB_DB_FILE"] = File.join(TEST_SUPPORT_PATH, "require_test_db_file")
|
13
|
+
|
14
|
+
@ardb_config =
|
15
|
+
Ardb::Config.new.tap do |c|
|
16
|
+
c.adapter = "postgresql"
|
17
|
+
c.database = "redding_ardb_test"
|
18
|
+
c.encoding = "unicode"
|
19
|
+
c.min_messages = "WARNING"
|
20
|
+
|
21
|
+
c.logger = TEST_LOGGER
|
22
|
+
c.root_path = File.join(TEST_SUPPORT_PATH, "postgresql")
|
23
|
+
c.migrations_path = "migrations"
|
24
|
+
c.schema_path = "schema"
|
25
|
+
c.schema_format = :ruby
|
26
|
+
end
|
24
27
|
Assert.stub(Ardb, :config){ @ardb_config }
|
25
28
|
|
26
29
|
Ardb.init(false)
|
@@ -33,7 +36,7 @@ class PostgresqlDbTests < Assert::Context
|
|
33
36
|
teardown do
|
34
37
|
Ardb.reset_adapter
|
35
38
|
ActiveRecord::Base.logger = @orig_ar_logger
|
36
|
-
ENV[
|
39
|
+
ENV["ARDB_DB_FILE"] = @orig_env_ardb_db_file
|
37
40
|
end
|
38
41
|
|
39
42
|
private
|
@@ -41,12 +44,11 @@ class PostgresqlDbTests < Assert::Context
|
|
41
44
|
# useful when testing creating/dropping/migrating DBs
|
42
45
|
def silence_stdout
|
43
46
|
current_stdout = $stdout.dup
|
44
|
-
$stdout = File.new(
|
47
|
+
$stdout = File.new("/dev/null", "w")
|
45
48
|
begin
|
46
49
|
yield
|
47
50
|
ensure
|
48
51
|
$stdout = current_stdout
|
49
52
|
end
|
50
53
|
end
|
51
|
-
|
52
54
|
end
|
data/test/system/.keep
ADDED
File without changes
|