module GlobalID::Locator
Constants
- DEFAULT_LOCATOR
Public Class Methods
Takes either a GlobalID
or a string that can be turned into a GlobalID
Options:
-
:includes
- A Symbol, Array, Hash or combination of them. The same structure you would pass into aincludes
method of Active Record. If present, locate will load all the relationships specified here. See guides.rubyonrails.org/active_record_querying.html#eager-loading-associations. -
:only
- A class, module or Array of classes and/or modules that are allowed to be located. Passing one or more classes limits instances of returned classes to those classes or their subclasses. Passing one or more modules in limits instances of returned classes to those including that module. If no classes or modules match,nil
is returned.
# File lib/global_id/locator.rb, line 20 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
Takes an array of GlobalIDs or strings that can be turned into a GlobalIDs. All GlobalIDs must belong to the same app, as they will be located using the same locator using its locate_many
method.
By default the GlobalIDs will be located using Model.find(array_of_ids), so the models must respond to that finder signature.
This approach will efficiently call only one find (or where(id: id), when using ignore_missing) per model class, but still interpolate the results to match the order in which the gids were passed.
Options:
-
:includes
- A Symbol, Array, Hash or combination of them The same structure you would pass into a includes method of Active Record. @see guides.rubyonrails.org/active_record_querying.html#eager-loading-associations If present,locate_many
will load all the relationships specified here. Note: It only works if all the gids models have that relationships. -
:only
- A class, module or Array of classes and/or modules that are allowed to be located. Passing one or more classes limits instances of returned classes to those classes or their subclasses. Passing one or more modules in limits instances of returned classes to those including that module. If no classes or modules match,nil
is returned. -
:ignore_missing
- By default,locate_many
will call find on the model to locate the ids extracted from the GIDs. In Active Record (and other data stores following the same pattern), find will raise an exception if a named ID can’t be found. When you set this option to true, we will use where(id: ids) instead, which does not raise on missing records.
# File lib/global_id/locator.rb, line 60 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
Takes an array of SignedGlobalIDs or strings that can be turned into a SignedGlobalIDs. The SignedGlobalIDs are located using Model.find(array_of_ids), so the models must respond to that finder signature.
This approach will efficiently call only one find per model class, but still interpolate the results to match the order in which the gids were passed.
Options:
-
:includes
- A Symbol, Array, Hash or combination of them The same structure you would pass into a includes method of Active Record. @see guides.rubyonrails.org/active_record_querying.html#eager-loading-associations If present,locate_many_signed
will load all the relationships specified here. Note: It only works if all the gids models have that relationships. -
:only
- A class, module or Array of classes and/or modules that are allowed to be located. Passing one or more classes limits instances of returned classes to those classes or their subclasses. Passing one or more modules in limits instances of returned classes to those including that module. If no classes or modules match,nil
is returned.
# File lib/global_id/locator.rb, line 103 def locate_many_signed(sgids, options = {}) locate_many sgids.collect { |sgid| SignedGlobalID.parse(sgid, options.slice(:for)) }.compact, options end
Takes either a SignedGlobalID
or a string that can be turned into a SignedGlobalID
Options:
-
:includes
- A Symbol, Array, Hash or combination of them The same structure you would pass into a includes method of Active Record. @see guides.rubyonrails.org/active_record_querying.html#eager-loading-associations If present,locate_signed
will load all the relationships specified here. -
:only
- A class, module or Array of classes and/or modules that are allowed to be located. Passing one or more classes limits instances of returned classes to those classes or their subclasses. Passing one or more modules in limits instances of returned classes to those including that module. If no classes or modules match,nil
is returned.
# File lib/global_id/locator.rb, line 81 def locate_signed(sgid, options = {}) SignedGlobalID.find sgid, options end
Tie a locator to an app. Useful when different apps collaborate and reference each others’ Global IDs.
The locator can be either a block or a class.
Using a block:
GlobalID::Locator.use :foo do |gid, options| FooRemote.const_get(gid.model_name).find(gid.model_id) end
Using a class:
GlobalID::Locator.use :bar, BarLocator.new class BarLocator def locate(gid, options = {}) @search_client.search name: gid.model_name, id: gid.model_id end end
# File lib/global_id/locator.rb, line 127 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
Private Class Methods
# File lib/global_id/locator.rb, line 140 def find_allowed?(model_class, only = nil) only ? Array(only).any? { |c| model_class <= c } : true end
# File lib/global_id/locator.rb, line 136 def locator_for(gid) @locators.fetch(normalize_app(gid.app)) { DEFAULT_LOCATOR } end
# File lib/global_id/locator.rb, line 148 def normalize_app(app) app.to_s.downcase end
# File lib/global_id/locator.rb, line 144 def parse_allowed(gids, only = nil) gids.collect { |gid| GlobalID.parse(gid) }.compact.select { |gid| find_allowed?(gid.model_class, only) } end