Class: Shamu::Entities::EntityLookupService
- Inherits:
-
Services::Service
- Object
- Services::Service
- Shamu::Entities::EntityLookupService
- Defined in:
- lib/shamu/entities/entity_lookup_service.rb
Overview
Looks up entities from compiled EntityPath strings allowing references to be stored as opaque values in an external service and later looked up without knowing which services are required to look up the entities.
Useful for implementing a node
field in a Relay GraphQL endpoint or
resolving entities in an audit log.
#lookup maps entity types to the service class used to look up entities
of that type. The services must implement the well known #lookup
method
that takes an array of ids as an argument.
If there is no entry mapping in the entity_map
provided to the
constructor then EntityLookupService will attempt to locate a service
named Shamu::EntitiesService in the same namespace as the entity type.
The EntityLookupService should be configured as a per-request singleton in Scorpion with all custom entity mappings set.
Scorpion.prepare do
capture Shamu::Entities::EntityLookupService do |scorpion|
scorpion.new( Shamu::Entities::EntityLookupService, { "User" => Users::ExternalUsersService }, {} )
end
end
Direct Known Subclasses
Instance Method Summary collapse
-
#ids(entities) ⇒ Object
Map the given entities to their EntityPath that can later be used to #lookup the given entity.
-
#initialize(entity_map = nil) ⇒ EntityLookupService
constructor
A new instance of EntityLookupService.
-
#lookup(*ids) ⇒ EntityList<Entity>
Look up all the entities from their composed EntityPath.
-
#record_ids(ids) ⇒ Object
Map the encoded ids back to their raw record IDs discarding any type information.
-
#service_class_for(entity_type) ⇒ Shamu::Services::Service
Gets the class of the service used to look up entities of the given type.
Methods inherited from Services::Service
#cache_for, #cached_lookup, #entity_list, #entity_lookup_list, #find_by_lookup, #lazy_association, #lookup_association
Constructor Details
#initialize(entity_map = nil) ⇒ EntityLookupService
Returns a new instance of EntityLookupService.
33 34 35 36 37 38 39 40 41 |
# File 'lib/shamu/entities/entity_lookup_service.rb', line 33 def initialize( entity_map = nil ) entity_map ||= {} @entity_map_cache = Hash.new do |hash, entity_type| hash[ entity_type ] = entity_map[ entity_type ] \ || entity_map[ entity_type.to_s ] \ || find_implicit_service_class( entity_type.to_s ) end super() end |
Instance Method Details
#ids(entities) ⇒ Object
Map the given entities to their Shamu::Entities::EntityPath that can later be used to #lookup the given entity.
53 54 55 56 57 |
# File 'lib/shamu/entities/entity_lookup_service.rb', line 53 def ids( entities ) Array.wrap( entities ).map do |entity| EntityPath.compose_entity_path( [ entity ] ) end end |
#lookup(*ids) ⇒ EntityList<Entity>
Look up all the entities from their composed Shamu::Entities::EntityPath.
given ids.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/shamu/entities/entity_lookup_service.rb', line 74 def lookup( *ids ) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize types = {} # Decompose entity paths and group by entity type ids.each do |composed| path = EntityPath.decompose_entity_path( composed ) fail "Only root entities can be restored" unless path.size == 1 type, id = path.first types[ type ] ||= { paths: [], ids: [] } types[ type ][ :paths ] << composed types[ type ][ :ids ] << id end # Short-circuit if we only have one entity type if types.size == 1 service_class = service_class_for( types.first.first ) service = scorpion.fetch service_class return service.lookup( *types.first.last[ :ids ] ) end # Lookup all entities in batches hydrated = types.map do |type, map| service_class = service_class_for( type ) service = scorpion.fetch service_class entities = service.lookup( *map[ :ids ] ) Hash[ map[ :paths ].zip( entities ) ] end # Map found entities back to their original input order mapped = ids.map do |id| found = nil hydrated.each do |map| break if found = map[ id ] end found end Entities::List.new mapped end |
#record_ids(ids) ⇒ Object
Map the encoded ids back to their raw record IDs discarding any type information.
63 64 65 66 67 |
# File 'lib/shamu/entities/entity_lookup_service.rb', line 63 def record_ids( ids ) Array.wrap( ids ).map do |id| EntityPath.decompose_entity_path( id ).first.last.to_model_id end end |
#service_class_for(entity_type) ⇒ Shamu::Services::Service
Gets the class of the service used to look up entities of the given type. Use a scorpion to get an instance of the service class.
47 48 49 |
# File 'lib/shamu/entities/entity_lookup_service.rb', line 47 def service_class_for( entity_type ) entity_map_cache[ entity_type.to_sym ] end |