Skip to content

Commit

Permalink
fixed issue where the lazy loading of an attribute would erase change…
Browse files Browse the repository at this point in the history
…s to the upper layers of an entity
  • Loading branch information
joamag committed Nov 20, 2015
1 parent 36e85d1 commit b0adfa8
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
22 changes: 16 additions & 6 deletions data/src/entity_manager/structures.py
Expand Up @@ -4620,7 +4620,7 @@ def _load_lazy(self, name):
# attribute is not going to be "lazy loaded" again)
return attribute

def _load_lazy_attr(self, name):
def _load_lazy_attr(self, name, force = False):
"""
Loads a lazy loaded base attribute, this will be used in
entities that have been loaded using polymorphism and for
Expand All @@ -4629,12 +4629,20 @@ def _load_lazy_attr(self, name):
Loading the attribute will trigger a concrete loading of
the entity values and all of them will be updated.
An optional flag may be used to force the setting of already
defined/set attributes (from the upper layers in hierarchy).
This method accesses the data source so it's considered
to be an "expensive" operation.
@type name: String
@param name: The name of the attribute to be used as reference
in the loading of the concrete class (lazy load).
@type force: bool
@param force: If the setting of attributes should be forced
meaning that attributes that are already set in the entity
may be overriden by new values from data source, this is
valid for the upper layers of the class hierarchy.
@rtype: Object
@return: The value for the attribute that triggered the concrete
load of the class (lazy load).
Expand Down Expand Up @@ -4682,11 +4690,13 @@ def _load_lazy_attr(self, name):
# in case the current name in iteration is
# not present in the (new) entity no need to
# retrieve it and set it in the entity
if not _entity.has_value(name):
# continues the loop the name is not present
# in the (new) entity it's impossible to update
# it in the entity
continue
if not _entity.has_value(name): continue

# in case the value is already set in the base
# no duplicate setting should occur (would possibly
# revert changed to entity), note that in case the
# force flag is set the value is set the same way
if self.has_value(name) and not force: continue

# retrieves the value for the current
# name in the (new) entity and sets it in
Expand Down
54 changes: 54 additions & 0 deletions data/src/entity_manager/test.py
Expand Up @@ -1306,6 +1306,60 @@ def test_validate_relation(self):
valid_relation = self.entity_manager.validate_relation(person, "parent")
self.assertEqual(valid_relation, True)

def test_lazy_attribute(self):
# creates the required entity classes in the data source
self.entity_manager.create(mocks.Person)
self.entity_manager.create(mocks.Dog)

# creates a person entity with it's default attributes and
# saves it into the data source
person = mocks.Person()
person.object_id = 1
person.status = 1
person.name = "name_person"
self.entity_manager.save(person)

# verifies that the data remains unchanged after
# the saving (persistence)
self.assertEqual(person.object_id, 1)
self.assertEqual(person.status, 1)
self.assertEqual(person.name, "name_person")

# retrieves the person using a polymorphic query so
# that only the root entity fields are populated and
# then verifies that the result is valid/set
saved_person = self.entity_manager.get(mocks.RootEntity, 1)
self.assertNotEqual(saved_person, None)

# detaches the person from the data source and verifies
# that the root entity level fields are set but the person
# level ones are not (polymorphic query)
saved_person.detach()
self.assertEqual(saved_person.object_id, 1)
self.assertEqual(saved_person.status, 1)
self.assertEqual(saved_person.name, None)

# attaches the person back to the data source (enabling lazy
# attribute evaluation) and verifies that the person level
# attributes are now accessible and that the top level ones
# (root entity) remain the same after lazy attribute evaluation
saved_person.attach()
saved_person.status = 2
self.assertEqual(saved_person.name, "name_person")
self.assertEqual(saved_person.status, 2)

# runs the original test one more time be using the root entity
# level of retrieval and then forces the loading of the lazy
# attribute (should populate also upper layers) and verifies
# that the status value is returned to the original value because
# of the forced loading of the upper layer attributes
saved_person = self.entity_manager.get(mocks.RootEntity, 1)
self.assertNotEqual(saved_person, None)
saved_person.status = 2
saved_person._load_lazy_attr("name", force = True)
self.assertEqual(saved_person.name, "name_person")
self.assertEqual(saved_person.status, 1)

def test_abstract(self):
# creates the required entity classes in the data source
self.entity_manager.create(mocks.RootEntityAbstract)
Expand Down

0 comments on commit b0adfa8

Please sign in to comment.