Single app with multiple databases?
opened this issue · comments
My app switches to a different database based on subdomain using:
Mongoid.override_database("timeline_#{subdomain}_production")
So when the globalid is generated, it looks something like:
gid://timeline/User/55230a4278616e6fbc010000
This does not help because this ID is meaningless without knowing what the subdomain or the database name is. I am looking for something like:
gid://timeline/database_name/User/55230a4278616e6fbc010000
So that ActiveJob or whatever is responsible for finding the record knows where to actually look for it.
Any ideas/suggestions?
P.S. this is related to this issue: rails/activejob#112
one option you have is to pass the database name as GID parameter. In your model:
class User
def to_global_id(options = {})
options[:database] = current_database
super(options)
end
end
and in an initializer setup a locator for your applications
GlobalID::Locator.use :template do |gid|
Mongoid.override_database gid.params[:database]
gid.model_class.find(gid.model_id)
end
What @cristianbica said is the right direction to go in. Also we try to keep the issue tracker for bugs only. Please try Stack Overflow for help where a wider community can help you. Thanks 😁
Thank you, this worked beautifully:
# in config/initializers/global_id.rb
GlobalID::Locator.use :timeline do |gid|
database_switcher = DatabaseSwitcher.new
database_switcher.switch_to gid.params[:timeline_name]
gid.model_class.find(gid.model_id)
end
# in my model
include GlobalID::Identification # For activejob (delayed emailing, etc)
def to_global_id(options = {})
options[:timeline_name] = timeline_name
super(options)
end
I had an issue where ActionText::Attachable
introduces the use of:
def attachable_sgid
to_sgid(expires_in: nil, for: LOCATOR_NAME).to_s
end
I've already overridden to_global_id
with something like this:
module DomainHashGlobalId
extend ActiveSupport::Concern
def to_global_id(options = {})
options[:domain_hash] = SiteSetting[:entity].domain_hash
super(options)
end
end
ActiveSupport.on_load :active_storage_record do
include DomainHashGlobalId
end
Unfortunately to_signed_global_id
(to_sgid
) doesn't seem to use to_global_id
to get its non-secure value and I have to override it also in my concern with:
def to_signed_global_id(options = {})
options[:domain_hash] = SiteSetting[:entity].domain_hash
super(options)
end
I've had a pretty thorough look through the code and can't see why these two methods would behave differently since the Signed version of the class inherits of the standard GlobalID
class. So strange :)
Actually, the more I look at it, the two methods are first class and one doesn't depend on the other. Makes overriding them a bit more nuanced! :)
Turns out one needs to also redefine the aliases for them to point to our new methods:
module DomainHashGlobalId
extend ActiveSupport::Concern
def to_global_id(options = {})
options[:domain_hash] = SiteSetting[:entity].domain_hash
super(options)
end
alias to_gid to_global_id
def to_signed_global_id(options = {})
options[:domain_hash] = SiteSetting[:entity].domain_hash
super(options)
end
alias to_sgid to_signed_global_id
end
ActionText::Attachable
uses to_sgid
specifically: