Skip to content

Commit

Permalink
fix: Ensure derives are generated in FileBone inside a RecordBone
Browse files Browse the repository at this point in the history
… too (#1370)

The `postSavedHandler` of the `FileBone` inside a `RelSkel` (which is
used as `UsingSkel` for a `RecordBone`) was never called. Therefore
`ensureDerived` was never called for this bone too and derives are never
generated.

Fixes #817
  • Loading branch information
sveneberth authored Jan 19, 2025
1 parent 84d80ba commit a090e5b
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/viur/core/bones/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1093,13 +1093,13 @@ def performMagic(self, valuesCache: dict, name: str, isAdd: bool):
"""
pass # We do nothing by default

def postSavedHandler(self, skel: 'viur.core.skeleton.SkeletonInstance', boneName: str, key: str):
def postSavedHandler(self, skel: "SkeletonInstance", boneName: str, key: db.Key | None) -> None:
"""
Can be overridden to perform further actions after the main entity has been written.
:param boneName: Name of this bone
:param skel: The skeleton this bone belongs to
:param key: The (new?) Database Key we've written to
:param key: The (new?) Database Key we've written to. In case of a RelSkel the key is None.
"""
pass

Expand Down
10 changes: 9 additions & 1 deletion src/viur/core/bones/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,20 @@ def postSavedHandler(self, skel, boneName, key):
the derived files directly.
"""
super().postSavedHandler(skel, boneName, key)
from viur.core.skeleton import RelSkel, Skeleton

if issubclass(skel.skeletonCls, Skeleton):
prefix = f"{skel.kindName}_{boneName}"
elif issubclass(skel.skeletonCls, RelSkel): # RelSkel is just a container and has no kindname
prefix = f"{skel.skeletonCls.__name__}_{boneName}"
else:
raise NotImplementedError(f"Cannot handle {skel.skeletonCls=}")

def handleDerives(values):
if isinstance(values, dict):
values = [values]
for val in (values or ()): # Ensure derives getting build for each file referenced in this relation
ensureDerived(val["dest"]["key"], f"{skel.kindName}_{boneName}", self.derive)
ensureDerived(val["dest"]["key"], prefix, self.derive)

values = skel[boneName]
if self.derive and values:
Expand Down
16 changes: 16 additions & 0 deletions src/viur/core/bones/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,22 @@ def singleValueFromClient(self, value, skel, bone_name, client_data):
)
return usingSkel, usingSkel.errors

def postSavedHandler(self, skel, boneName, key) -> None:
super().postSavedHandler(skel, boneName, key)
for idx, lang, value in self.iter_bone_value(skel, boneName):
using = self.using()
using.unserialize(value)
for bone_name, bone in using.items():
bone.postSavedHandler(using, bone_name, None)

def refresh(self, skel, boneName) -> None:
super().refresh(skel, boneName)
for idx, lang, value in self.iter_bone_value(skel, boneName):
using = self.using()
using.unserialize(value)
for bone_name, bone in using.items():
bone.refresh(using, bone_name)

def getSearchTags(self, skel: 'viur.core.skeleton.SkeletonInstance', name: str) -> set[str]:
"""
Collects search tags from the 'using' skeleton instance for the given bone.
Expand Down
4 changes: 3 additions & 1 deletion src/viur/core/bones/relational.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ def _get_single_destinct_hash(self, value):

return tuple(parts)

def postSavedHandler(self, skel: "SkeletonInstance", boneName: str, key: db.Key) -> None:
def postSavedHandler(self, skel, boneName, key) -> None:
"""
Handle relational updates after a skeleton is saved.
Expand All @@ -502,6 +502,8 @@ def postSavedHandler(self, skel: "SkeletonInstance", boneName: str, key: db.Key)
:param boneName: The name of the relational bone.
:param key: The key of the saved skeleton instance.
"""
if key is None: # RelSkel container (e.g. RecordBone) has no key, it's covered by it's parent
return
if not skel[boneName]:
values = []
elif self.multiple and self.languages:
Expand Down

0 comments on commit a090e5b

Please sign in to comment.