module GlobalID::Locator
def find_allowed?(model_class, only = nil)
def find_allowed?(model_class, only = nil) only ? Array(only).any? { |c| model_class <= c } : true end
def locate(gid, options = {})
instances of returned classes to those including that module. If no classes or
classes to those classes or their subclasses. Passing one or more modules in limits
allowed to be located. Passing one or more classes limits instances of returned
* :only - A class, module or Array of classes and/or modules that are
See https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations.
If present, locate will load all the relationships specified here.
The same structure you would pass into a +includes+ method of Active Record.
* :includes - A Symbol, Array, Hash or combination of them.
Options:
Takes either a GlobalID or a string that can be turned into a GlobalID
def locate(gid, options = {}) gid = GlobalID.parse(gid) return unless gid && find_allowed?(gid.model_class, options[:only]) locator = locator_for(gid) if locator.method(:locate).arity == 1 GlobalID.deprecator.warn "It seems your locator is defining the `locate` method only with one argument. Please make sure your locator is receiving the options argument as well, like `locate(gid, options = {})`." locator.locate(gid) else locator.locate(gid, options.except(:only)) end end
def locate_many(gids, options = {})
- See: https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations -
def locate_many(gids, options = {}) if (allowed_gids = parse_allowed(gids, options[:only])).any? locator = locator_for(allowed_gids.first) locator.locate_many(allowed_gids, options) else [] end end
def locate_many_signed(sgids, options = {})
- See: https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations -
def locate_many_signed(sgids, options = {}) locate_many sgids.collect { |sgid| SignedGlobalID.parse(sgid, options.slice(:for)) }.compact, options end
def locate_signed(sgid, options = {})
- See: https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations -
def locate_signed(sgid, options = {}) SignedGlobalID.find sgid, options end
def locator_for(gid)
def locator_for(gid) @locators.fetch(normalize_app(gid.app)) { DEFAULT_LOCATOR } end
def normalize_app(app)
def normalize_app(app) app.to_s.downcase end
def parse_allowed(gids, only = nil)
def parse_allowed(gids, only = nil) gids.collect { |gid| GlobalID.parse(gid) }.compact.select { |gid| find_allowed?(gid.model_class, only) } end
def use(app, locator = nil, &locator_block)
end
@search_client.search name: gid.model_name, id: gid.model_id
def locate(gid, options = {})
class BarLocator
GlobalID::Locator.use :bar, BarLocator.new
Using a class:
end
FooRemote.const_get(gid.model_name).find(gid.model_id)
GlobalID::Locator.use :foo do |gid, options|
Using a block:
The locator can be either a block or a class.
Useful when different apps collaborate and reference each others' Global IDs.
Tie a locator to an app.
def use(app, locator = nil, &locator_block) raise ArgumentError, 'No locator provided. Pass a block or an object that responds to #locate.' unless locator || block_given? URI::GID.validate_app(app) @locators[normalize_app(app)] = locator || BlockLocator.new(locator_block) end