Class: Guacamole::IdentityMap

Inherits:
Object
  • Object
show all
Defined in:
lib/guacamole/identity_map.rb

Overview

This class implements the 'Identity Map' pattern (Fowler, EAA, 195) to ensure only one copy of the same database document is present in memory within the same session. Internally a Hamster::Hash is used. This hash implementation is immutable and thus it is safe to use the current IdentityMap implementation in concurrent situations.

The IdentityMap should be purged after any unit of work (i.e. a request). If used in Rails the Session middleware will automatically be registered. For other Rack-based use cases you must register it yourself. For all other use cases you need to take when to call IdentityMap.reset all by yourself.

Defined Under Namespace

Classes: Session

Class Method Summary collapse

Class Method Details

.identity_map_instanceHamster::Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The internally used map

Returns:

  • (Hamster::Hash)

    an instance of an immutable hash



119
120
121
# File 'lib/guacamole/identity_map.rb', line 119

def identity_map_instance
  @identity_map_instance ||= Hamster.hash
end

.include?(object_or_class, key = nil) ⇒ true, false

Tests if the map contains some object

The method accepts either a class and key or just any Object that responds to key. Supporting both is made for your convenience.

Parameters:

  • object_or_class (Object#read, Class)

    Either the object to check or the class of the object you're looking for

  • key (Object, nil) (defaults to: nil)

    In case you provided a Class as first parameter you must provide the key for the object here

Returns:

  • (true, false)

    does the map contain the object or not



101
102
103
# File 'lib/guacamole/identity_map.rb', line 101

def include?(object_or_class, key = nil)
  identity_map_instance.key? key_for(object_or_class, key)
end

.key_for(object_or_class, key = nil) ⇒ Array(Class, Object)

Constructs the key used internally by the map

Parameters:

  • object_or_class (Object#read, Class)

    Either an object or a Class

  • key (Object, nil) (defaults to: nil)

    In case you provided a Class as first parameter you must provide the key for the object here

Returns:

  • (Array(Class, Object))

    the created key



111
112
113
# File 'lib/guacamole/identity_map.rb', line 111

def key_for(object_or_class, key = nil)
  key ? [object_or_class, key] : [object_or_class.class, object_or_class.key]
end

.resetnil

Purges all stored object from the map by setting the internal structure to nil

Returns:

  • (nil)


51
52
53
# File 'lib/guacamole/identity_map.rb', line 51

def reset
  @identity_map_instance = nil
end

.retrieve(klass, key) ⇒ Object

Retrieves a stored object from the map

Parameters:

  • klass (Class)

    The class of the object you want to get

  • key (Object)

    Whatever is the key of that object

Returns:

  • (Object)

    the stored object



71
72
73
# File 'lib/guacamole/identity_map.rb', line 71

def retrieve(klass, key)
  identity_map_instance.get key_for(klass, key)
end

.retrieve_or_store(klass, key) { ... } ⇒ Object

Retrieves a stored object or adds it based on the block if it is not already present

This can be used to retrieve and store in one step. See DocumentModelMapper#document_to_model for an example.

Parameters:

  • klass (Class)

    The class of the object you want to get

  • key (Object)

    Whatever is the key of that object

Yields:

  • A block if the object is not already present

Yield Returns:

  • (Object#read)

    the object to store. The key and class should match with input params

Returns:

  • (Object)

    the stored object



85
86
87
88
89
# File 'lib/guacamole/identity_map.rb', line 85

def retrieve_or_store(klass, key, &block)
  return retrieve(klass, key) if include?(klass, key)

  store block.call
end

.store(object) ⇒ Object#key

Add an object to the map

The object must implement a key method. There is no check if that method is present.

Parameters:

  • object (Object#key)

    Any object that implements the key method (and has a class)

Returns:

  • (Object#key)

    the object which just has been stored



61
62
63
64
# File 'lib/guacamole/identity_map.rb', line 61

def store(object)
  @identity_map_instance = identity_map_instance.put(key_for(object), object)
  object
end