Some tasks don't have to run on every tenant. The task to calculate the TSV is only done for records which were present before we added the TSV column, and that isn't going to happen in any tenants because we added the TSV column before adding the tenants table. Similarly, the migration needed for existing polls isn't necessary because there weren't any tenants before we allowed to set the starting/ending time to polls. We aren't adding any tests for these tasks because tests for rake tasks are slow and tests creating tenants are also slow, making the combination of the two even slower, particularly if we add tests for every single task we're changing. We're adding tests for the `.run_on_each` method instead.
70 lines
1.6 KiB
Ruby
70 lines
1.6 KiB
Ruby
class Tenant < ApplicationRecord
|
|
validates :schema,
|
|
presence: true,
|
|
uniqueness: true,
|
|
exclusion: { in: ->(*) { excluded_subdomains }},
|
|
format: { with: URI::DEFAULT_PARSER.regexp[:HOST] }
|
|
validates :name, presence: true, uniqueness: true
|
|
|
|
after_create :create_schema
|
|
after_update :rename_schema
|
|
after_destroy :destroy_schema
|
|
|
|
def self.resolve_host(host)
|
|
return nil unless Rails.application.config.multitenancy.present?
|
|
return nil if host.blank? || host.match?(Resolv::AddressRegex)
|
|
|
|
host_domain = allowed_domains.find { |domain| host == domain || host.ends_with?(".#{domain}") }
|
|
host.delete_prefix("www.").sub(/\.?#{host_domain}\Z/, "").presence
|
|
end
|
|
|
|
def self.allowed_domains
|
|
dev_domains = %w[localhost lvh.me example.com]
|
|
dev_domains + [default_host]
|
|
end
|
|
|
|
def self.excluded_subdomains
|
|
%w[mail public shared_extensions www]
|
|
end
|
|
|
|
def self.default_host
|
|
ActionMailer::Base.default_url_options[:host]
|
|
end
|
|
|
|
def self.current_schema
|
|
Apartment::Tenant.current
|
|
end
|
|
|
|
def self.default?
|
|
current_schema == "public"
|
|
end
|
|
|
|
def self.switch(...)
|
|
Apartment::Tenant.switch(...)
|
|
end
|
|
|
|
def self.run_on_each(&block)
|
|
["public"].union(Apartment.tenant_names).each do |schema|
|
|
switch(schema, &block)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def create_schema
|
|
Apartment::Tenant.create(schema)
|
|
end
|
|
|
|
def rename_schema
|
|
if saved_change_to_schema?
|
|
ActiveRecord::Base.connection.execute(
|
|
"ALTER SCHEMA \"#{schema_before_last_save}\" RENAME TO \"#{schema}\";"
|
|
)
|
|
end
|
|
end
|
|
|
|
def destroy_schema
|
|
Apartment::Tenant.drop(schema)
|
|
end
|
|
end
|