Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow a list of schemas when switching using schemas #154

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ switched back at the end of the block to what it was before.
There is also `switch!` which doesn't take a block, but it's recommended to use `switch`.
To return to the default tenant, you can call `switch` with no arguments.

#### Multiple Tenants

When using schemas, you can also pass in a list of schemas if desired. Any tables defined in a schema earlier in the chain will be referenced first, so this is only useful if you have a schema with only some of the tables defined:

```ruby
Apartment::Tenant.switch(['tenant_1', 'tenant_2']) do
# ...
end
```

### Switching Tenants per request

You can have Apartment route to the appropriate tenant by adding some Rack middleware.
Expand Down
6 changes: 2 additions & 4 deletions lib/apartment/adapters/jdbc_postgresql_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ class JDBCPostgresqlSchemaAdapter < PostgresqlSchemaAdapter
#
def connect_to_new(tenant = nil)
return reset if tenant.nil?
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless schema_exists?(tenant)

tenant = tenant.to_s
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless tenant_exists?(tenant)

@current = tenant
@current = tenant.is_a?(Array) ? tenant.map(&:to_s) : tenant.to_s
Apartment.connection.schema_search_path = full_search_path
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
raise TenantNotFound, "One of the following schema(s) is invalid: #{full_search_path}"
Expand Down
12 changes: 8 additions & 4 deletions lib/apartment/adapters/postgresql_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,9 @@ def drop_command(conn, tenant)
#
def connect_to_new(tenant = nil)
return reset if tenant.nil?
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless schema_exists?(tenant)

tenant = tenant.to_s
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless tenant_exists?(tenant)

@current = tenant
@current = tenant.is_a?(Array) ? tenant.map(&:to_s) : tenant.to_s
Apartment.connection.schema_search_path = full_search_path

# When the PostgreSQL version is < 9.3,
Expand Down Expand Up @@ -149,6 +147,12 @@ def reset_sequence_names
c.remove_instance_variable :@sequence_name if c.instance_variable_defined?(:@sequence_name)
end
end

def schema_exists?(schemas)
return true unless Apartment.tenant_presence_check

Array(schemas).all? { |schema| Apartment.connection.schema_exists?(schema.to_s) }
end
end

# Another Adapter for Postgresql when using schemas and SQL
Expand Down
2 changes: 0 additions & 2 deletions lib/apartment/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,9 @@ class Railtie < Rails::Railtie

# Overrides reload! to also call Apartment::Tenant.init as well
# so that the reloaded classes have the proper table_names
# rubocop:disable Lint/Debugger
console do
require 'apartment/console'
end
# rubocop:enable Lint/Debugger
end
end
end
7 changes: 7 additions & 0 deletions spec/examples/schema_adapter_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@
expect(connection.schema_search_path).to start_with %("#{public_schema}")
expect(User.sequence_name).to eq "#{public_schema}.#{User.table_name}_id_seq"
end

it 'allows a list of schemas' do
subject.switch([schema1, schema2]) do
expect(connection.schema_search_path).to include %("#{schema1}")
expect(connection.schema_search_path).to include %("#{schema2}")
end
end
end

describe '#reset' do
Expand Down