diff --git a/README.md b/README.md index c5c0b96..b72d484 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,28 @@ end After defining locators as above, URIs like "gid://foo/Person/1" and "gid://bar/Person/1" will now use the foo block locator and `BarLocator` respectively. Other apps will still keep using the default locator. +### Custom Default Locator + +A custom default locator can be set for an app by calling `GlobalID::Locator.default_locator=` and providing a default locator to use for that app. + +```ruby +class MyCustomLocator < UnscopedLocator + def locate(gid, options = {}) + ActiveRecord::Base.connected_to(role: :reading) do + super(gid, options) + end + end + + def locate_many(gids, options = {}) + ActiveRecord::Base.connected_to(role: :reading) do + super(gids, options) + end + end +end + +GlobalID::Locator.default_locator = MyCustomLocator.new +``` + ## Contributing to GlobalID GlobalID is work of many contributors. You're encouraged to submit pull requests, propose diff --git a/lib/global_id/global_id.rb b/lib/global_id/global_id.rb index 1082326..9bf961f 100644 --- a/lib/global_id/global_id.rb +++ b/lib/global_id/global_id.rb @@ -32,6 +32,10 @@ def app=(app) @app = URI::GID.validate_app(app) end + def default_locator(default_locator) + Locator.default_locator = default_locator + end + private def parse_encoded_gid(gid, options) new(Base64.urlsafe_decode64(gid), options) rescue nil diff --git a/lib/global_id/locator.rb b/lib/global_id/locator.rb index 0b4ebbc..c9edc5e 100644 --- a/lib/global_id/locator.rb +++ b/lib/global_id/locator.rb @@ -5,6 +5,9 @@ module Locator class InvalidModelIdError < StandardError; end class << self + # The default locator used when no app-specific locator is found. + attr_accessor :default_locator + # Takes either a GlobalID or a string that can be turned into a GlobalID # # Options: @@ -134,7 +137,7 @@ def use(app, locator = nil, &locator_block) private def locator_for(gid) - @locators.fetch(normalize_app(gid.app)) { DEFAULT_LOCATOR } + @locators.fetch(normalize_app(gid.app)) { default_locator } end def find_allowed?(model_class, only = nil) @@ -223,7 +226,8 @@ def unscoped(model_class) end end end - DEFAULT_LOCATOR = UnscopedLocator.new + + self.default_locator = UnscopedLocator.new class BlockLocator def initialize(block) diff --git a/test/cases/global_locator_test.rb b/test/cases/global_locator_test.rb index 1fecbbf..5165c85 100644 --- a/test/cases/global_locator_test.rb +++ b/test/cases/global_locator_test.rb @@ -386,6 +386,18 @@ def locate_many(gids, options = {}); gids.map(&:model_id); end assert_equal 2, found.length end + test "can set default_locator" do + class MyLocator + def locate(gid) + :my_locator + end + end + + with_default_locator(MyLocator.new) do + assert_equal :my_locator, GlobalID::Locator.locate('gid://app/Person/1') + end + end + private def with_app(app) old_app, GlobalID.app = GlobalID.app, app @@ -393,6 +405,13 @@ def with_app(app) ensure GlobalID.app = old_app end + + def with_default_locator(default_locator) + old_locator, GlobalID::Locator.default_locator = GlobalID::Locator.default_locator, default_locator + yield + ensure + GlobalID::Locator.default_locator = old_locator + end end class ScopedRecordLocatingTest < ActiveSupport::TestCase