Custom locator raises NameError when class name not defined
daveolib opened this issue · comments
If I have a custom locator, say:
GlobalID::Locator.use :generated do |gid, options|
# Return generated object based on GID
end
...
GlobalID.parse("gid://generated/DoesNotExist/123").find
Before it gets to my locator, the library calls constantize
on "DoesNotExist"
when trying to get the model_class
, even if there is no :only
set in the options.
I'm not sure what the best solution is here -- if you skip find_allowed?
when the :skip
option isn't set, that introduces some subtle behaviour. It could be interesting to open another hook, say :use_class
, which returns the class of the GID, but does not instantiate it. The find_allowed?
portion would not be changed.
Thoughts?
Ran into a similar issue just now, as I'm trying to use global IDs to store references to remote objects in a different service.
What I've decided doing at the moment is to delegate the model name resolution to the locator, as I want them to reside in their own ruby namespace to avoid (potential) conflicts with my app's models. That was the least intrusive patch I could find, if just requires patching the model_name
method on GlobalID
like this:
class GlobalID
def model_name
locator = GlobalID::Locator.send(:locator_for, self)
locator.try(:model_name, uri) || uri.model_name
end
end
This then allows me to register a locator like this:
module OtherApp
RemoteObjectResponse = Data.define(:id, ...)
class GidLocator
def locate(gid, _options = {})
api_client.get(gid.model_name, gid.model_id)
end
def model_name(uri)
"OtherApp::#{uri.model_name}Response"
end
end
end
GlobalID::Locator.use :other_app, OtherApp::GidLocator.new
lookup works then with:
GlobalID.parse("gid://other_app/RemoteObject/123").find
#=> OtherApp::RemoteObjectResponse object
BTW, the issue discussed here affects the example code in https://github.com/rails/globalid/blob/main/README.md#custom-app-locator.
For a real resolution in the project I think it'd be probably better to try and move the model class resolution/checking code from GobalID into the locators.
I can draft up a PR if that approach sounds acceptable?