storey 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/README.md +17 -10
- data/gemfiles/rails_5.0.gemfile.lock +3 -1
- data/gemfiles/rails_5.1.gemfile.lock +3 -1
- data/gemfiles/rails_5.2.gemfile.lock +3 -1
- data/lib/storey.rb +42 -17
- data/lib/storey/duplicator.rb +23 -20
- data/lib/storey/gen_dump_command.rb +52 -0
- data/lib/storey/gen_load_command.rb +41 -0
- data/lib/storey/hstore.rb +1 -1
- data/lib/storey/sql_dumper.rb +2 -2
- data/lib/storey/suffixifier.rb +1 -1
- data/lib/storey/unsuffixifier.rb +1 -1
- data/lib/storey/version.rb +1 -1
- data/lib/tasks/storey.rake +1 -1
- data/spec/lib/storey_spec.rb +16 -0
- data/spec/storey/configuration_spec.rb +4 -4
- data/spec/storey/create_plain_schema_spec.rb +3 -3
- data/spec/storey/create_spec.rb +1 -1
- data/spec/storey/default_search_path_spec.rb +2 -2
- data/spec/storey/drop_spec.rb +1 -1
- data/spec/storey/duplicate_spec.rb +1 -9
- data/spec/storey/duplicator_spec.rb +9 -8
- data/spec/storey/excluded_models_spec.rb +6 -3
- data/spec/storey/{builds_dump_command_spec.rb → gen_dump_command_spec.rb} +52 -4
- data/spec/storey/{builds_load_command_spec.rb → gen_load_command_spec.rb} +35 -4
- data/spec/storey/hstore_spec.rb +2 -2
- data/spec/storey/schema_exists_spec.rb +1 -1
- data/spec/storey/schema_search_path_for_spec.rb +1 -1
- data/spec/storey/schema_spec.rb +1 -1
- data/spec/storey/schemas_spec.rb +1 -1
- data/spec/storey/suffixifier_spec.rb +2 -2
- data/spec/storey/switch_spec.rb +6 -6
- data/spec/storey/unsuffixifier_spec.rb +1 -1
- data/storey.gemspec +1 -0
- metadata +24 -8
- data/lib/storey/builds_dump_command.rb +0 -42
- data/lib/storey/builds_load_command.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d868102f5a1ce14a7d937639ab4cda6b59ed9d10be52bee5ce219d46cadddfc
|
4
|
+
data.tar.gz: b6d1ae7e3276463d5fed292024f5d2ea19be909d5fa9075bc4e731a5d1127fda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9838fa46e3d3c84c17e2994587759db404ca47e6bbb1dc666bf76cc9c79348d6fad7dc677cfd5967af376d385e4eb3532eed4f2eb7d50a078788dcc3eb87a82b
|
7
|
+
data.tar.gz: 8d45a6ad1b0cac2f3a3b708b070684b7ff3134b8b41a7e38fbc8b4c135f27f91ab45bb363d48dfc4cc9b5723e9b18574f794ce7c6ed546dde20279bc81f5d4a7
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
4
4
|
|
5
|
+
## [2.1.0] - 2018-07-04
|
6
|
+
### Added
|
7
|
+
- Print duplication stdout for debugging
|
8
|
+
- Allow users to set `database_url` in the config
|
9
|
+
- Deprecate setting of config through `Storey`; set through configuration
|
10
|
+
|
5
11
|
## [2.0.2] - 2018-06-29
|
6
12
|
### Fixed
|
7
13
|
- Fix instances when the default schema is the wrong schema
|
data/README.md
CHANGED
@@ -10,17 +10,24 @@ Heavily inspired by the Apartment gem, Storey simplifies the implementation of m
|
|
10
10
|
|
11
11
|
Typically set in an initializer: `config/initializer/storey.rb`
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
```ruby
|
14
|
+
Storey.configure do |c|
|
15
|
+
# Defines the tables that should stay available to all (ie in the public schema)
|
16
|
+
# Note that there's currently no way to exclude tables that aren't linked to models
|
17
|
+
# If you have any ideas on how to do this I'm open to suggestions
|
18
|
+
c.excluded_models = %w(User Company Role Permission)
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
# If set, all schemas are created with the suffix.
|
21
|
+
# Used for obscuring the schema name - which is important when performing schema duplication.
|
22
|
+
# c.suffix = "_suffix"
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
+
# Defines schemas that should always stay in the search path, apart from the one you switched to.
|
25
|
+
# c.persistent_schemas = %w(hstore)
|
26
|
+
|
27
|
+
# If you use a connection string, set it here. When nil, it falls back to the configuration in database.yml
|
28
|
+
c.database_url = ENV["DATABASE_URL"]
|
29
|
+
end
|
30
|
+
```
|
24
31
|
|
25
32
|
# Methods
|
26
33
|
|
@@ -104,7 +111,7 @@ Accepts
|
|
104
111
|
origin - name of old schema to copy
|
105
112
|
copy - name of new schema
|
106
113
|
|
107
|
-
Copies a schema with all data under a new name. Best used in conjunction with `Storey.suffix` set.
|
114
|
+
Copies a schema with all data under a new name. Best used in conjunction with `Storey.configuration.suffix` set.
|
108
115
|
|
109
116
|
Usage:
|
110
117
|
|
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
storey (2.0
|
4
|
+
storey (2.1.0)
|
5
5
|
easy_class_to_instance_method (~> 0.0.2)
|
6
|
+
gem_config
|
6
7
|
pg
|
7
8
|
rails (>= 4.0.0)
|
8
9
|
|
@@ -59,6 +60,7 @@ GEM
|
|
59
60
|
diff-lcs (1.3)
|
60
61
|
easy_class_to_instance_method (0.0.2)
|
61
62
|
erubis (2.7.0)
|
63
|
+
gem_config (0.3.1)
|
62
64
|
globalid (0.4.1)
|
63
65
|
activesupport (>= 4.2.0)
|
64
66
|
i18n (0.9.5)
|
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
storey (2.0
|
4
|
+
storey (2.1.0)
|
5
5
|
easy_class_to_instance_method (~> 0.0.2)
|
6
|
+
gem_config
|
6
7
|
pg
|
7
8
|
rails (>= 4.0.0)
|
8
9
|
|
@@ -59,6 +60,7 @@ GEM
|
|
59
60
|
diff-lcs (1.3)
|
60
61
|
easy_class_to_instance_method (0.0.2)
|
61
62
|
erubi (1.7.1)
|
63
|
+
gem_config (0.3.1)
|
62
64
|
globalid (0.4.1)
|
63
65
|
activesupport (>= 4.2.0)
|
64
66
|
i18n (1.0.1)
|
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
storey (2.0
|
4
|
+
storey (2.1.0)
|
5
5
|
easy_class_to_instance_method (~> 0.0.2)
|
6
|
+
gem_config
|
6
7
|
pg
|
7
8
|
rails (>= 4.0.0)
|
8
9
|
|
@@ -63,6 +64,7 @@ GEM
|
|
63
64
|
diff-lcs (1.3)
|
64
65
|
easy_class_to_instance_method (0.0.2)
|
65
66
|
erubi (1.7.1)
|
67
|
+
gem_config (0.3.1)
|
66
68
|
globalid (0.4.1)
|
67
69
|
activesupport (>= 4.2.0)
|
68
70
|
i18n (1.0.1)
|
data/lib/storey.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "gem_config"
|
1
2
|
require 'easy_class_to_instance_method'
|
2
3
|
require "active_support/core_ext/module" # so we can use mattr_accessor
|
3
4
|
require "open3"
|
@@ -17,8 +18,8 @@ require 'storey/suffixifier'
|
|
17
18
|
require 'storey/unsuffixifier'
|
18
19
|
require 'storey/resets_column_info'
|
19
20
|
require 'storey/utils'
|
20
|
-
require 'storey/
|
21
|
-
require 'storey/
|
21
|
+
require 'storey/gen_dump_command'
|
22
|
+
require 'storey/gen_load_command'
|
22
23
|
require 'storey/schema_name'
|
23
24
|
require 'storey/sets_env_password'
|
24
25
|
require 'storey/get_migration_versions'
|
@@ -30,16 +31,37 @@ module Storey
|
|
30
31
|
mattr_reader :excluded_models
|
31
32
|
extend self
|
32
33
|
|
34
|
+
include GemConfig::Base
|
35
|
+
with_configuration do
|
36
|
+
has :database_url, classes: [String, NilClass]
|
37
|
+
has :suffix, classes: [String, NilClass]
|
38
|
+
has :persistent_schemas, classes: Array, default: []
|
39
|
+
has :excluded_models, classes: Array, default: []
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.persistent_schemas=(schemas)
|
43
|
+
deprecate "setting persistent schemas directly via `Storey.persistent_schemas=` is deprecated. Please use `Storey.configure {|c| c.persistent_schemas = %w(hstore) }` instead."
|
44
|
+
self.configuration.persistent_schemas = schemas
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.suffix=(s)
|
48
|
+
deprecate "setting suffix directly via `Storey.suffix=` is deprecated. Please use `Storey.configure {|c| c.suffix = %w(_mysfx) }` instead."
|
49
|
+
self.configuration.suffix = s
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.excluded_models=(models)
|
53
|
+
deprecate "setting models directly via `Storey.excluded_models=` is deprecated. Please use `Storey.configure {|c| c.excluded_models = %w(User Setting) }` instead."
|
54
|
+
self.configuration.excluded_models = models
|
55
|
+
end
|
56
|
+
|
33
57
|
def init
|
34
|
-
self.excluded_models ||= []
|
35
|
-
self.persistent_schemas ||= []
|
36
58
|
process_excluded_models
|
37
59
|
end
|
38
60
|
|
39
61
|
def default_search_path
|
40
62
|
set_default_search_path
|
41
63
|
default_search_paths = @@default_search_path.split(',')
|
42
|
-
paths = default_search_paths + self.persistent_schemas
|
64
|
+
paths = default_search_paths + self.configuration.persistent_schemas
|
43
65
|
paths.uniq!
|
44
66
|
paths.compact!
|
45
67
|
paths.join(',')
|
@@ -49,11 +71,6 @@ module Storey
|
|
49
71
|
self.schema == self.default_search_path
|
50
72
|
end
|
51
73
|
|
52
|
-
def excluded_models=(array)
|
53
|
-
@@excluded_models = array
|
54
|
-
process_excluded_models
|
55
|
-
end
|
56
|
-
|
57
74
|
def schema(options={})
|
58
75
|
options[:suffix] ||= false
|
59
76
|
|
@@ -154,7 +171,7 @@ module Storey
|
|
154
171
|
def schema_exists?(name)
|
155
172
|
schema_name = suffixify(name)
|
156
173
|
|
157
|
-
schemas_in_db = self.schemas(suffix: self.suffix.present?)
|
174
|
+
schemas_in_db = self.schemas(suffix: self.configuration.suffix.present?)
|
158
175
|
schemas_in_db << %("$user")
|
159
176
|
schema_names = schema_name.split(',').map(&:strip)
|
160
177
|
schemas_not_in_db = schema_names - schemas_in_db
|
@@ -164,7 +181,7 @@ module Storey
|
|
164
181
|
def schema_search_path_for(schema_name)
|
165
182
|
schema_names = schema_name.split(',')
|
166
183
|
path = [suffixify(schema_name)]
|
167
|
-
self.persistent_schemas.each do |schema|
|
184
|
+
self.configuration.persistent_schemas.each do |schema|
|
168
185
|
unless schema_names.include?(schema)
|
169
186
|
path << suffixify(schema)
|
170
187
|
end
|
@@ -173,9 +190,10 @@ module Storey
|
|
173
190
|
end
|
174
191
|
|
175
192
|
def reload_config!
|
176
|
-
self.excluded_models = []
|
177
|
-
self.persistent_schemas = []
|
178
|
-
self.suffix = nil
|
193
|
+
self.configuration.excluded_models = []
|
194
|
+
self.configuration.persistent_schemas = []
|
195
|
+
self.configuration.suffix = nil
|
196
|
+
self.configuration.database_url = nil
|
179
197
|
end
|
180
198
|
|
181
199
|
def database_config
|
@@ -213,7 +231,7 @@ module Storey
|
|
213
231
|
end
|
214
232
|
|
215
233
|
def process_excluded_models
|
216
|
-
self.excluded_models.each do |model_name|
|
234
|
+
self.configuration.excluded_models.each do |model_name|
|
217
235
|
model_name.constantize.tap do |klass|
|
218
236
|
table_name = klass.table_name.split('.', 2).last
|
219
237
|
klass.table_name = "public.#{table_name}"
|
@@ -242,7 +260,14 @@ module Storey
|
|
242
260
|
end
|
243
261
|
|
244
262
|
def psql_load_command(options={})
|
245
|
-
|
263
|
+
args = self.database_config.slice(
|
264
|
+
:database,
|
265
|
+
:username,
|
266
|
+
:host,
|
267
|
+
:port,
|
268
|
+
:password,
|
269
|
+
).merge(options).symbolize_keys
|
270
|
+
GenLoadCommand.(args)
|
246
271
|
end
|
247
272
|
|
248
273
|
def set_default_search_path
|
data/lib/storey/duplicator.rb
CHANGED
@@ -39,29 +39,26 @@ module Storey
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def dump_schema(options={})
|
42
|
-
SetsEnvPassword.with(Storey.database_config[:password])
|
43
42
|
prepare_schema_dump_directories
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
arg_options[:schema] ||= @source_schema
|
53
|
-
arg_options['schema-only'] = nil if @structure_only
|
54
|
-
|
55
|
-
switches = Utils.command_line_switches_from(arg_options)
|
56
|
-
pg_dump_command = [
|
57
|
-
"pg_dump",
|
58
|
-
switches,
|
59
|
-
Storey.database_config[:database],
|
60
|
-
].join(" ")
|
44
|
+
options[:host] ||= Storey.database_config[:host]
|
45
|
+
options[:structure_only] = true if @structure_only
|
46
|
+
options[:schemas] = @source_schema
|
47
|
+
options[:database] ||= Storey.database_config[:database]
|
48
|
+
options[:username] ||= Storey.database_config[:username]
|
49
|
+
options[:file] = @source_file
|
50
|
+
pg_dump_command = GenDumpCommand.(options)
|
61
51
|
|
62
52
|
stdout_str, stderr_str, status = Open3.capture3(pg_dump_command)
|
63
53
|
unless status.exitstatus.zero?
|
64
|
-
|
54
|
+
msg = [
|
55
|
+
"Problem dumping",
|
56
|
+
"`#{@source_schema}`",
|
57
|
+
"to make a copy of it into",
|
58
|
+
"`#{@target_schema}`:",
|
59
|
+
stderr_str,
|
60
|
+
].join(" ")
|
61
|
+
raise StoreyError, msg
|
65
62
|
end
|
66
63
|
end
|
67
64
|
|
@@ -73,7 +70,13 @@ module Storey
|
|
73
70
|
|
74
71
|
def load_schema(options={})
|
75
72
|
options[:file] ||= @target_file
|
76
|
-
psql_options = Storey.database_config.
|
73
|
+
psql_options = Storey.database_config.slice(
|
74
|
+
:database,
|
75
|
+
:username,
|
76
|
+
:host,
|
77
|
+
:port,
|
78
|
+
:password,
|
79
|
+
).merge(options).symbolize_keys
|
77
80
|
|
78
81
|
if duplicating_from_default?
|
79
82
|
# Since we are copying the source schema and we're after structure only,
|
@@ -82,7 +85,7 @@ module Storey
|
|
82
85
|
::Storey.create_plain_schema @target_schema
|
83
86
|
end
|
84
87
|
|
85
|
-
psql_load_command =
|
88
|
+
psql_load_command = GenLoadCommand.(psql_options)
|
86
89
|
Open3.capture3(psql_load_command)
|
87
90
|
|
88
91
|
copy_source_schema_migrations
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Storey
|
2
|
+
class GenDumpCommand
|
3
|
+
|
4
|
+
def self.call(
|
5
|
+
database_url: Storey.configuration.database_url,
|
6
|
+
database: nil,
|
7
|
+
host: nil,
|
8
|
+
username: nil,
|
9
|
+
structure_only: false,
|
10
|
+
file: nil,
|
11
|
+
schemas: nil,
|
12
|
+
password: nil
|
13
|
+
)
|
14
|
+
switches = {}
|
15
|
+
|
16
|
+
if database_url.nil?
|
17
|
+
if database.blank?
|
18
|
+
raise ArgumentError, 'database must be supplied'
|
19
|
+
end
|
20
|
+
|
21
|
+
switches['host'] = host if host.present?
|
22
|
+
switches['username'] = username if username.present?
|
23
|
+
end
|
24
|
+
|
25
|
+
switches['schema-only'] = nil if structure_only
|
26
|
+
switches['no-privileges'] = nil
|
27
|
+
switches['no-owner'] = nil
|
28
|
+
switches[:file] = Shellwords.escape(file)
|
29
|
+
|
30
|
+
if schemas
|
31
|
+
schemas = schemas.split(',')
|
32
|
+
schemas_switches = schemas.map do |part|
|
33
|
+
Utils.command_line_switches_from({schema: Shellwords.escape(part) })
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
command_parts = []
|
38
|
+
if password.present?
|
39
|
+
command_parts << "PGPASSWORD=#{password}"
|
40
|
+
end
|
41
|
+
command_parts << "pg_dump"
|
42
|
+
command_parts << database_url if database_url.present?
|
43
|
+
command_parts += [
|
44
|
+
Utils.command_line_switches_from(switches),
|
45
|
+
schemas_switches,
|
46
|
+
]
|
47
|
+
command_parts << database if database_url.blank?
|
48
|
+
command_parts.compact.join(' ')
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Storey
|
2
|
+
class GenLoadCommand
|
3
|
+
|
4
|
+
def self.call(
|
5
|
+
file: nil,
|
6
|
+
command: nil,
|
7
|
+
database_url: Storey.configuration.database_url,
|
8
|
+
database: nil,
|
9
|
+
username: nil,
|
10
|
+
host: nil,
|
11
|
+
port: nil,
|
12
|
+
password: nil
|
13
|
+
)
|
14
|
+
switches = {}
|
15
|
+
if file.present?
|
16
|
+
switches[:file] = Shellwords.escape(file)
|
17
|
+
end
|
18
|
+
switches[:command] = %Q("#{command}") if command.present?
|
19
|
+
|
20
|
+
command_parts = ["psql"]
|
21
|
+
|
22
|
+
if database_url.present?
|
23
|
+
command_parts << database_url
|
24
|
+
else
|
25
|
+
switches[:dbname] = database
|
26
|
+
switches[:username] = username if username.present?
|
27
|
+
switches[:host] = host if host.present?
|
28
|
+
switches[:port] = port if port.present?
|
29
|
+
if password.present?
|
30
|
+
switches[:password] = password
|
31
|
+
else
|
32
|
+
switches['no-password'] = nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
command_parts << Utils.command_line_switches_from(switches)
|
37
|
+
command_parts.join(' ')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
data/lib/storey/hstore.rb
CHANGED
@@ -19,7 +19,7 @@ module Storey
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def ensure_hstore_is_persistent
|
22
|
-
unless Storey.persistent_schemas.include?('hstore')
|
22
|
+
unless Storey.configuration.persistent_schemas.include?('hstore')
|
23
23
|
fail StoreyError, 'You are attempting to install hstore data type, but the hstore schema (where the data type will be installed) is not one of the persistent schemas. Please add hstore to the list of persistent schemas.'
|
24
24
|
end
|
25
25
|
end
|
data/lib/storey/sql_dumper.rb
CHANGED
data/lib/storey/suffixifier.rb
CHANGED
data/lib/storey/unsuffixifier.rb
CHANGED
data/lib/storey/version.rb
CHANGED
data/lib/tasks/storey.rake
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Storey do
|
4
|
+
|
5
|
+
describe ".configure" do
|
6
|
+
it "customizes settings" do
|
7
|
+
described_class.configure do |c|
|
8
|
+
c.database_url = "postgres://url.com/db"
|
9
|
+
end
|
10
|
+
|
11
|
+
expect(described_class.configuration.database_url).
|
12
|
+
to eq "postgres://url.com/db"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -2,12 +2,12 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Storey, "configuration" do
|
4
4
|
it "should allow setting of suffix" do
|
5
|
-
Storey.suffix = "_hello"
|
6
|
-
Storey.suffix.
|
5
|
+
Storey.configuration.suffix = "_hello"
|
6
|
+
expect(Storey.configuration.suffix).to eq "_hello"
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should allow setting of excluded_models" do
|
10
|
-
Storey.excluded_models = %w(Company)
|
11
|
-
Storey.excluded_models.
|
10
|
+
Storey.configuration.excluded_models = %w(Company)
|
11
|
+
expect(Storey.configuration.excluded_models).to eq %w(Company)
|
12
12
|
end
|
13
13
|
end
|
@@ -4,18 +4,18 @@ describe Storey, '.create_plain_schema' do
|
|
4
4
|
context 'when there is no suffix set' do
|
5
5
|
it 'should create a schema without a suffix' do
|
6
6
|
Storey.create_plain_schema 'dun'
|
7
|
-
Storey.schemas(suffix: true).
|
7
|
+
expect(Storey.schemas(suffix: true)).to include('dun')
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
context 'when there is a suffix set' do
|
12
12
|
before do
|
13
|
-
Storey.suffix = '_lop'
|
13
|
+
Storey.configuration.suffix = '_lop'
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'should create a schema with the suffix' do
|
17
17
|
Storey.create_plain_schema 'dun'
|
18
|
-
Storey.schemas(suffix: true).
|
18
|
+
expect(Storey.schemas(suffix: true)).to include('dun_lop')
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
data/spec/storey/create_spec.rb
CHANGED
@@ -17,13 +17,13 @@ describe 'Storey', '#default_search_path' do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'includes the persistent schemas' do
|
20
|
-
Storey.persistent_schemas = %w(hello there)
|
20
|
+
Storey.configuration.persistent_schemas = %w(hello there)
|
21
21
|
expect(Storey.default_search_path).to eq '"$user",public,hello,there'
|
22
22
|
end
|
23
23
|
|
24
24
|
context 'when the persistent schemas includes `public`' do
|
25
25
|
it 'has one instance of public' do
|
26
|
-
Storey.persistent_schemas = %w(public hello)
|
26
|
+
Storey.configuration.persistent_schemas = %w(public hello)
|
27
27
|
expect(Storey.default_search_path).to eq '"$user",public,hello'
|
28
28
|
end
|
29
29
|
end
|
data/spec/storey/drop_spec.rb
CHANGED
@@ -52,17 +52,9 @@ describe Storey, "#duplicate!" do
|
|
52
52
|
|
53
53
|
end
|
54
54
|
|
55
|
-
it "should clear the PGPASSWORD environment variable" do
|
56
|
-
Storey.create 'ricky'
|
57
|
-
expect(Storey::SetsEnvPassword).to receive(:with).
|
58
|
-
with(Storey.database_config[:password])
|
59
|
-
Storey.duplicate! 'ricky', 'bobby'
|
60
|
-
ENV['PGPASSWORD'].should be_blank
|
61
|
-
end
|
62
|
-
|
63
55
|
context "when a suffix is set" do
|
64
56
|
before do
|
65
|
-
Storey.suffix = "_shakenbake"
|
57
|
+
Storey.configuration.suffix = "_shakenbake"
|
66
58
|
Storey.create 'ricky' do
|
67
59
|
Post.create :name => "Hi"
|
68
60
|
end
|
@@ -4,18 +4,19 @@ describe Storey::Duplicator do
|
|
4
4
|
|
5
5
|
describe '#perform!' do
|
6
6
|
context "when the dump is a failure" do
|
7
|
-
it '
|
7
|
+
it 'raises an error' do
|
8
8
|
duplicator = described_class.new('non-existent-will-fail-dump', 'new')
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
expected_msg = [
|
10
|
+
"Problem dumping `non-existent-will-fail-dump` to make a copy of it",
|
11
|
+
"into `new`: pg_dump: no matching schemas were found",
|
12
|
+
].join(" ")
|
13
|
+
expect { duplicator.perform! }.
|
14
|
+
to raise_error(Storey::StoreyError).
|
15
|
+
with_message(/#{expected_msg}/)
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
|
-
it '
|
19
|
+
it 'removes the target and source sql files after work' do
|
19
20
|
Storey.create 'boo'
|
20
21
|
duplicator = described_class.new('boo', 'ya')
|
21
22
|
duplicator.perform!
|
@@ -2,14 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Storey, "dealing with excluded_models" do
|
4
4
|
before do
|
5
|
-
Storey.excluded_models = %w(Company)
|
5
|
+
Storey.configuration.excluded_models = %w(Company)
|
6
|
+
# In practice, `excluded_models` is not set on the fly, but since we do so
|
7
|
+
# in the tests, we must call `init` to set the models to the right tables:
|
8
|
+
Storey.init
|
6
9
|
end
|
7
10
|
|
8
11
|
it "should always reference these models in the public schema" do
|
9
12
|
Storey.create("foo") { Company.create :name => "company_1" }
|
10
13
|
Company.create :name => "company_2"
|
11
14
|
|
12
|
-
Company.count.
|
13
|
-
Storey.switch("foo") {Company.count.
|
15
|
+
expect(Company.count).to eq 2
|
16
|
+
Storey.switch("foo") { expect(Company.count).to eq 2 }
|
14
17
|
end
|
15
18
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
module Storey
|
4
|
+
describe GenDumpCommand do
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
described_class.execute(options)
|
6
|
+
subject(:command) do
|
7
|
+
described_class.(options)
|
8
8
|
end
|
9
9
|
|
10
10
|
let(:options) do
|
@@ -16,6 +16,54 @@ describe Storey::BuildsDumpCommand do
|
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
19
|
+
context "connection string is passed in" do
|
20
|
+
let(:options) do
|
21
|
+
{
|
22
|
+
structure_only: true,
|
23
|
+
file: 'myfile.sql',
|
24
|
+
schemas: 'public',
|
25
|
+
database_url: "postgres://user:pass@ip.com:5432/db",
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
it "uses the connection string" do
|
30
|
+
expect(command).to include "pg_dump postgres://user:pass@ip.com:5432/db"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "connection string is passed in" do
|
35
|
+
let(:options) do
|
36
|
+
{
|
37
|
+
structure_only: true,
|
38
|
+
file: 'myfile.sql',
|
39
|
+
database_url: "postgres://user:pass@ip.com:5432/db",
|
40
|
+
database: "testdb",
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
it "ignores the `database` value" do
|
45
|
+
expect(command).to_not match /testdb/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "connection string is set in Storey" do
|
50
|
+
before do
|
51
|
+
Storey.configuration.database_url = "postgres://user:pass@ip.com:5432/db"
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:options) do
|
55
|
+
{
|
56
|
+
structure_only: true,
|
57
|
+
file: 'myfile.sql',
|
58
|
+
schemas: 'public',
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "uses the connection string" do
|
63
|
+
expect(command).to include "pg_dump postgres://user:pass@ip.com:5432/db"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
19
67
|
context "when host is specified" do
|
20
68
|
before do
|
21
69
|
options.merge!(host: "localhost")
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
module Storey
|
4
|
+
describe GenLoadCommand do
|
4
5
|
|
5
|
-
describe '.execute' do
|
6
6
|
let(:options) do
|
7
7
|
{
|
8
8
|
file: '/path/file dump.sql',
|
@@ -10,11 +10,12 @@ describe Storey::BuildsLoadCommand do
|
|
10
10
|
username: 'myuser',
|
11
11
|
host: 'localhost',
|
12
12
|
port: '5467',
|
13
|
-
password: '12345'
|
13
|
+
password: '12345',
|
14
|
+
database_url: nil,
|
14
15
|
}
|
15
16
|
end
|
16
17
|
|
17
|
-
subject { described_class.
|
18
|
+
subject(:command) { described_class.(options) }
|
18
19
|
|
19
20
|
it { should include('--file=/path/file\ dump.sql') }
|
20
21
|
it { should include('--dbname=mydb') }
|
@@ -22,6 +23,36 @@ describe Storey::BuildsLoadCommand do
|
|
22
23
|
it { should include('--host=localhost') }
|
23
24
|
it { should include('--password=12345')}
|
24
25
|
|
26
|
+
context "when database_url is passed in" do
|
27
|
+
subject(:command) do
|
28
|
+
described_class.(
|
29
|
+
database_url: "postgres://u:p@host:5432/db",
|
30
|
+
file: '/path/file dump.sql',
|
31
|
+
host: 'localhost',
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "prioritizes the database_url" do
|
36
|
+
expect(command).to include "psql postgres://u:p@host:5432/db"
|
37
|
+
expect(command).to_not include "localhost"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when database_url is set in Storey config" do
|
42
|
+
before do
|
43
|
+
Storey.configuration.database_url = "postgres://u:p@host:5432/db"
|
44
|
+
end
|
45
|
+
|
46
|
+
subject(:command) do
|
47
|
+
described_class.(file: '/path/file dump.sql', host: 'localhost')
|
48
|
+
end
|
49
|
+
|
50
|
+
it "prioritizes the database_url" do
|
51
|
+
expect(command).to include "psql postgres://u:p@host:5432/db"
|
52
|
+
expect(command).to_not include "localhost"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
25
56
|
context 'when host is not set' do
|
26
57
|
before { options[:host] = nil }
|
27
58
|
it { should_not include('--host=') }
|
data/spec/storey/hstore_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Storey::Hstore do
|
4
4
|
describe '.install' do
|
5
5
|
it 'installs the extension into the hstore schema' do
|
6
|
-
Storey.persistent_schemas = %w(hstore)
|
6
|
+
Storey.configuration.persistent_schemas = %w(hstore)
|
7
7
|
described_class.install
|
8
8
|
expect { ::ActiveRecord::Base.connection.execute "DROP EXTENSION hstore" }.
|
9
9
|
to_not raise_error
|
@@ -11,7 +11,7 @@ describe Storey::Hstore do
|
|
11
11
|
|
12
12
|
context 'hstore is not one of the persistent schemas' do
|
13
13
|
it 'fails with an StoreyError' do
|
14
|
-
Storey.persistent_schemas = []
|
14
|
+
Storey.configuration.persistent_schemas = []
|
15
15
|
message = 'You are attempting to install hstore data type, but the hstore schema (where the data type will be installed) is not one of the persistent schemas. Please add hstore to the list of persistent schemas.'
|
16
16
|
expect { described_class.install }.
|
17
17
|
to raise_error(Storey::StoreyError, message)
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Storey, '#schema_search_path_for' do
|
4
4
|
|
5
5
|
context 'given a search path that is one of the persistent schemas' do
|
6
|
-
Storey.persistent_schemas = %w(halla)
|
6
|
+
Storey.configuration.persistent_schemas = %w(halla)
|
7
7
|
Storey.schema_search_path_for('bola,halla').should == 'bola, halla'
|
8
8
|
Storey.schema_search_path_for('halla').should == 'halla'
|
9
9
|
Storey.schema_search_path_for('halla,bola').should == 'halla, bola'
|
data/spec/storey/schema_spec.rb
CHANGED
data/spec/storey/schemas_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Storey::Suffixifier do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
context 'suffixes have been turned on' do
|
11
|
-
before { Storey.suffix = '_suff' }
|
11
|
+
before { Storey.configuration.suffix = '_suff' }
|
12
12
|
|
13
13
|
context 'when the schema given has not already been suffixified' do
|
14
14
|
let(:schema_name) { 'boom' }
|
@@ -30,7 +30,7 @@ describe Storey::Suffixifier do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'suffixes are not on' do
|
33
|
-
before { Storey.suffix = nil }
|
33
|
+
before { Storey.configuration.suffix = nil }
|
34
34
|
let(:schema_name) { 'boom' }
|
35
35
|
it { should == 'boom' }
|
36
36
|
end
|
data/spec/storey/switch_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe Storey, "#switch" do
|
|
11
11
|
|
12
12
|
context "with a schema set" do
|
13
13
|
before do
|
14
|
-
Storey.suffix = "_hello"
|
14
|
+
Storey.configuration.suffix = "_hello"
|
15
15
|
Storey.create "foobar"
|
16
16
|
end
|
17
17
|
|
@@ -56,7 +56,7 @@ describe Storey, "#switch" do
|
|
56
56
|
context "when the schema passed does not exist" do
|
57
57
|
context "when the suffix is set" do
|
58
58
|
before do
|
59
|
-
Storey.suffix = "_rock"
|
59
|
+
Storey.configuration.suffix = "_rock"
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should raise an error naming the schema with suffix" do
|
@@ -111,7 +111,7 @@ describe Storey, "#switch" do
|
|
111
111
|
persistent_schemas.each do |schema|
|
112
112
|
Storey.create schema
|
113
113
|
end
|
114
|
-
Storey.persistent_schemas = persistent_schemas
|
114
|
+
Storey.configuration.persistent_schemas = persistent_schemas
|
115
115
|
end
|
116
116
|
|
117
117
|
it 'should switch to the schema with the persitent schemas still in the search path' do
|
@@ -125,13 +125,13 @@ describe Storey, "#switch" do
|
|
125
125
|
|
126
126
|
context 'when suffixes are set' do
|
127
127
|
before do
|
128
|
-
Storey.suffix = '_boomboom'
|
128
|
+
Storey.configuration.suffix = '_boomboom'
|
129
129
|
Storey.create 'foobar'
|
130
130
|
persistent_schemas = %w(handle bar foo)
|
131
131
|
persistent_schemas.each do |schema|
|
132
132
|
Storey.create schema
|
133
133
|
end
|
134
|
-
Storey.persistent_schemas = persistent_schemas
|
134
|
+
Storey.configuration.persistent_schemas = persistent_schemas
|
135
135
|
end
|
136
136
|
|
137
137
|
it 'should switch to the schema with the persitent schemas still in the search path' do
|
@@ -151,7 +151,7 @@ describe Storey, "#switch" do
|
|
151
151
|
persistent_schemas.each do |schema|
|
152
152
|
Storey.create schema
|
153
153
|
end
|
154
|
-
Storey.persistent_schemas = persistent_schemas
|
154
|
+
Storey.configuration.persistent_schemas = persistent_schemas
|
155
155
|
end
|
156
156
|
|
157
157
|
it 'should not have duplicate schemas in the search path' do
|
@@ -6,7 +6,7 @@ describe Storey::Unsuffixifier do
|
|
6
6
|
subject { described_class.new(schema_name).unsuffixify }
|
7
7
|
|
8
8
|
context 'when the suffix is set' do
|
9
|
-
before { Storey.suffix = '_buff' }
|
9
|
+
before { Storey.configuration.suffix = '_buff' }
|
10
10
|
|
11
11
|
context 'when the schema name does not have a suffix' do
|
12
12
|
let(:schema_name) { 'big' }
|
data/storey.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: storey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ramon Tayag
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-rails
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: gem_config
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Storey aims to simplify the implementation of managing a multi-tenant
|
84
98
|
application.
|
85
99
|
email:
|
@@ -106,11 +120,11 @@ files:
|
|
106
120
|
- gemfiles/rails_5.2.gemfile
|
107
121
|
- gemfiles/rails_5.2.gemfile.lock
|
108
122
|
- lib/storey.rb
|
109
|
-
- lib/storey/builds_dump_command.rb
|
110
|
-
- lib/storey/builds_load_command.rb
|
111
123
|
- lib/storey/dumper.rb
|
112
124
|
- lib/storey/duplicator.rb
|
113
125
|
- lib/storey/exceptions.rb
|
126
|
+
- lib/storey/gen_dump_command.rb
|
127
|
+
- lib/storey/gen_load_command.rb
|
114
128
|
- lib/storey/get_migration_versions.rb
|
115
129
|
- lib/storey/hstore.rb
|
116
130
|
- lib/storey/migrator.rb
|
@@ -165,10 +179,9 @@ files:
|
|
165
179
|
- spec/dummy/public/favicon.ico
|
166
180
|
- spec/dummy/script/rails
|
167
181
|
- spec/fixtures/.gitkeep
|
182
|
+
- spec/lib/storey_spec.rb
|
168
183
|
- spec/migrator_spec.rb
|
169
184
|
- spec/spec_helper.rb
|
170
|
-
- spec/storey/builds_dump_command_spec.rb
|
171
|
-
- spec/storey/builds_load_command_spec.rb
|
172
185
|
- spec/storey/configuration_spec.rb
|
173
186
|
- spec/storey/create_plain_schema_spec.rb
|
174
187
|
- spec/storey/create_spec.rb
|
@@ -179,6 +192,8 @@ files:
|
|
179
192
|
- spec/storey/duplicate_spec.rb
|
180
193
|
- spec/storey/duplicator_spec.rb
|
181
194
|
- spec/storey/excluded_models_spec.rb
|
195
|
+
- spec/storey/gen_dump_command_spec.rb
|
196
|
+
- spec/storey/gen_load_command_spec.rb
|
182
197
|
- spec/storey/get_migration_versions_spec.rb
|
183
198
|
- spec/storey/hstore_spec.rb
|
184
199
|
- spec/storey/native_schema_matcher_spec.rb
|
@@ -261,10 +276,9 @@ test_files:
|
|
261
276
|
- spec/dummy/public/favicon.ico
|
262
277
|
- spec/dummy/script/rails
|
263
278
|
- spec/fixtures/.gitkeep
|
279
|
+
- spec/lib/storey_spec.rb
|
264
280
|
- spec/migrator_spec.rb
|
265
281
|
- spec/spec_helper.rb
|
266
|
-
- spec/storey/builds_dump_command_spec.rb
|
267
|
-
- spec/storey/builds_load_command_spec.rb
|
268
282
|
- spec/storey/configuration_spec.rb
|
269
283
|
- spec/storey/create_plain_schema_spec.rb
|
270
284
|
- spec/storey/create_spec.rb
|
@@ -275,6 +289,8 @@ test_files:
|
|
275
289
|
- spec/storey/duplicate_spec.rb
|
276
290
|
- spec/storey/duplicator_spec.rb
|
277
291
|
- spec/storey/excluded_models_spec.rb
|
292
|
+
- spec/storey/gen_dump_command_spec.rb
|
293
|
+
- spec/storey/gen_load_command_spec.rb
|
278
294
|
- spec/storey/get_migration_versions_spec.rb
|
279
295
|
- spec/storey/hstore_spec.rb
|
280
296
|
- spec/storey/native_schema_matcher_spec.rb
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Storey
|
2
|
-
class BuildsDumpCommand
|
3
|
-
|
4
|
-
easy_class_to_instance
|
5
|
-
|
6
|
-
def initialize(options={})
|
7
|
-
@options = options
|
8
|
-
if @options[:database].blank?
|
9
|
-
raise ArgumentError, 'database must be supplied'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute
|
14
|
-
|
15
|
-
switches = {}
|
16
|
-
switches['schema-only'] = nil if @options[:structure_only]
|
17
|
-
switches['no-privileges'] = nil
|
18
|
-
switches['no-owner'] = nil
|
19
|
-
switches['host'] = @options[:host] if @options[:host].present?
|
20
|
-
switches['username'] = @options[:username] if @options[:username].present?
|
21
|
-
switches[:file] = Shellwords.escape(@options[:file])
|
22
|
-
|
23
|
-
if @options[:schemas]
|
24
|
-
schemas = @options[:schemas].split(',')
|
25
|
-
schemas_switches = schemas.map do |part|
|
26
|
-
Utils.command_line_switches_from({schema: Shellwords.escape(part) })
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
command_parts = []
|
31
|
-
if @options[:password].present?
|
32
|
-
command_parts << "PGPASSWORD=#{@options[:password]}"
|
33
|
-
end
|
34
|
-
command_parts += ['pg_dump',
|
35
|
-
Utils.command_line_switches_from(switches),
|
36
|
-
schemas_switches,
|
37
|
-
@options[:database]]
|
38
|
-
command_parts.compact.join(' ')
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Storey
|
2
|
-
class BuildsLoadCommand
|
3
|
-
|
4
|
-
easy_class_to_instance
|
5
|
-
|
6
|
-
def initialize(options={})
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
|
10
|
-
def execute
|
11
|
-
switches = {}
|
12
|
-
if @options[:file].present?
|
13
|
-
switches[:file] = Shellwords.escape(@options[:file])
|
14
|
-
end
|
15
|
-
switches[:dbname] = @options[:database]
|
16
|
-
switches[:username] = @options[:username] if @options[:username].present?
|
17
|
-
switches[:host] = @options[:host] if @options[:host].present?
|
18
|
-
switches[:port] = @options[:port] if @options[:port].present?
|
19
|
-
if @options[:password].present?
|
20
|
-
switches[:password] = @options[:password]
|
21
|
-
else
|
22
|
-
switches['no-password'] = nil
|
23
|
-
end
|
24
|
-
switches[:command] = %Q("#{@options[:command]}") if @options[:command].present?
|
25
|
-
command_parts = ['psql',
|
26
|
-
Utils.command_line_switches_from(switches)]
|
27
|
-
command_parts.join(' ')
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|