Class: Penthouse::Tenants::SchemaTenant

Inherits:
BaseTenant
  • Object
show all
Includes:
Migratable
Defined in:
lib/penthouse/tenants/schema_tenant.rb

Direct Known Subclasses

OctopusSchemaTenant

Instance Attribute Summary collapse

Attributes inherited from BaseTenant

#identifier

Instance Method Summary collapse

Methods included from Migratable

#migrate

Constructor Details

#initialize(identifier, tenant_schema:, persistent_schemas: ["shared_extensions"], default_schema: "public") ⇒ SchemaTenant

Returns a new instance of SchemaTenant.

Parameters:

  • identifier (String, Symbol)

    An identifier for the tenant

  • tenant_schema (String)

    your tenant’s schema name in Postgres

  • persistent_schemas (Array<String>) (defaults to: ["shared_extensions"])

    The schemas you always want in the search path

  • default_schema (String) (defaults to: "public")

    The global schema name, usually ‘public’



24
25
26
27
28
29
30
# File 'lib/penthouse/tenants/schema_tenant.rb', line 24

def initialize(identifier, tenant_schema:, persistent_schemas: ["shared_extensions"], default_schema: "public")
  super(identifier)
  self.tenant_schema = tenant_schema.freeze
  self.persistent_schemas = Array(persistent_schemas).flatten.freeze
  self.default_schema = default_schema.freeze
  freeze
end

Instance Attribute Details

#default_schemaObject

Returns the value of attribute default_schema.



17
18
19
# File 'lib/penthouse/tenants/schema_tenant.rb', line 17

def default_schema
  @default_schema
end

#persistent_schemasObject

Returns the value of attribute persistent_schemas.



17
18
19
# File 'lib/penthouse/tenants/schema_tenant.rb', line 17

def persistent_schemas
  @persistent_schemas
end

#tenant_schemaObject

Returns the value of attribute tenant_schema.



17
18
19
# File 'lib/penthouse/tenants/schema_tenant.rb', line 17

def tenant_schema
  @tenant_schema
end

Instance Method Details

#call(&block) {|SchemaTenant| ... } ⇒ void

This method returns an undefined value.

switches to the tenant schema to run the block, ensuring we switch back afterwards, regardless of whether an exception occurs

Parameters:

  • block (Block)

    The code to execute within the schema

Yields:



37
38
39
40
41
42
43
44
45
46
# File 'lib/penthouse/tenants/schema_tenant.rb', line 37

def call(&block)
  begin
    # set the search path to include the tenant
    ActiveRecord::Base.connection.schema_search_path = persistent_schemas.dup.unshift(tenant_schema).join(", ")
    block.yield(self)
  ensure
    # reset the search path back to the default
    ActiveRecord::Base.connection.schema_search_path = persistent_schemas.dup.unshift(default_schema).join(", ")
  end
end

#create(run_migrations: Penthouse.configuration.migrate_tenants?, db_schema_file: Penthouse.configuration.db_schema_file) ⇒ void

This method returns an undefined value.

creates the tenant schema

Parameters:

  • run_migrations (Boolean) (defaults to: Penthouse.configuration.migrate_tenants?)

    whether or not to run migrations, defaults to Penthouse.configuration.migrate_tenants?

  • db_schema_file (String) (defaults to: Penthouse.configuration.db_schema_file)

    a path to the DB schema file to load, defaults to Penthouse.configuration.db_schema_file



52
53
54
55
56
57
58
# File 'lib/penthouse/tenants/schema_tenant.rb', line 52

def create(run_migrations: Penthouse.configuration.migrate_tenants?, db_schema_file: Penthouse.configuration.db_schema_file)
  sql = ActiveRecord::Base.send(:sanitize_sql_array, ["create schema if not exists %s", tenant_schema])
  ActiveRecord::Base.connection.exec_query(sql, 'Create Schema')
  if !!run_migrations
    migrate(db_schema_file: db_schema_file)
  end
end

#delete(force: true) ⇒ void

This method returns an undefined value.

drops the tenant schema

Parameters:

  • force (Boolean) (defaults to: true)

    whether or not to drop the schema if not empty, defaults to true



63
64
65
66
# File 'lib/penthouse/tenants/schema_tenant.rb', line 63

def delete(force: true)
  sql = ActiveRecord::Base.send(:sanitize_sql_array, ["drop schema if exists %s %s", tenant_schema, force ? 'cascade' : 'restrict'])
  ActiveRecord::Base.connection.exec_query(sql, 'Delete Schema')
end

#exists?Boolean

returns whether or not this tenant’s schema exists

Returns:

  • (Boolean)

    whether or not the tenant exists



70
71
72
73
74
# File 'lib/penthouse/tenants/schema_tenant.rb', line 70

def exists?
  sql = ActiveRecord::Base.send(:sanitize_sql_array, ["select 1 from pg_namespace where nspname = '%s'", tenant_schema])
  result = ActiveRecord::Base.connection.exec_query(sql, "Schema Exists")
  !result.rows.empty?
end