Ralph::IdentityMap
Per-request identity map for loaded models
The identity map ensures that within a given scope, loading the same record multiple times returns the same object instance. This:
- Prevents duplicate objects for the same database record
- Reduces memory usage when the same records are accessed repeatedly
- Ensures consistency when modifying objects
Usage
The identity map is scoped to a block using IdentityMap.with:
Ralph::IdentityMap.with do
user1 = User.find(1)
user2 = User.find(1) # Returns same instance from identity map
user1.object_id == user2.object_id # => true
# Changes to one reference affect all references
user1.name = "New Name"
user2.name # => "New Name"
end
Web Framework Integration
In web frameworks, you typically enable the identity map for each request:
# In a before_action or middleware
Ralph::IdentityMap.with do
# Handle request...
call_next(context)
end
Thread Safety
The identity map uses fiber-local storage, so each fiber/request has its own isolated identity map. This is safe for concurrent requests.
Caveats
- The identity map only works within the scope of
IdentityMap.with - Outside this scope, each query returns new model instances
- Be careful with long-running identity maps as they can accumulate memory
- Call
IdentityMap.clearto manually clear the map within a scope
Class methods
Get all models of a specific class from the identity map
Clear all entries from the current identity map
Use this to free memory or to ensure fresh data is loaded.
Get a model from the identity map
Returns the cached model if found, nil otherwise. This is called automatically by Model.find and similar methods.
Check if a specific model is in the identity map
Remove a model from the identity map
This should be called after destroying a model.
Store a model in the identity map
This is called automatically after loading a model from the database.
Execute a block with an identity map enabled
Within this block, loading the same record multiple times will return the same object instance.
Example
Ralph::IdentityMap.with do
user1 = User.find(1)
user2 = User.find(1)
user1.object_id == user2.object_id # => true
end