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

Idea: Locating embedded resources #174

Open
stevecrozz opened this issue Feb 1, 2024 · 0 comments
Open

Idea: Locating embedded resources #174

stevecrozz opened this issue Feb 1, 2024 · 0 comments

Comments

@stevecrozz
Copy link

The code I am providing here is to illustrate an idea, a seed for discussion, not a proposal to adopt it as-is.

Nevertheless, I have put together some handy code that lets me locate resources that are embedded within other resources, for example, embedded within a serialized column, like a postgres jsonb structure. I could make another gem out of this, but some form of this idea seems pretty generally useful. I wonder if the community here has any thoughts on whether this idea is worth iterating on, or importing into the globalid project.

The concept is a regular URI::GID where a "host model" can be located in the normal way, but adds additional params to the URI::GID in order to locate an object that is only locatable within its host. This implementation imposes no requirements on the name or format of those params, only that whatever params exist can be used by the "host model" to locate the required sub-resource. The host model need only implement an instance method, gid_sublocate in this case, and given the gid property, it can do whatever work is needed to find the specified subresource.

In a nutshell, this means resources that are not normally globally addressable can become globally addressable by leaning on the addressability of some host model.

# Allows objects to be located within other objects and referenced through the
# GlobalID gem. In order to participate, the sublocatable's class must
# implement an instance method `to_global_id` and the host class must implement
# `gid_sublocate`
#
# # Returns a sublocated object if one can be found, for example:
# def gid_sublocator(gid)
#   key = gid.params[:some_key]
#   serialized_column[key]
# end
#
# # Returns a GlobalID object which will be passed to gid_sublocator to
# # locate this object later, for example:
# def to_global_id(options = {})
#   GlobalID.new(
#     URI::GID.build(
#       app: GlobalID.app,
#       model_name: 'Host::Model',
#       model_id: 123,
#       params: {
#         some_key: 'abc'
#       }
#     )
#   )
# end
class GidSublocator < GlobalID::Locator::UnscopedLocator
  def locate(gid, options = {})
    sublocate(super, gid)
  end

  def locate_many(gids, options = {})
    super.zip(gids).map do |(located, gid)|
      sublocate(located, gid)
    end
  end

  private def sublocate(located, gid)
    located.try(:gid_sublocate, gid) || located
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant