[Seaside] components via meta-data?
itsme213
itsme213 at hotmail.com
Sat Jul 1 21:00:55 UTC 2006
Apologies for this long post from a newbie. I was trying out Adrian
Lienhard's Mewa with Seaside and it seems Mewa has languished. I was curious
what knowledgable Seasiders thought of the following.
QUESTION: Can we build very smart Seaside components automatically from
meta-data of the domain objects, and still require a very small amount of
meta-data for customized components?
What's different about these "Components"?
=========================================
Nothing changes on the interface between the Component and sessions,
browsers, etc. However, each component in that tree is connected to domain
objects via a meta-layer. This meta-layer provides a uniform (structural)
reflective interface to all domain objects, their attribute values, and
their operations including parameters and calling constraints, so that
generic view and editor components can operate through this interface.
What is this meta-layer?
========================
Components in successive levels of the component tree are (STRICTLY)
attached to either
- (meta)objects or
- (meta)attributes of those object, or
- (meta)operations on those objects
A meta-object (in this discussion) is NOT a class; rather, it is a
proxy-like object carrying meta-information for a specific domain object
(instance). (The "meta" terminology comes from Mewa).
A meta-attribute is an object carrying meta-information for the value of a
specific attribute of a specific object.
A meta-operation is an object carrying meta-information for a specific
operation that might be invoked on a specific object.
In combination these three carry all the information needed to construct
components.
The attached pictures from the Mewa paper show the essential idea (but don't
include the meta-attributes and meta-operations).
None of these meta-things need db-level persistance, they might use
session-level persistence. Below is pseudo-Ruby code (sorry, I am not yet
fluent in Smalltalk):
class MetaObject
# mostly acts as a proxy to obj, adding meta-information
has_one :obj, Object
has_many :attributes, MetaAttribute
has_many :operations, MetaOperation
def renderHtmlOn: html
# walk attributes to structure views
# walk operations to structure buttons/anchors/editors/...even wizards
end
end
class MetaAttribute
# a slot value of a domain object i.e. obj + attr + value
# or, a slot + value of an operation on an object (op + param + value)
has_one :attribute, Symbol
has_one :type, Class # or duck-type
has_one :multiplicity, Symbol
# :attribute, :type, :mult should be shared via class level Attribute
# I've just stuffed them here, just easier to understand this way
has_one :owner, Object # domain obj or a MetaOperation (below)
def value
owner.instance_variable_get attribute # or #send...
end
def replace (replacement_obj)
# illustrative only
owner.send "#{attribute.to_s}=", replacement_obj
end
def add (added_obj)
# illustrative; only defined if attr is a collection
owner.send "add_to_#{attribute.to_s}", added_obj
end
end
class MetaOperation
# an operation-to-be-called on an object
#
has_one :operation, Symbol
has_many :params, MetaAttribute
# tracks param name, type, multiplicity, etc.
# Used to populate (d)html accordingly
# including using the smarts below
# :operation and :params could be shared via class level Operation
has_one :owner, Object
has_many :current_values, Hash
# current user-selected param values, hashed by param_symbol
# for populating of parameter candidates e.g. a drop-down list
# may be used via Ajax, including current parameter selection
def candidates_for (param)
owner.candidates_for operation, param, curr_values
end
# for enabling of operations e.g. menu or button enabling
# may be used via Ajax, including current parameter selection
def invocable?
owner.invocable? (operation, current_values)
end
def invoke
owner.send operations, current_values
end
end
Example meta-layer instance
===========================
Assume there is a component tree consisting of nested viewers and editors.
On demand, build metadata about domain objects that these viewers and
editors connect to, including the attributes and relations of these domain
objects. Make that metadata structure uniformly as follows:
m_obj
m_attr
m_obj
m_obj
m_attr...
m_op1
m_attr...
m_attr...
m_op2
So if I have objects
joe=Person.new
joe.name = "Joe"
home=House.new(:address=>"123 hometown")
joe.add_house home
vacation_home = House.new
joe.add_house vacation_home
room1 = Room.new
room2 = Room.new
home.add_room room1
home.add_room room2
bob=Person.new
joe.add_friend bob
Then a view or editor *on joe* will create and use this metadata structure:
joe -- meta-object
joe#name -- meta-attribute
joe#name= -- meta-operation
joe#houses -- meta-attribute
home -- meta-object
home#address -- meta-attribute
"123 hometown" -- metaobject, optimized away
home#rooms -- meta-attribute
room1 -- meta-object
room2
vacation_home
joe#friends
bob
Example Component Tree
======================
CLAIM: The component tree should exactly parallel this metaobject and
metaattribute structure (by default). So here are the components in that
tree, and the (meta)-things they connect to:
person_viewer --> joe
#houses_viewer --> joe#houses
house_viewer --> home
#address_viewer --> home#address
address_viewer --> "123 hometown"
#rooms_viewer --> home#rooms
room_viewer --> room1
room_editor --> room2#modify
new_size --> room2#modify.new_size
house_viewer --> vacation_home
#friends_viewer --> joe#friends
person_viewer --> bob
As always, some of the elements in the above tree might change dynamically
with Ajax e.g. a viewer might be replaced by an editor when the little
"edit" link is clicked; but the editor would still be attached to the same
meta-instance.
I believe all the components in this tree could be generic by default, all
the meta-objects constructed automatically given a few meta-data hints.
Not sure how Seaside deals with Ajax right now, but we might need some event
machinery between the tree and domain objects so an (Ajax) operation that
replaced one component might also update other parts of related components
in the tree. Ajax-induced updates would propagate up to the tree root
collecting component updates, before going back to the client.
CSS
===
Seaside components can be reused wonderfully, including embedding them in
others. But if CSS is only provided at the page level, would it make sense
for a component to (somehow) compose the CSS of its parts? We could
eliminate some CSS warts while at it
http://lunchroom.lunchboxsoftware.com/articles/2005/08/19/rcss-anyone, and
with a few restrictions still retain client caching etc. Far less important
than the component ideas above, though.
Thoughts? Am I talking nonsense?
Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mewa.png
Type: image/png
Size: 7139 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/seaside/attachments/20060701/c38a50a7/mewa-0001.png
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mewa2.png
Type: image/png
Size: 11481 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/seaside/attachments/20060701/c38a50a7/mewa2-0001.png
More information about the Seaside
mailing list