Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make DEFAULT_LOCATOR Configurable #179

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions lib/global_id/global_id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions lib/global_id/locator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions test/cases/global_locator_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -386,13 +386,32 @@ 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
yield
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
Expand Down
Loading