Version 16 (modified by 12 years ago) ( diff ) | ,
---|
Table of Contents
S3XRC | S3 Model Extensions | Super-Entities
S3 Super-Entities
Introduction
Sometimes it is useful to share the same component across multiple resources. To achieve this in a generic way, S3XRC supports a special type of link tables - so-called Super-Entities:
Instead of having several foreign keys for different primary resources, the shared component contains only one foreign key to the link table, the so-called super-key.
The primary resource (=instance table) contains the same super-key field as the component, thus the forward join of resource-to-component can be established as a natural join, i.e. without accessing the link table.
For the (seldom needed) backward join component-to-resource, the link table must be involved because it contains the table name of the primary resource in the field {{instance_type}}.
Disadvantage of the link table method is that the link table has to be updated whenever a primary resource record is created, updated or deleted - which generates some (minimal) extra load on write, however, it is recommended to not use super-entities for resources where the extra load on write can give a serious performance problem (e.g. messages), or at least to keep the super-entity table lean and free of extra references.
- code examples to follow...
API
To simplify the handling of super-entities in the model, S3Model provides a unified API for super-entities:
Defining a Super-Entity
To define a super-entity, you can use the super_entity()
function:
table = super_entity(tablename, "sit_id", situation_types, Field("datetime", "datetime"), # shared field location_id()) # shared field
You can define so-called shared fields in the super-entity, which are mirrored from the respective resource record. This allows to easily access these data from the component without the need to involve the primay instance table in the backward-join:
In case the names of the shared fields in your instance table differ from those of the super-entity, you can define a field mapping:
Defining an Instance of a Super-Entity
To make a table an instance of a super-entity, you can use s3xrc.model.configure()
:
s3xrc.model.configure(table, super_entity = db.sit_situation)
By default, all fields that the table and the super-entity have in common will be mirrored in the super-entity ("shared fields"). You can override this by specifying a list of fields to be mirrored by the super-entity.
s3xrc.model.configure(table, super_entity = db.sit_situation, sit_situation_fields = ["datetime"])
In case your table uses different names for the shared fields, you can use a dict instead to specify a mapping:
s3xrc.model.configure(table, super_entity = db.sit_situation, sit_situation_fields = dict(datetime="timestmp", location_id="location_id"))
Linking to a Super-Entity
Both, instance tables as well as shared components need to be linked to the super-entity. This can be done by inserting a super-key field into the instance/component table which must have the same name as the primary key of the super-entity. You can use the super_link()
function as a DRY method for this:
resourcename = "presence" tablename = "%s_%s" % (prefix, resourcename) table = db.define_table(tablename, super_link(db.pr_pentity), # pe_id super_link(db.sit_situation), # sit_id ...)
Note: super_link
generates a Field
instance - if you just need the name of the super-key field, you can use:
sk = super_key(db.pr_pentity) # returns the string "pe_id"
Updating a Super-Entity
If you use s3_rest_controller() for CRUD, it will automatically create, update and delete super-entities as necessary.
Otherwise, or if you manipulate records outside s3_rest_controller, you have to update all super-entities which an instance table implements whenever you create, update or delete a record in that table.
To do this, you can use:
s3db.update_super(table, record)
where table
is the instance table and record
the newly created/updated record.
In case you're going to delete a record from an instance table, you may use:
s3db.delete_super(table, record)
before you delete the record, where table
is the instance table and record
the record to be deleted.
Attachments (1)
-
super_entity.png
(38.8 KB
) - added by 11 years ago.
Super-Entity Relationships
Download all attachments as: .zip