storey 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +6 -0
  4. data/README.md +17 -10
  5. data/gemfiles/rails_5.0.gemfile.lock +3 -1
  6. data/gemfiles/rails_5.1.gemfile.lock +3 -1
  7. data/gemfiles/rails_5.2.gemfile.lock +3 -1
  8. data/lib/storey.rb +42 -17
  9. data/lib/storey/duplicator.rb +23 -20
  10. data/lib/storey/gen_dump_command.rb +52 -0
  11. data/lib/storey/gen_load_command.rb +41 -0
  12. data/lib/storey/hstore.rb +1 -1
  13. data/lib/storey/sql_dumper.rb +2 -2
  14. data/lib/storey/suffixifier.rb +1 -1
  15. data/lib/storey/unsuffixifier.rb +1 -1
  16. data/lib/storey/version.rb +1 -1
  17. data/lib/tasks/storey.rake +1 -1
  18. data/spec/lib/storey_spec.rb +16 -0
  19. data/spec/storey/configuration_spec.rb +4 -4
  20. data/spec/storey/create_plain_schema_spec.rb +3 -3
  21. data/spec/storey/create_spec.rb +1 -1
  22. data/spec/storey/default_search_path_spec.rb +2 -2
  23. data/spec/storey/drop_spec.rb +1 -1
  24. data/spec/storey/duplicate_spec.rb +1 -9
  25. data/spec/storey/duplicator_spec.rb +9 -8
  26. data/spec/storey/excluded_models_spec.rb +6 -3
  27. data/spec/storey/{builds_dump_command_spec.rb → gen_dump_command_spec.rb} +52 -4
  28. data/spec/storey/{builds_load_command_spec.rb → gen_load_command_spec.rb} +35 -4
  29. data/spec/storey/hstore_spec.rb +2 -2
  30. data/spec/storey/schema_exists_spec.rb +1 -1
  31. data/spec/storey/schema_search_path_for_spec.rb +1 -1
  32. data/spec/storey/schema_spec.rb +1 -1
  33. data/spec/storey/schemas_spec.rb +1 -1
  34. data/spec/storey/suffixifier_spec.rb +2 -2
  35. data/spec/storey/switch_spec.rb +6 -6
  36. data/spec/storey/unsuffixifier_spec.rb +1 -1
  37. data/storey.gemspec +1 -0
  38. metadata +24 -8
  39. data/lib/storey/builds_dump_command.rb +0 -42
  40. data/lib/storey/builds_load_command.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89dc451e50d3e25bfa3e2f4028f1718059cd28f8aafab7aaf87a1815837f9121
4
- data.tar.gz: 3f32de0842a1c7d05b91fc7b715fbb1710d8452e0fe7db00eb740994d35cb80e
3
+ metadata.gz: 4d868102f5a1ce14a7d937639ab4cda6b59ed9d10be52bee5ce219d46cadddfc
4
+ data.tar.gz: b6d1ae7e3276463d5fed292024f5d2ea19be909d5fa9075bc4e731a5d1127fda
5
5
  SHA512:
6
- metadata.gz: 73992092bc15f428a45bea3b4a9de2794f9eeb72f0aaec6d3eee7b36b2cf6c4030ae10d6b9f869702589acc724b3c92dabb4597373541926be2e01fe05b5ba7c
7
- data.tar.gz: 0617b1dd0a58fe4bf1d8dacfcd8a1cddd8efcf8ef5ff7f384edbbffd950a905525529f3de1e005a133d647a2806d365be3b5a12c07855f9f81a1c9c234f3e9d3
6
+ metadata.gz: 9838fa46e3d3c84c17e2994587759db404ca47e6bbb1dc666bf76cc9c79348d6fad7dc677cfd5967af376d385e4eb3532eed4f2eb7d50a078788dcc3eb87a82b
7
+ data.tar.gz: 8d45a6ad1b0cac2f3a3b708b070684b7ff3134b8b41a7e38fbc8b4c135f27f91ab45bb363d48dfc4cc9b5723e9b18574f794ce7c6ed546dde20279bc81f5d4a7
data/.travis.yml CHANGED
@@ -3,7 +3,7 @@ language: ruby
3
3
  services:
4
4
  postgresql
5
5
  addons:
6
- postgresql: 9.4
6
+ postgresql: 9.6
7
7
  before_script:
8
8
  - cp spec/dummy/config/database.yml{.sample,}
9
9
  - psql -U postgres -c 'CREATE DATABASE storey_test;'
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
- # Defines the tables that should stay available to all (ie in the public schema)
14
- # Note that there's currently no way to exclude tables that aren't linked to models
15
- # If you have any ideas on how to do this I'm open to suggestions
16
- Storey.excluded_models = %w(User Company Role Permission)
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
- # If set, all schemas are created with the suffix.
19
- # Used for obscuring the schema name - which is important when performing schema duplication.
20
- # Storey.suffix = "_suffix"
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
- # Defines schemas that should always stay in the search path, apart from the one you switched to.
23
- # Storey.persistent_schemas = %w(hstore)
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.1)
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.1)
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.1)
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/builds_dump_command'
21
- require 'storey/builds_load_command'
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
- BuildsLoadCommand.execute(self.database_config.merge(options))
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
@@ -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
- if Storey.database_config[:host].present?
46
- options[:host] ||= Storey.database_config[:host]
47
- end
48
-
49
- arg_options = options.dup
50
- arg_options[:username] ||= Storey.database_config[:username]
51
- arg_options[:file] ||= @source_file
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
- raise StoreyError, "There seems to have been a problem dumping `#{@source_schema}` to make a copy of it into `#{@target_schema}`"
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.merge(options)
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 = BuildsLoadCommand.execute(psql_options)
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
@@ -33,8 +33,8 @@ module Storey
33
33
  file: @file,
34
34
  schemas: search_path,
35
35
  database: database_name,
36
- )
37
- @command = BuildsDumpCommand.execute(args)
36
+ ).symbolize_keys
37
+ @command = GenDumpCommand.(args)
38
38
  end
39
39
 
40
40
  end
@@ -26,7 +26,7 @@ module Storey
26
26
  end
27
27
 
28
28
  def suffix
29
- Storey.suffix
29
+ Storey.configuration.suffix
30
30
  end
31
31
 
32
32
  def native_schema?(schema_name)
@@ -22,7 +22,7 @@ module Storey
22
22
  private
23
23
 
24
24
  def suffix
25
- Storey.suffix
25
+ Storey.configuration.suffix
26
26
  end
27
27
 
28
28
  def schema_names
@@ -1,3 +1,3 @@
1
1
  module Storey
2
- VERSION = "2.0.2"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  namespace :storey do
2
2
 
3
3
  namespace :hstore do
4
- desc "Install hstore into the hstore#{Storey.suffix} schema"
4
+ desc "Install hstore into the hstore#{Storey.configuration.suffix} schema"
5
5
  task :install => :environment do
6
6
  Storey::Hstore.install
7
7
  end
@@ -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.should == "_hello"
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.should == %w(Company)
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).should include('dun')
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).should include('dun_lop')
18
+ expect(Storey.schemas(suffix: true)).to include('dun_lop')
19
19
  end
20
20
  end
21
21
  end
@@ -76,7 +76,7 @@ describe Storey, "#create" do
76
76
 
77
77
  context "when suffix is set" do
78
78
  before do
79
- Storey.suffix = "_rock"
79
+ Storey.configuration.suffix = "_rock"
80
80
  end
81
81
 
82
82
  it "should create a schema with the suffix" do
@@ -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
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Storey, "#drop" do
4
4
  context "when suffix is set" do
5
5
  before do
6
- Storey.suffix = "bar"
6
+ Storey.configuration.suffix = "bar"
7
7
  Storey.create "foo"
8
8
  end
9
9
 
@@ -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 'should raise an error' do
7
+ it 'raises an error' do
8
8
  duplicator = described_class.new('non-existent-will-fail-dump', 'new')
9
- expect {
10
- duplicator.perform!
11
- }.to raise_error(
12
- Storey::StoreyError,
13
- "There seems to have been a problem dumping `non-existent-will-fail-dump` to make a copy of it into `new`"
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 'should remove the target and source sql files after work' do
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.should == 2
13
- Storey.switch("foo") {Company.count.should == 2}
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
- describe Storey::BuildsDumpCommand do
3
+ module Storey
4
+ describe GenDumpCommand do
4
5
 
5
- describe '.execute' do
6
- subject do
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
- describe Storey::BuildsLoadCommand do
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.execute(options) }
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=') }
@@ -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)
@@ -28,7 +28,7 @@ describe Storey, '#schema_exists?' do
28
28
  context 'when there is a suffix' do
29
29
  context 'when the schema exists' do
30
30
  before do
31
- Storey.suffix = '_boo'
31
+ Storey.configuration.suffix = '_boo'
32
32
  Storey.create 'croo'
33
33
  end
34
34
 
@@ -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'
@@ -13,7 +13,7 @@ describe Storey, "#schema" do
13
13
 
14
14
  context "when a suffix is set" do
15
15
  before do
16
- Storey.suffix = "_rock"
16
+ Storey.configuration.suffix = "_rock"
17
17
  Storey.create "hello"
18
18
  Storey.switch "hello"
19
19
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Storey, "#schemas" do
4
4
  context "when suffix is set" do
5
5
  before do
6
- Storey.suffix = "_roboto"
6
+ Storey.configuration.suffix = "_roboto"
7
7
  end
8
8
 
9
9
  it "should return an array of the schemas without the suffix by default" do
@@ -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
@@ -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
@@ -25,4 +25,5 @@ Gem::Specification.new do |s|
25
25
  s.add_runtime_dependency 'easy_class_to_instance_method', '~> 0.0.2'
26
26
  s.add_runtime_dependency "rails", ">= 4.0.0"
27
27
  s.add_runtime_dependency "pg"
28
+ s.add_runtime_dependency "gem_config"
28
29
  end
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.2
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-06-29 00:00:00.000000000 Z
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