Skip to content

IdentityMap

module

Defined in src/ralph/identity_map.cr:49

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.clear to manually clear the map within a scope

Class Methods

.all(model_class : T.class) : Array(T) forall T

View source

Get all models of a specific class from the identity map


.clear

View source

Clear all entries from the current identity map

Use this to free memory or to ensure fresh data is loaded.


.enabled?

View source

Check if an identity map is currently active


.get(model_class : T.class, id) : T | Nil forall T

View source

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.


.has?(model_class : T.class, id) : Bool forall T

View source

Check if a specific model is in the identity map


.remove(model_class : T.class, id) : Nil forall T

View source

Remove a model by class and id


.remove(model : Model) : Nil

View source

Remove a model from the identity map

This should be called after destroying a model.


.reset_stats

View source

Reset statistics


.set(model : Model) : Model

View source

Store a model in the identity map

This is called automatically after loading a model from the database.


.size

View source

Get the current size of the identity map


.stats

View source

Get identity map statistics


.with

View source

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

Nested Types

  • ModelStore -

    Type for storing models by class name and primary key Key format: "ClassName:primary_key_value"

  • Stats -

    Statistics for monitoring identity map usage