Module: Storey

Extended by:
Storey
Includes:
GemConfig::Base
Included in:
Storey
Defined in:
lib/storey.rb,
lib/storey/utils.rb,
lib/storey/dumper.rb,
lib/storey/hstore.rb,
lib/storey/version.rb,
lib/storey/migrator.rb,
lib/storey/duplicator.rb,
lib/storey/exceptions.rb,
lib/storey/sql_dumper.rb,
lib/storey/rack_switch.rb,
lib/storey/ruby_dumper.rb,
lib/storey/schema_name.rb,
lib/storey/suffixifier.rb,
lib/storey/unsuffixifier.rb,
lib/storey/gen_dump_command.rb,
lib/storey/gen_load_command.rb,
lib/storey/sets_env_password.rb,
lib/storey/resets_column_info.rb,
lib/storey/native_schema_matcher.rb,
lib/storey/get_migration_versions.rb

Defined Under Namespace

Classes: Dumper, Duplicator, GenDumpCommand, GenLoadCommand, GetMigrationVersions, Hstore, Migrator, NativeSchemaMatcher, RackSwitch, Railtie, ResetsColumnInfo, RubyDumper, SchemaExists, SchemaInvalid, SchemaName, SchemaNotFound, SchemaReserved, SetsEnvPassword, SqlDumper, StoreyError, Suffixifier, TableNotFOund, Unsuffixifier, Utils, WithinTransaction

Constant Summary collapse

VERSION =
"2.2.0"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.excluded_models=(models) ⇒ Object



54
55
56
57
# File 'lib/storey.rb', line 54

def self.excluded_models=(models)
  deprecate "setting models directly via `Storey.excluded_models=` is deprecated. Please use `Storey.configure {|c| c.excluded_models = %w(User Setting) }` instead."
  self.configuration.excluded_models = models
end

.persistent_schemas=(schemas) ⇒ Object



44
45
46
47
# File 'lib/storey.rb', line 44

def self.persistent_schemas=(schemas)
  deprecate "setting persistent schemas directly via `Storey.persistent_schemas=` is deprecated. Please use `Storey.configure {|c| c.persistent_schemas = %w(hstore) }` instead."
  self.configuration.persistent_schemas = schemas
end

.suffix=(s) ⇒ Object



49
50
51
52
# File 'lib/storey.rb', line 49

def self.suffix=(s)
  deprecate "setting suffix directly via `Storey.suffix=` is deprecated. Please use `Storey.configure {|c| c.suffix = %w(_mysfx) }` instead."
  self.configuration.suffix = s
end

Instance Method Details

#create(name, options = {}, &block) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/storey.rb', line 85

def create(name, options={}, &block)
  name = SchemaName.new(name)
  name.validate_format!
  name.validate_reserved! unless options[:force]

  if self.schemas.include?(name)
    fail(Storey::SchemaExists, %{The schema "#{name}" already exists.})
  end

  if options[:load_database_structure].nil?
    options[:load_database_structure] = true
  end

  if options[:load_database_structure]
    duplicator = Storey::Duplicator.new('public',
                                        name,
                                        structure_only: true)
    duplicator.perform!
    name = suffixify name
    switch name do
      block.call if block_given?
    end
  else
    self.create_plain_schema name
  end
end

#create_plain_schema(schema_name) ⇒ Object



112
113
114
115
116
# File 'lib/storey.rb', line 112

def create_plain_schema(schema_name)
  name = suffixify schema_name
  command = "CREATE SCHEMA #{name}"
  Open3.capture3 psql_load_command(command: command)
end

#database_configObject



202
203
204
205
206
# File 'lib/storey.rb', line 202

def database_config
  Rails.configuration.
    database_configuration[Rails.env].
    with_indifferent_access
end

#db_command_line_switches_from(extra_config = {}) ⇒ Object



221
222
223
# File 'lib/storey.rb', line 221

def db_command_line_switches_from(extra_config={})
  Utils.db_command_line_switches_from(self.database_config, extra_config)
end

#default_schema?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/storey.rb', line 72

def default_schema?
  self.schema == self.default_search_path
end

#default_search_pathObject



63
64
65
66
67
68
69
70
# File 'lib/storey.rb', line 63

def default_search_path
  set_default_search_path
  default_search_paths = @@default_search_path.split(',')
  paths = default_search_paths + self.configuration.persistent_schemas
  paths.uniq!
  paths.compact!
  paths.join(',')
end

#drop(name) ⇒ Object



136
137
138
139
140
141
142
143
# File 'lib/storey.rb', line 136

def drop(name)
  name = suffixify name
  command = "DROP SCHEMA #{name} CASCADE"
  ::ActiveRecord::Base.connection.execute(command)
rescue ::ActiveRecord::StatementInvalid => e
  raise(Storey::SchemaNotFound,
        %{The schema "#{name}" cannot be found. Error: #{e}})
end

#duplicate!(from_schema, to_schema, options = {}) ⇒ Object



208
209
210
211
# File 'lib/storey.rb', line 208

def duplicate!(from_schema, to_schema, options={})
  duplicator = Duplicator.new(from_schema, to_schema, options)
  duplicator.perform!
end

#initObject



59
60
61
# File 'lib/storey.rb', line 59

def init
  process_excluded_models
end

#matches_default_search_path?(schema_name) ⇒ Boolean

Returns:

  • (Boolean)


213
214
215
216
217
218
219
# File 'lib/storey.rb', line 213

def matches_default_search_path?(schema_name)
  paths = self.default_search_path.split(',')
  paths.each do |path|
    return true if path == schema_name
  end
  self.default_search_path == schema_name
end

#reload_config!Object



195
196
197
198
199
200
# File 'lib/storey.rb', line 195

def reload_config!
  self.configuration.excluded_models = []
  self.configuration.persistent_schemas = []
  self.configuration.suffix = nil
  self.configuration.database_url = nil
end

#schema(options = {}) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/storey.rb', line 76

def schema(options={})
  options[:suffix] ||= false

  name = ::ActiveRecord::Base.connection.schema_search_path
  name = unsuffixify(name) if !options[:suffix]
  return name.split(",").map(&:strip) if options[:array]
  name
end

#schema_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


174
175
176
177
178
179
180
181
182
# File 'lib/storey.rb', line 174

def schema_exists?(name)
  schema_name = suffixify(name)

  schemas_in_db = self.schemas(suffix: self.configuration.suffix.present?)
  schemas_in_db << %("$user")
  schema_names = schema_name.split(',').map(&:strip)
  schemas_not_in_db = schema_names - schemas_in_db
  schemas_not_in_db.empty?
end

#schema_search_path_for(schema_name) ⇒ Object



184
185
186
187
188
189
190
191
192
193
# File 'lib/storey.rb', line 184

def schema_search_path_for(schema_name)
  schema_names = schema_name.split(',')
  path = [suffixify(schema_name)]
  self.configuration.persistent_schemas.each do |schema|
    unless schema_names.include?(schema)
      path << suffixify(schema)
    end
  end
  path.uniq.join(',')
end

#schemas(options = {}) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/storey.rb', line 118

def schemas(options={})
  options[:suffix] ||= false
  options[:public] = true unless options.has_key?(:public)

  sql = "SELECT nspname FROM pg_namespace"
  sql << " WHERE nspname !~ '^pg_.*'"
  sql << " AND nspname != 'information_schema'"
  sql << " AND nspname != 'public'" unless options[:public]

  names = ::ActiveRecord::Base.connection.query(sql).flatten

  if options[:suffix]
    names
  else
    names = names.map {|name| unsuffixify(name)}
  end
end

#switch(name = nil, &block) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/storey.rb', line 145

def switch(name=nil, &block)
  set_default_search_path

  if block_given?
    original_schema = schema
    switch name
    result = block.call
    switch original_schema
    result
  else
    ::ActiveRecord::Base.connection.query_cache.clear
    reset and return if name.blank? || name == 'public'
    path = self.schema_search_path_for(name)

    unless self.schema_exists?(name)
      fail(Storey::SchemaNotFound, %{The schema "#{path}" cannot be found.})
    end

    ::ActiveRecord::Base.connection.schema_search_path = path
  end
rescue ::ActiveRecord::StatementInvalid => e
  if e.to_s =~ /relation ".*" does not exist at character \d+/
    warn "See https://github.com/ramontayag/storey/issues/11"
    raise e
  else
    raise e
  end
end