Skip to content
Permalink
Browse files

Check if model responds to unscoped before locating many.

When attempting to locate many gids, if the first gid in the collection
responded to `unscoped` the rest of the gids would be assumed to also
respond to it, but that's unreliable.

Instead, refactor UnscopedLocator to check if the model class responds
to `unscoped` before finding and let the super locate if it doesn't.

This uncovered that the unscoped check in `locator_for` should be moved
into the UnscopedLocator. Then the unscoped locator can be the default
locator.

Fixes #82.
  • Loading branch information
kaspth committed Jan 6, 2016
1 parent ab8524e commit 2d4bc2d12761a737a5eb3f22fdb35ca8bc5f736b
Showing with 19 additions and 9 deletions.
  1. +14 −9 lib/global_id/locator.rb
  2. +5 −0 test/cases/global_locator_test.rb
@@ -106,9 +106,7 @@ def use(app, locator = nil, &locator_block)

private
def locator_for(gid)
@locators.fetch(normalize_app(gid.app)) do
gid.model_class.respond_to?(:unscoped) ? UNSCOPED_LOCATOR : DEFAULT_LOCATOR
end
@locators.fetch(normalize_app(gid.app)) { DEFAULT_LOCATOR }
end

def find_allowed?(model_class, only = nil)
@@ -127,7 +125,7 @@ def normalize_app(app)
private
@locators = {}

class DefaultLocator
class BaseLocator
def locate(gid)
gid.model_class.find gid.model_id
end
@@ -151,19 +149,26 @@ def find_records(model_class, ids, options)
end
end
end
DEFAULT_LOCATOR = DefaultLocator.new

class UnscopedLocator < DefaultLocator
class UnscopedLocator < BaseLocator
def locate(gid)
gid.model_class.unscoped { super }
if gid.model_class.respond_to?(:unscoped)
gid.model_class.unscoped { super }
else
super
end
end

private
def find_records(model_class, ids, options)
model_class.unscoped { super }
if model_class.respond_to?(:unscoped)
model_class.unscoped { super }
else
super
end
end
end
UNSCOPED_LOCATOR = UnscopedLocator.new
DEFAULT_LOCATOR = UnscopedLocator.new

class BlockLocator
def initialize(block)
@@ -264,4 +264,9 @@ class ScopedRecordLocatingTest < ActiveSupport::TestCase
assert_equal [ Person::Scoped.new('1'), Person::Scoped.new('2') ],
GlobalID::Locator.locate_many([ Person::Scoped.new('1').to_gid, Person::Scoped.new('2').to_gid ])
end

test "by many with scoped and unscoped records" do
assert_equal [ Person::Scoped.new('1'), Person.new('2') ],
GlobalID::Locator.locate_many([ Person::Scoped.new('1').to_gid, Person.new('2').to_gid ])
end
end

0 comments on commit 2d4bc2d

Please sign in to comment.
You can’t perform that action at this time.