1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
11 \paperpackage widemarginsa4
15 \use_numerical_citations 0
16 \paperorientation portrait
19 \paragraph_separation indent
21 \quotes_language english
25 \paperpagestyle default
39 \begin_inset Quotes eld
43 \begin_inset Quotes erd
53 is a very useful module that works on top of the
57 framework to do rapid developing of complex data-driven web appilcations
72 was founded and developed and continues to be developed and mantained by
83 The conventions used in this manual are:
86 Dode is shown as a monospace font.
87 When it is expected that the user is working in an interactive environment
88 what the user should type appears as bold, while the computer result appears
89 non-bold, for example:
102 Names of people or products are show as small caps, like
117 require further revision.
122 ToDo: Add more conventions as they are needed, possible classes of text:
123 names of concepts, name of programming entities, like variables, functions,
124 etc (which are embedded in text, should they be shown monospaced ?).
132 Protocol A Protocol for introspection on relational objects.
136 Presentations A Mewa-like
142 http://www.adrian-lienhard.ch/files/mewa.pdf
145 layer for UncommonWeb
151 http://common-lisp.net/project/ucw/
160 First we start with the data model.
161 The Meta Model Protocol (MMP) is used to provide information on the data
162 objects and how they relate to one another.
163 Its is currently implemented as a layer over CLSQL
172 , although support is planned for other backends (
183 The MMP shares its definition syntax with
189 's Object Oriented Data Definition Language (OODDL)
195 http://clsql.b9.com/manual/ref-ooddl.html
201 Shouldn't this footnote be a bibliographical entry ? or something like that
209 The macro to define view-classes is named DEF-VIEW-CLASS/META, and takes
210 the same arguments as DEF-VIEW-CLASS from CLSQL.
211 For the purposes of this simple example, we will only need two functions
212 from the MMP beyond what CLSQL provides : LIST-SLOTS and LIST-SLOT-TYPES[5].
215 We'll define a simple class to hold a user.
220 (def-view-class/meta user ()
225 ((userid :initarg :userid :accessor userid :type integer :db-kind :key)
230 (username :initarg :username :accessor username :type string :db-kind
236 (password :initarg :password :accessor password :type string :db-kind
240 and now we create a user:
245 (defparameter user (make-instance 'user :userid 1
255 :password "p@ssw0rd"))
258 We can see the slots of users running:
263 (lisp-on-lines::list-slots user)
266 (USERID USERNAME PASSWORD)
274 (lisp-on-lines::list-slot-types user)
277 ((USERID INTEGER) (USERNAME STRING) (PASSWORD STRING))
280 To see the default attributes of a class
281 \begin_inset Marginal
286 Is this correct ? Drew, please, check.
294 (lisp-on-lines::default-attributes user)
297 ((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
300 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
303 (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD))
306 To set the attributes of a class to the default values we use:
311 (lisp-on-lines::set-default-attributes user)
314 ((USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
317 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
320 (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD))
323 which takes an object of the class we are working with.
324 This is going to be change so we can do this action directly on the class.
325 It is on the TODO file.
333 (lisp-on-lines::find-class-attributes user)
336 (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)
339 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
342 (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
348 note that the mewa functions (find-attribute, set-attribute etc) can take
349 either an instance, or a class-name as a symbol:
354 (lisp-on-lines::find-class-attributes 'user)
357 (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)
360 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
363 (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
371 (lisp-on-lines::find-class-attributes (make-instance 'user))
374 (USER (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)
377 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
380 (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
386 Using that information, we have enough to create an interface to the object.
391 includes a powerful presentation system
397 To see this system in action, we strongly recomend to study the presentations
398 example which comes with
403 Reading components/presentations.lisp can help understand a lot about how
404 presentations are built.
407 , but it is not dynamic enough for some of the most advanced applications.
408 Mewa defines an approach to presentations that solves that problem, but
409 the paper is written from a
414 A mixture of the two , Mewa Presentations(MP), is described here.
426 An attribute is essentially a named version of the DEFPRESENTATION slot-like
427 arguments, for example in :
432 (defpresentation person-editor (object-presentation)
437 ((string :label "First Name" :slot-name 'first-name :max-length 30)))
440 the (string :label "First Name" ...) form is an attribute definiton.
441 Attributes are accessed through FIND-ATTIRIBUTES, and are composed at run
446 's presentation system is done at compile time) to display the object.
447 This allows a very flexible system of displaying objects which is reminiscent
462 discovered this, rather than invent or design it, so there are some rough
463 edges, but its a good start.
469 Its much easier to show this than to tell.
470 Lets present our user class.
475 , you'd define a presentation as such :
480 (defpresentation user-presentation (object-presentation)
483 ((INTEGER :LABEL "USERID" :SLOT-NAME USERID)
486 (STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
489 (STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)))
492 which could be presented using PRESENT-OBJECT :
497 (present-object user :using 'user-presentation)
500 The equivalent approach using mewa presentations is actually longer and
501 more verbose(!) but it serves to demonstrate how the MP system works.
504 Mewa Presentations adds a set of attributes to a class, keyed off the class
506 Attributes are inherited, so if you define an attribute on T, you can use
510 MP stores named attributes keyed on a class name.
511 To achieve the same functionality as the above using mp would look like
517 (setf (lisp-on-lines::find-attribute 'user :viewer)
518 \begin_inset Marginal
523 Isn't this too imperative (in contrast to functional, lispy).
531 '(lisp-on-lines::mewa-object-presentation
536 :attributes (userid username password)
541 :global-properties (:editablep nil)))
544 (:VIEWER MEWA-OBJECT-PRESENTATION
550 (USERID USERNAME PASSWORD)
561 (setf (lisp-on-lines::find-attribute 'user 'userid)
562 \begin_inset Marginal
567 Are this setfs to 'userid, 'username and 'password needed ? I (Pupeno) inspected
568 they contents at of this moment and they seem to already contain what they
577 '(integer :label "userid" :slot-name userid))
580 (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
585 (setf (lisp-on-lines::find-attribute 'user 'username)
590 '(STRING :LABEL "USERNAME" :SLOT-NAME USERNAME))
593 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
598 (setf (lisp-on-lines::find-attribute 'user 'password)
603 '(STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD))
606 (PASSWORD STRING :LABEL "USERNAME" :SLOT-NAME PASSWORD)
611 (lisp-on-lines::find-class-attributes 'user)
617 (:VIEWER MEWA-OBJECT-PRESENTATION
623 (USERID USERNAME PASSWORD)
632 (PASSWORD STRING :LABEL "PASSWORD" :SLOT-NAME PASSWORD)
635 (USERNAME STRING :LABEL "USERNAME" :SLOT-NAME USERNAME)
638 (USERID INTEGER :LABEL "USERID" :SLOT-NAME USERID)
644 this is all turned into a
648 presentation at runtime using MAKE-PRESENTATION, for example, the following
649 code should be enough to show what's built so far attached to the examples
655 (defcomponent lol-example (window-component)
665 (defmethod render-on ((res response) (lol-example lol-example))
675 (<ucw:render-component :component (lisp-on-lines::make-presentation
676 user :type :viewer)))
681 (defentry-point "lol.ucw" (:application *example-application*) ()
686 (call 'products-presentation))
689 As you'll see, nothing is exported from the LISP-ON-LINES package.
690 If you wish to use LOL in your own package (or in UCW-USER or whatever),
691 you simply need to use the MEWA and META-MODEL packages.
694 SET-ATTRIBUTE can be used in place of (setf (find-attribute)) when you want
695 to "inherit" the properties of an existing attribute definition :
698 LISP-ON-LINES> (set-attribute 'user 'password '(string :label "password:
699 (must be at leat 8 chars)"))
708 "password: (must be at leat 8 chars)"
717 Now we want to create a presentation with which to edit the username.
718 we will use the existing attributes on a subclass of mewa-object-presetation
722 LISP-ON-LINES> (defcomponent user-editor (mewa-object-presentation)
731 :attributes '((username :label "Enter your New Username") password)
734 :global-properties '(:editablep t)))
740 LISP-ON-LINES> (setf (find-attribute 'user :editor) '(user-editor))
743 (:EDITOR USER-EDITOR)
749 which we then can display below our earlier example :
752 (defmethod render-on ((res response) (e presentations-index))
758 As you'll see, nothing is exported from the LISP-ON-LINES package.
762 if you wish to use LOL in your own package (or in UCW-USER or whatever),
765 you simply need to use the MEWA and META-MODEL packages"
768 (<ucw:render-component :component (lisp-on-lines::make-presentation lisp-on-line
769 s::user :type :viewer))
772 (<ucw:render-component :component (lisp-on-lines::make-presentation lisp-on-line
773 s::user :type :editor)))
776 that should give you some idea on how it works ..
777 ask me when you get confused :)
783 This is Pupeno's view of how to do rapid developing of a database-driven
785 It currently is going to assume a very specific case but latter it may
789 We first start with a
793 connection of CLSQL which is set up with one line:
798 (clsql:connect '("localhost" "geo" "geo" "geogeo"))
801 which connect us to the server on
810 \begin_inset Quotes eld
814 \begin_inset Quotes erd
818 \begin_inset Quotes eld
822 \begin_inset Quotes erd
825 (this is not a smart way to generate password, don't do this).
826 To have a nice SQL environment, we also want:
831 (clsql:locally-enable-sql-reader-syntax)
836 (setf clsql:*default-caching* nil)
839 Actually, it is more than a nice environmnet, without those lines the rest
840 of the code won't work.
847 database, there's a table called
851 which has the following structure:
856 CREATE TABLE product (
881 cost double precision,
886 CONSTRAINT product_cost_check CHECK ((cost > (0)::double precision))
896 ALTER TABLE ONLY product ADD CONSTRAINT product_name_key UNIQUE (name);
901 ALTER TABLE ONLY product ADD CONSTRAINT product_pkey PRIMARY KEY (id);
906 ToDo: express the table structure in a better way.
909 Now we'll create the class that represents a product, mirroring the database
915 (lisp-on-lines::def-view-class/table "product")
918 and then we generate the default attributes (from
922 's slots) and assign it to
931 (lisp-on-lines::set-default-attributes (make-instance 'product))
932 \begin_inset Marginal
937 set-default-attributes is marked to be renamed to set-generated-attributes.
943 As you can see, we instantiate
949 set-default-attributes
951 , because it expects an object instead of a class.
952 We don't need the object anymore, so we don't save any reference to it.
953 In the future we might have a
955 set-default-attributes
957 that can use a class directly.
958 Now we set a the attribute
964 mewa-object-presentation
966 exposing the attributes we like the user to work with:
971 (setf (lisp-on-lines::find-attribute (make-instance 'product) :viewer)
976 '(lisp-on-lines::mewa-object-presentation
981 :attributes (name details description cost)
986 :global-properties (:editablep nil)))
989 The last parameter shows that it is not editable, which makes sense for