Module: Storey

Extended by:
Storey
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/ruby_dumper.rb,
lib/storey/schema_name.rb,
lib/storey/suffixifier.rb,
lib/storey/unsuffixifier.rb,
lib/storey/sets_env_password.rb,
lib/storey/resets_column_info.rb,
lib/storey/builds_dump_command.rb,
lib/storey/builds_load_command.rb,
lib/storey/native_schema_matcher.rb

Defined Under Namespace

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

Constant Summary collapse

VERSION =
"1.0.0"

Instance Method Summary collapse

Instance Method Details

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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/storey.rb', line 67

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



94
95
96
97
98
# File 'lib/storey.rb', line 94

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

#database_configObject



180
181
182
183
184
# File 'lib/storey.rb', line 180

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

#db_command_line_switches_from(extra_config = {}) ⇒ Object



199
200
201
# File 'lib/storey.rb', line 199

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)


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

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

#default_search_pathObject



38
39
40
41
42
43
44
# File 'lib/storey.rb', line 38

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

#drop(name) ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/storey.rb', line 118

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



186
187
188
189
# File 'lib/storey.rb', line 186

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

#excluded_models=(array) ⇒ Object



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

def excluded_models=(array)
  @@excluded_models = array
  process_excluded_models
end

#initObject



31
32
33
34
35
36
# File 'lib/storey.rb', line 31

def init
  self.default_search_path = self.schema
  self.excluded_models ||= []
  self.persistent_schemas ||= []
  process_excluded_models
end

#matches_default_search_path?(schema_name) ⇒ Boolean

Returns:

  • (Boolean)


191
192
193
194
195
196
197
# File 'lib/storey.rb', line 191

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



174
175
176
177
178
# File 'lib/storey.rb', line 174

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

#schema(options = {}) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/storey.rb', line 55

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

  name = ::ActiveRecord::Base.connection.schema_search_path

  if options[:suffix]
    name
  else
    unsuffixify name
  end
end

#schema_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


153
154
155
156
157
158
159
160
161
# File 'lib/storey.rb', line 153

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

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

#schema_search_path_for(schema_name) ⇒ Object



163
164
165
166
167
168
169
170
171
172
# File 'lib/storey.rb', line 163

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

#schemas(options = {}) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/storey.rb', line 100

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



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/storey.rb', line 127

def switch(name=nil, &block)
  if block_given?
    original_schema = schema
    switch name
    result = block.call
    switch original_schema
    result
  else
    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