-
Notifications
You must be signed in to change notification settings - Fork 168
Synchronise subdomain domain CRUD actions in the database with a Heroku instance via Heroku's Platform API
Rui edited this page Nov 11, 2020
·
2 revisions
I've spent a lot of time consolidating information creating a pattern that uses a series of callbacks on a Tenant model that synchronises subdomain/domain CRUD actions in the database with a Heroku instance via Heroku's Platform API. I think this could be useful for a lot of people using this gem. For now, here's a snapshot of what I've done...
class Organisation < ApplicationRecord
# version control
has_paper_trail
# validations
validates :name, length: { in: 3..100 }, presence: true
validates :subdomain, length: { in: 3..20 }, presence: true, uniqueness: true
validates { subdomain_available_on_heroku } unless Rails.env.development?
after_create { create_tenant }
after_destroy { remove_tenant }
after_save { rename_tenant }
private
def subdomain_available_on_heroku
# get list of domains from Heroku
domain_list = heroku.domain.list(app_id)
# check if domains include the subdomain and abort if so
if domain_list.include?(self.subdomain)
errors.add(:subdomain, 'something has gone wrong - the subdomain is available in the database but not available on Heroku')
throw(:abort)
end
end
def create_tenant
Apartment::Tenant.create(self.subdomain)
# create the subdomain on heroku
unless Rails.env.development?
heroku.domain.create(ENV['HEROKU_APP_ID'], "#{self.subdomain}.#{ENV['DOMAIN_NAME']}")
end
end
def remove_tenant
Apartment::Tenant.drop(self.subdomain)
# cleanup the subdomain on heroku
unless Rails.env.development?
heroku.domain.delete(ENV['HEROKU_APP_ID'], "#{self.subdomain}.#{ENV['DOMAIN_NAME']}")
end
end
def rename_tenant
if self.paper_trail.previous_version.present? && self.paper_trail.previous_version.subdomain != self.subdomain
ActiveRecord::Base.connection.execute("ALTER SCHEMA \"#{self.paper_trail.previous_version.subdomain}\" RENAME TO \"#{self.subdomain}\";")
# cleanup the subdomain on heroku
unless Rails.env.development?
heroku.domain.delete(ENV['HEROKU_APP_ID'], "#{self.paper_trail.previous_version.subdomain}.#{ENV['DOMAIN_NAME']}")
heroku.domain.create(ENV['HEROKU_APP_ID'], "#{self.subdomain}.#{ENV['DOMAIN_NAME']}")
end
end
end
end