-
Notifications
You must be signed in to change notification settings - Fork 463
Fully separate schema: common vs tenant #117
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
base: master
Are you sure you want to change the base?
Changes from all commits
dbcb828
3c0f433
45e14a7
c4495ee
a0c7b10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,22 @@ def drop(tenant) | |
| raise SchemaNotFound, "The schema #{tenant.inspect} cannot be found." | ||
| end | ||
|
|
||
| def load(tenant) | ||
| # require 'active_record/schema_dumper' | ||
| # filename = File.join(Apartment.migration_path, "#{tenant}_schema.rb") | ||
| # File.open(filename, "w:utf-8") do |file| | ||
| # ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) | ||
| # end | ||
| end | ||
|
|
||
| def dump(tenant) | ||
| require 'active_record/schema_dumper' | ||
| filename = File.join(Apartment.migration_path, "..", "#{tenant}_schema.rb") | ||
| File.open(filename, "w:utf-8") do |file| | ||
| ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) | ||
| end | ||
| end | ||
|
|
||
| # Reset search path to default search_path | ||
| # Set the table_name to always use the default namespace for excluded models | ||
| # | ||
|
|
@@ -84,12 +100,16 @@ def current_tenant | |
|
|
||
| # Set schema search path to new schema | ||
| # | ||
| def connect_to_new(tenant = nil) | ||
| def connect_to_new(tenant = nil, exclusive = false) | ||
| return reset if tenant.nil? | ||
| raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.schema_exists? tenant | ||
|
|
||
| @current_tenant = tenant.to_s | ||
| Apartment.connection.schema_search_path = full_search_path | ||
| if exclusive | ||
| Apartment.connection.schema_search_path = @current_tenant | ||
| else | ||
| Apartment.connection.schema_search_path = full_search_path | ||
| end | ||
|
|
||
| rescue *rescuable_exceptions | ||
| raise SchemaNotFound, "One of the following schema(s) is invalid: #{tenant}, #{full_search_path}" | ||
|
|
@@ -113,7 +133,19 @@ def full_search_path | |
| end | ||
|
|
||
| def persistent_schemas | ||
| [@current_tenant, Apartment.persistent_schemas].flatten | ||
| case Apartment.persistent_schemas | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This type of case/switch will not be accepted in Apartment. It's pretty explicitly going against OO. I'd prefer to have some sort of interface that the persistent Something like the |
||
| when Proc | ||
| result = Apartment.persistent_schemas.call(@current_tenant) | ||
| when Hash | ||
| result = Apartment.persistent_schemas[@current_tenant] | ||
| when Array | ||
| result = Apartment.persistent_schemas | ||
| when String | ||
| result = Apartment.persistent_schemas.split(',') | ||
| when NilClass | ||
| return [@current_tenant] | ||
| end | ||
| [@current_tenant, result].flatten.uniq | ||
| end | ||
| end | ||
| end | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,27 +7,55 @@ module Migrator | |
|
|
||
| # Migrate to latest | ||
| def migrate(database) | ||
| ensure_schema_migrations_table_exists(database) | ||
| Database.process(database) do | ||
| version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil | ||
|
|
||
| ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, version) do |migration| | ||
| ActiveRecord::Migrator.migrate(migration_paths(database), version) do |migration| | ||
| ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope) | ||
| end | ||
| end | ||
| dump_schema(database) | ||
| end | ||
|
|
||
| # Migrate up/down to a specific version | ||
| def run(direction, database, version) | ||
| ensure_schema_migrations_table_exists(database) | ||
| Database.process(database) do | ||
| ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_paths, version) | ||
| ActiveRecord::Migrator.run(direction, migration_paths(database), version) | ||
| end | ||
| dump_schema(database) | ||
| end | ||
|
|
||
| # rollback latest migration `step` number of times | ||
| def rollback(database, step = 1) | ||
| ensure_schema_migrations_table_exists(database) | ||
| Database.process(database) do | ||
| ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step) | ||
| ActiveRecord::Migrator.rollback(migration_paths(database), step) | ||
| end | ||
| dump_schema(database) | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def ensure_schema_migrations_table_exists(database) | ||
| Database.process(database, true) do | ||
| ActiveRecord::SchemaMigration.create_table | ||
| end | ||
| end | ||
|
|
||
| def dump_schema(database) | ||
| puts "dump_schema(#{database})" | ||
| Database.process(database, true) do | ||
| Database.dump(database) | ||
| end | ||
| end | ||
|
|
||
| def migration_paths(tenant) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| paths = [Apartment.migration_path] | ||
| paths << "#{Apartment.migration_path}/../#{tenant}" if File.exists?("#{Apartment.migration_path}/../#{tenant}") | ||
| paths | ||
| end | ||
|
|
||
| end | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I Don't think I agree with this default. Can you explain why you think Apartment shouldn't migrate the tenants by default?
I'm just trying to look at things from a new user's perspective. Someone that doesn't know Apartment that well would have to know to enable this, rather than it just working out of the box. More advanced users can disable it to their liking, but I'd like to err on the side of simplicity