Class: Innkeeper::Adapters::AbstractAdapter

Inherits:
Object
  • Object
show all
Includes:
ActiveSupport::Callbacks
Defined in:
lib/innkeeper/adapters/abstract_adapter.rb

Direct Known Subclasses

Mysql2Adapter, PostgresqlAdapter

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAbstractAdapter

Returns a new instance of AbstractAdapter.



9
10
11
12
13
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 9

def initialize
  reset
rescue Innkeeper::TenantNotFound
  puts "WARN: Unable to connect to default tenant"
end

Instance Attribute Details

#currentObject (readonly)

Returns the value of attribute current.



7
8
9
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 7

def current
  @current
end

Instance Method Details

#config_for(tenant) ⇒ Object



94
95
96
97
98
99
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 94

def config_for(tenant)
  return tenant if tenant.is_a?(Hash)

  decorated_tenant = decorate(tenant)
  Innkeeper.tenant_resolver.resolve(decorated_tenant)
end

#connection_switch!(config, without_keys: []) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 136

def connection_switch!(config, without_keys: [])
  config = config.reject{ |k, _| without_keys.include?(k) }

  config.merge!(name: connection_specification_name(config))

  unless Innkeeper.connection_handler.retrieve_connection_pool(config[:name])
    Innkeeper.connection_handler.establish_connection(config)
  end

  Thread.current[:_innkeeper_connection_specification_name] = config[:name]
  simple_switch(config) if config[:database] || config[:schema_search_path]
end

#create(tenant) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 28

def create(tenant)
  run_callbacks :create do
    begin
      previous_tenant = @current
      config = config_for(tenant)
      difference = current_difference_from(config)

      if difference[:host]
        connection_switch!(config, without_keys: [:database, :schema_search_path])
      end

      create_tenant!(config)
      simple_switch(config)
      @current = tenant

      import_database_schema
      seed_data if Innkeeper.seed_after_create

      yield if block_given?
    ensure
      switch!(previous_tenant) rescue reset
    end
  end
end

#current_difference_from(config) ⇒ Object



131
132
133
134
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 131

def current_difference_from(config)
  current_config = config_for(@current)
  config.select{ |k, v| current_config[k] != v }
end

#decorate(tenant) ⇒ Object



101
102
103
104
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 101

def decorate(tenant)
  decorator = Innkeeper.tenant_decorator
  decorator ? decorator.call(tenant) : tenant
end

#drop(tenant) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 53

def drop(tenant)
  previous_tenant = @current

  config = config_for(tenant)
  difference = current_difference_from(config)

  if difference[:host]
    connection_switch!(config, without_keys: [:database])
  end

  unless database_exists?(config[:database])
    raise TenantNotFound, "Error while dropping database #{config[:database]} for tenant #{tenant}"
  end

  Innkeeper.connection.drop_database(config[:database])

  @current = tenant
ensure
  switch!(previous_tenant) rescue reset
end

#import_database_schemaObject



149
150
151
152
153
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 149

def import_database_schema
  ActiveRecord::Schema.verbose = false

  load_or_abort(Innkeeper.database_schema_file) if Innkeeper.database_schema_file
end

#load_or_abort(file) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 159

def load_or_abort(file)
  if File.exist?(file)
    load(file)
  else
    abort %{#{file} doesn't exist yet}
  end
end

#process_excluded_modelsObject



106
107
108
109
110
111
112
113
114
115
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 106

def process_excluded_models
  excluded_config = config_for(Innkeeper.default_tenant).merge(name: :_innkeeper_excluded)
  Innkeeper.connection_handler.establish_connection(excluded_config)

  Innkeeper.excluded_models.each do |excluded_model|
    # user mustn't have overridden `connection_specification_name`
    # cattr_accessor in model
    excluded_model.constantize.connection_specification_name = :_innkeeper_excluded
  end
end

#raise_connect_error!(tenant, exception) ⇒ Object

Raises:



167
168
169
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 167

def raise_connect_error!(tenant, exception)
  raise TenantNotFound, "Error while connecting to tenant #{tenant}: #{exception.message}"
end

#resetObject



15
16
17
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 15

def reset
  switch!(Innkeeper.default_tenant)
end

#seed_dataObject



155
156
157
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 155

def seed_data
  silence_warnings{ load_or_abort(Innkeeper.seed_data_file) } if Innkeeper.seed_data_file
end

#setup_connection_specification_nameObject



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 117

def setup_connection_specification_name
  Innkeeper.connection_class.connection_specification_name = nil
  Innkeeper.connection_class.instance_eval do
    def connection_specification_name
      if !defined?(@connection_specification_name) || @connection_specification_name.nil?
        innkeeper_spec_name = Thread.current[:_innkeeper_connection_specification_name]
        return innkeeper_spec_name ||
          (self == ActiveRecord::Base ? "primary" : superclass.connection_specification_name)
      end
      @connection_specification_name
    end
  end
end

#switch(tenant = nil) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 19

def switch(tenant = nil)
  previous_tenant = @current
  switch!(tenant)

  yield
ensure
  switch!(previous_tenant) rescue reset
end

#switch!(tenant) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/innkeeper/adapters/abstract_adapter.rb', line 74

def switch!(tenant)
  run_callbacks :switch do
    return reset if tenant.nil?

    config = config_for(tenant)

    if Innkeeper.force_reconnect_on_switch
      connection_switch!(config)
    else
      switch_tenant(config)
    end

    @current = tenant

    Innkeeper.connection.clear_query_cache

    tenant
  end
end