Ok, the learning curve is steep and my idea on what I'm doing is less then basic. However here we go, this is the code (defmodel foobar (model) ((val-1 :cell t :accessor val-1 :initform "" :initarg :val-1) (val-3 :cell t :accessor val-3 :initarg :val-3 :initform (c-in "Initialize"))))
(def-c-output val-1 () (format t "val-1 is ~a, val-3 is ~a~%" (val-1 self) (val-3 self)))
(defun foo-test () (cell-reset) (let ((obj (make-instance 'foobar :val-1 (c? (if (val-3 self) (setf (val-1 self) (val-3 self)) "val-3 not set")))))
(setf (val-3 obj) "another val-3") (setf (val-3 obj) "yet another val for val-3")) (values))
In this utterly primitive example the val3 slot "steers" the slot-1 slot. Translated to my need to sync db-view and "user-view", I assume I have to write model with the two objects in it do the initialization from one side (e.g populating from the database), I probably also have to write a function to feed to the :unchanged (or so slot), if that yiels true, then the view and database data are in sync if not I have to update the database data from the view.
Is this the way to go, or am I overlooking something (I guess I do, just cells is too new for me....)
Regards Friedrich
Friedrich Dominicus wrote:
Ok, the learning curve is steep and my idea on what I'm doing is less then basic. However here we go, this is the code (defmodel foobar (model) ((val-1 :cell t :accessor val-1 :initform "" :initarg :val-1) (val-3 :cell t :accessor val-3 :initarg :val-3 :initform (c-in "Initialize"))))
(def-c-output val-1 () (format t "val-1 is ~a, val-3 is ~a~%" (val-1 self) (val-3 self)))
(defun foo-test () (cell-reset) (let ((obj (make-instance 'foobar :val-1 (c? (if (val-3 self) (setf (val-1 self) (val-3 self)) "val-3 not set")))))
Just use: (c? (or (val-3 self) "val-3 not set")) There is also a handy macro for cells of oneself: (c? (or (^val-3) "val-3 not set"))
The Cell engine populates the slot at the right time (long story, but the timing is delicate) initially and as val-3 changes.
Note that there is a runtime error generated when you attempt to SETF a ruled Cell, as your rule is doing (SETFing itself!), but I think at some point recently I changed things so the error is enforced only if *c-debug* is non-nil. Recall is fuzzy on why I did that.
Anyway, the idea is to have a declarative approach in which one supplies a rule for a slot and then the Cells engine takes over and keeps things in synch.
(setf (val-3 obj) "another val-3") (setf (val-3 obj) "yet another val for val-3")) (values))
In this utterly primitive example the val3 slot "steers" the slot-1 slot.
Think of it as slot-1 "following" val3. Note that there is no val-3 logic to change val-1. val-3 does not know anything about val-1. But val-1 has a rule that uses val-3. val-1 could have also used any number of other vals. This is important, and really constitutes the paradigm shift away from a procedural, manual SETFing of other values to a declarative "just worry about the rule for one value at a time".
Translated to my need to sync db-view and "user-view", I assume I have to write model with the two objects in it do the initialization from one side (e.g populating from the database), I probably also have to write a function to feed to the :unchanged (or so slot), if that yiels true, then the view and database data are in sync if not I have to update the database data from the view.
I am afraid you lost me there. "two objects"? "one side"? Maybe once you have absorbed the above correction and otherwise gottten a better understanding of the declarative model we can try some actual unambiguous code using a simple text file as a database, with each line constituting a row in an SQL table. I guess the principle will be the same, and this would be a rather extreme but illuminating Use Case to share with others.
Note that the original code I described was proprietary, so we would develop new code from scratch (and I cannot share the old code).
thanks for your comments. I'll spend some time of the day to implement the idea I have on my mind and will post it then. I'm sure someone using cells will find it "obscurred" programmed and will know a better way on how to approache the problem. I probably will drop the view stuff for now and just use formatted output. But I will use a database as "backend". I hope it won't be all too bad.
Regards Friedrich
I spend nearly the whole weekend on gettign a bit further. My code is not this:
(in-package :qss.web)
;; (use-package :cells) (eval-when (:compile-toplevel :execute) (defparameter *example-app* (make-instance 'cookie-session-application :url-prefix "/ucw/examples/" :tal-generator (make-instance 'yaclml:file-system-generator :cachep t :root-directories (list *ucw-tal-root*)) :www-roots (list *ucw-tal-root*))))
;; (register-application *default-server* *example-app*)
(cells:defmodel controller (cells:model) ((view-obj :accessor view-obj :cell t :initarg :view-obj :initform (cells:c-in nil)) (db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (update-from-view cells:self)))))
(clsql:def-view-class example-app () ((id :type integer :db-kind :key :accessor id :initarg :id) (tag :type string :accessor tag :initarg :tag) (description :type string :accessor description :initarg :description) (some-fk :type integer :accessor some-fk :initarg :some-fk) (some-objects :accessor some-objects :db-kind :join :db-info (:join-class other-class :retrieval :deferred :set nil :foreign-key example-id :home-key id))))
(clsql:def-view-class other-class () ((example-id :type integer :accessor example-id :initarg :example-id) (val :type string :accessor val :initarg :val)))
;; (clsql:create-view-from-class 'simple-db)
(defmethod update-from-view ((controller controller)) (with-accessors ((db-obj db-obj) (view-obj view-obj)) controller (inspect controller) ;; view should steer the database object usually (let ((other (some-objects db-obj))) (setf (tag db-obj) (read-client-value (tag view-obj)) (description db-obj) (read-client-value (description view-obj)) (val other) (read-client-value (other view-obj))) (clsql:update-records-from-instance db-obj)) (values)))
(defun populate-db () (let ((other (make-instance 'other-class :example-id 1 :val "some text"))) (clsql:update-records-from-instance other) (let ((mobj (make-instance 'example-app :id 1 :tag "some tag" :description "this is the description" :some-fk 1))) (setf (some-objects mobj) other) (clsql:update-records-from-instance mobj))))
;; (clsql:drop-view-from-class 'other-class) ;; (clsql:drop-view-from-class 'example-app)
;; ;; (clsql:create-view-from-class 'example-app) ;; (clsql:create-view-from-class 'other-class) ;; (populate-db)
(defcomponent example-view (simple-window-component) ((db-obj :initarg :db-obj :reader db-obj) (tag :accessor tag :initarg :tag :component (text-field :size 20 :maxlength 20)) (description :type string :accessor description :initarg :description :component (text-area-field :width 20 :height 10)) (other :accessor other :component (text-field :size 20 :maxlength 20))))
(defun setup-db () ;; open a connectoin to DB (clsql:enable-sql-reader-syntax))
;; (setup-db)
(defcomponent text (simple-window-component) ((view-text :initarg :view-text :reader view-text) (db-text :initarg :db-text :reader db-text)))
(defmethod render-on ((res response) (text text)) (inspect text) (<:p "view data: " (<:as-is (view-text text))) (<:p "database data: " (<:as-is (db-text text))))
(defmethod initialize-vfd ((view example-view) (controller controller)) (let ((db-obj (db-obj controller)))
(setf (some-objects db-obj) (car (clsql:select 'other-class :where [= [example-id] 1] :flatp t))) ;; (inspect db-obj) (clsql:update-records-from-instance db-obj) (setf (ucw::client-value (tag view)) (tag db-obj) (ucw::client-value (description view)) (description db-obj ) (ucw::client-value (other view )) (val (some-objects db-obj )) (view-obj controller) view) (inspect controller) (values)))
(defmethod render-on ((res response) (view example-view)) ;; this is not perfect but for the example it should be enough ;; (inspect view) (let ((controller (make-instance 'controller))) (setf (db-obj controller) (slot-value view 'db-obj)) (initialize-vfd view controller) (inspect controller) (<ucw:form :action (save-and-show-data view controller) (<:table (<:tr (<:td "tag") (<:td "Description") (<:td "Other text")) (<:tr (<:td (render-on res (tag view))) (<:td (render-on res (description view))) (<:td (render-on res (other view))))) (<:p (<:input :type "submit" :value "Accept")))))
(defaction save-and-show-data ((view example-view) (controller controller)) (call 'text :view-text (format nil "tag = ~a, descripton = ~a, other-text = ~a~%" (read-client-value (tag (view-obj controller))) (read-client-value (description (view-obj controller))) (read-client-value (other (view-obj controller)))) :db-text (format nil "tag = ~a, descripton = ~a, other-text = ~a~%" (tag (db-obj controller)) (description (db-obj controller)) (val (some-objects (db-obj controller))))))
(defun init-cells () (clsql:enable-sql-reader-syntax) (cells:cell-reset))
(defentry-point "index.ucw" (:application *example-app*) () (init-cells) (call 'example-view :db-obj (car (clsql:select 'example-app :where [= [id] 1] :flatp t :refresh t)))
my problem update-from-view is not called I was thinking that (db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (update-from-view cells:self)))))
is reponsible for it. But of course I'm set'fing the db-obj slot also, out come is that 1) the view is initialized from the db-view 2) that the db-view won't get changed.
I'm sure it could be done but I don't know how, could someone give me a hand please?
Regards Friedrich
I got it (probably ;-), would someone mind to comment on it?
(in-package :qss.web)
;; (use-package :cells) (eval-when (:compile-toplevel :execute) (defparameter *example-app* (make-instance 'cookie-session-application :url-prefix "/ucw/examples/" :tal-generator (make-instance 'yaclml:file-system-generator :cachep t :root-directories (list *ucw-tal-root*)) :www-roots (list *ucw-tal-root*))))
;; (register-application *default-server* *example-app*)
(cells:defmodel controller (cells:model) ((view-obj :accessor view-obj :cell t :initarg :view-obj :initform (cells:c-in nil)) (db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (update-from-view cells:self)))))
(clsql:def-view-class example-app () ((id :type integer :db-kind :key :accessor id :initarg :id) (tag :type string :accessor tag :initarg :tag) (description :type string :accessor description :initarg :description) (some-fk :type integer :accessor some-fk :initarg :some-fk) (some-objects :accessor some-objects :db-kind :join :db-info (:join-class other-class :retrieval :deferred :set nil :foreign-key example-id :home-key id))))
(clsql:def-view-class other-class () ((example-id :type integer :accessor example-id :initarg :example-id) (val :type string :accessor val :initarg :val)))
;; (clsql:create-view-from-class 'simple-db)
(defmethod update-from-view ((controller controller)) (print "in update-from-view" *error-output*)
(unless (slot-value controller 'db-obj) (print "in unless " *error-output*) ;; (inspect (db-obj (view-obj controller))) (setf (slot-value controller 'db-obj) (db-obj (view-obj controller))))
;; (inspect controller) ;; view should steer the database object usually (let* ((db-obj (slot-value controller 'db-obj)) (view (view-obj controller)) (other (some-objects db-obj))) (setf (tag db-obj) (read-client-value (tag view)) (description db-obj) (read-client-value (description view)) (val other) (read-client-value (other view)))
(clsql:update-records-from-instance db-obj) (print "in update-from-view before inspect" *error-output*) (inspect controller) ;; (setf (slot-value controller 'db-obj) db-obj)) (slot-value controller 'db-obj)))
(defun populate-db () (let ((other (make-instance 'other-class :example-id 1 :val "some text"))) (clsql:update-records-from-instance other) (let ((mobj (make-instance 'example-app :id 1 :tag "some tag" :description "this is the description" :some-fk 1))) (setf (some-objects mobj) other) (clsql:update-records-from-instance mobj))))
;; (clsql:drop-view-from-class 'other-class) ;; (clsql:drop-view-from-class 'example-app)
;; ;; (clsql:create-view-from-class 'example-app) ;; (clsql:create-view-from-class 'other-class) ;; (populate-db)
(defcomponent example-view (simple-window-component) ((db-obj :initarg :db-obj :reader db-obj) (tag :accessor tag :initarg :tag :component (text-field :size 20 :maxlength 20)) (description :type string :accessor description :initarg :description :component (text-area-field :width 20 :height 10)) (other :accessor other :component (text-field :size 20 :maxlength 20))))
(defun setup-db ()
(clsql:enable-sql-reader-syntax))
;; (setup-db)
(defcomponent text (simple-window-component) ((view-text :initarg :view-text :reader view-text) (db-text :initarg :db-text :reader db-text)))
(defmethod render-on ((res response) (text text)) (inspect text) (<:p "view data: " (<:as-is (view-text text))) (<:p "database data: " (<:as-is (db-text text))))
(defmethod init-view ((view example-view)) (let ((db-obj (db-obj view)))
(setf (some-objects db-obj) (car (clsql:select 'other-class :where [= [example-id] 1] :flatp t))) ;; (inspect db-obj) (clsql:update-records-from-instance db-obj) (setf (ucw::client-value (tag view)) (tag db-obj) (ucw::client-value (description view)) (description db-obj ) (ucw::client-value (other view )) (val (some-objects db-obj ))) view))
(defmethod render-on ((res response) (view example-view)) ;; this is not perfect but for the example it should be enough ;; (inspect view) (let ((controller (make-instance 'controller :view-obj (cells:c-in (init-view view))))) ;;(inspect controller)
(<ucw:form :action (save-and-show-data view controller) (<:table (<:tr (<:td "tag") (<:td "Description") (<:td "Other text")) (<:tr (<:td (render-on res (tag view))) (<:td (render-on res (description view))) (<:td (render-on res (other view))))) (<:p (<:input :type "submit" :value "Accept")))))
(defaction save-and-show-data ((view example-view) (controller controller)) (print "in save-and-show-data" *error-output*) (inspect (view-obj controller)) (inspect (db-obj controller))
(call 'text :view-text (format nil "tag = ~a, descripton = ~a, other-text = ~a~%" (read-client-value (tag (view-obj controller))) (read-client-value (description (view-obj controller))) (read-client-value (other (view-obj controller)))) :db-text (format nil "tag = ~a, descripton = ~a, other-text = ~a~%" (tag (db-obj controller)) (description (db-obj controller)) (val (some-objects (db-obj controller))))))
(defun init-cells () (clsql:enable-sql-reader-syntax) (cells:cell-reset))
(defentry-point "other.ucw" (:application *example-app*) () (init-cells) (call 'example-view :db-obj (car (clsql:select 'example-app :where [= [id] 1] :flatp t :refresh t)))
I this a decent use of 'cells and is it cells-ish?
Regards Friedrich
Friedrich Dominicus wrote:
I got it (probably ;-), would someone mind to comment on it?
(in-package :qss.web)
;; (use-package :cells) (eval-when (:compile-toplevel :execute) (defparameter *example-app* (make-instance 'cookie-session-application :url-prefix "/ucw/examples/" :tal-generator (make-instance 'yaclml:file-system-generator :cachep t :root-directories (list *ucw-tal-root*)) :www-roots (list *ucw-tal-root*))))
;; (register-application *default-server* *example-app*)
(cells:defmodel controller (cells:model) ((view-obj :accessor view-obj :cell t :initarg :view-obj :initform (cells:c-in nil))
Later on in the render-on method you instantiate a controller thus:
(make-instance 'controller :view-obj (cells:c-in (init-view view)))
But I do not see any place in the code where you SETF the view-obj slot, so you could just:
(make-instance 'controller :view-obj (init-view view))
C-IN (or C-INPUT) is used only where, in brief, the application will be using SETF to change the value in a sempahoric slot. This is partly because a dataflow model needs to get the original dataflow from somewhere, usually from operating system events or a socket. One can also sometimes get simpler and more efficient code by skipping the declarative aspect (in which a slot like view-obj would have a rule) and just make the slot C-In and then setf that slot from output methods on on other slots. But like I said, that loses the advantages of a declarative approach.
Now in this case I further do not see view-obj getting involved in any cell-mediated dataflow, so I do not think it even needs to be a cell.
(db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (update-from-view cells:self)))))
The opening bit of update-from-view says:
(unless (slot-value self 'db-obj) .....)
Actually, the c? macro offers any existing value as a read macro:
(db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (unless .cache. (update-from-view cells:self))))
...and then do not check for an existing slot-value in u-f-v. Now I do have rare occasion to write code like that, but the interesting thing here is that this rule only runs once, after which it would always return the same value. So there is no dataflow here, where one thing changes (by a SETF of some c-input) and then a bunch of other things get updated automatically in a cascade of rule evaluations.
Maybe I missed something. My first question, does this code work for you? If so, what are the things you see happening that tell you it work? Just give me a simple scenario, such as "I start by reading in this stuff. Then I change this description field, then I exit, and when I look at the DB I see the new description text." Provide the sample code and explain where necessary which code does which step.
A big problem here is that I do not know SQL or cl-sql. For example, is a view just in-memory, or does it refer to a screen view? I know a relational view is just an abstraction built atop physical tables, so maybe you are just talking about that. Well, I do see:
(defcomponent example-view (simple-window-component) ((db-obj :initarg :db-obj :reader db-obj) (tag :accessor tag :initarg :tag :component (text-field :size 20 :maxlength 20)) (description :type string :accessor description :initarg :description :component (text-area-field :width 20 :height 10)) (other :accessor other :component (text-field :size 20 :maxlength 20))))
...and that looks like a GUI view component. Maybe the term is used both ways? if you are updating a description field in a GUI view and then seeing it written back out to the DB, maybe you could lay out for me the code path by which that happens.
I this a decent use of 'cells and is it cells-ish?
Pending a better understanding of the above questions, as I said, I do not see Cells doing very much, and so I would be surprised if they help in this case. But let's see what your feedback is on the above.
kt
Kenny Tilton ktilton@nyc.rr.com writes:
Friedrich Dominicus wrote:
I got it (probably ;-), would someone mind to comment on it?
Thanks for your time. I try to explain my "convulted" way of getting into celsl a bit ;-)
(make-instance 'controller :view-obj (init-view view))
C-IN (or C-INPUT) is used only where, in brief, the application will be using SETF to change the value in a sempahoric slot. This is partly because a dataflow model needs to get the original dataflow from somewhere, usually from operating system events or a socket. One can also sometimes get simpler and more efficient code by skipping the declarative aspect (in which a slot like view-obj would have a rule) and just make the slot C-In and then setf that slot from output methods on on other slots. But like I said, that loses the advantages of a declarative approach.
Well I read the explanations in 01-somwwhat and there I found if you the slot hast to be setf-able you have to use c-in (in short, so I wrote it that way.
Now in this case I further do not see view-obj getting involved in any cell-mediated dataflow, so I do not think it even needs to be a cell.
(db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (update-from-view cells:self)))))
The opening bit of update-from-view says:
(unless (slot-value self 'db-obj) .....)
Actually, the c? macro offers any existing value as a read macro:
(db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (unless .cache. (update-from-view cells:self))))
I've seen the variable but was quite happy to find out the above way ;-)
...and then do not check for an existing slot-value in u-f-v. Now I do have rare occasion to write code like that, but the interesting thing here is that this rule only runs once, after which it would always return the same value. So there is no dataflow here, where one thing changes (by a SETF of some c-input) and then a bunch of other things get updated automatically in a cascade of rule evaluations.
I do not understand that. If the view changes e.g if I use the back button of my browser I'll be back to the old view. The data will get filled from the then actual Database view, if I change something again it will get propagated again from the View to the Backend.
Maybe I missed something. My first question, does this code work for you? If so, what are the things you see happening that tell you it work? Just give me a simple scenario, such as "I start by reading in this stuff. Then I change this description field, then I exit, and when I look at the DB I see the new description text." Provide the sample code and explain where necessary which code does which step.
See above, the back button of the browser makes it possible to return to the view.
A big problem here is that I do not know SQL or cl-sql. For example, is a view just in-memory, or does it refer to a screen view? I know a relational view is just an abstraction built atop physical tables, so maybe you are just talking about that. Well, I do see:
(defcomponent example-view (simple-window-component) ((db-obj :initarg :db-obj :reader db-obj) (tag :accessor tag :initarg :tag :component (text-field :size 20 :maxlength 20)) (description :type string :accessor description :initarg :description :component (text-area-field :width 20 :height 10)) (other :accessor other :component (text-field :size 20 :maxlength 20))))
...and that looks like a GUI view component. Maybe the term is used both ways? if you are updating a description field in a GUI view and then seeing it written back out to the DB, maybe you could lay out for me the code path by which that happens.
That is the view-component, I just included the db-obj to start the whole thing, I see from you comments that I probably could add it in the model and there the view-obj slot.
I this a decent use of 'cells and is it cells-ish?
Pending a better understanding of the above questions, as I said, I do not see Cells doing very much, and so I would be surprised if they help in this case. But let's see what your feedback is on the above.
Well Cells does the following for me here. I sketch the control-flow. - the first things which is called is a view which shows two textfields and one text area - On the first run the view object should be filled with data from the backend - so I got a view with the slots filled by database values - Now I may change one, two or three fields. Aftar I send the form the database should be updated, this is done by cells here. - After that the content of both the view and the database are shown - Now it happens that I found that I made a bug and hit Back on my browser - the browser will display me the first view again, but with the changed database values - I change them again hit submit and the stuff updates my Database again.
Agreed, cells does not do much here, but it's to learn how to let those objects interact. And for that it works quite nicely ;-)
Regards Friedrich
Friedrich Dominicus wrote:
Kenny Tilton ktilton@nyc.rr.com writes:
Friedrich Dominicus wrote:
I got it (probably ;-), would someone mind to comment on it?
Thanks for your time. I try to explain my "convulted" way of getting into celsl a bit ;-)
(make-instance 'controller :view-obj (init-view view))
C-IN (or C-INPUT) is used only where, in brief, the application will be using SETF to change the value in a sempahoric slot. This is partly because a dataflow model needs to get the original dataflow from somewhere, usually from operating system events or a socket. One can also sometimes get simpler and more efficient code by skipping the declarative aspect (in which a slot like view-obj would have a rule) and just make the slot C-In and then setf that slot from output methods on on other slots. But like I said, that loses the advantages of a declarative approach.
Well I read the explanations in 01-somwwhat and there I found if you the slot hast to be setf-able you have to use c-in (in short, so I wrote it that way.
I should have mentioned "...but I do not see any place in your code where you SETF view-obj". Did I miss it?
Now in this case I further do not see view-obj getting involved in any cell-mediated dataflow, so I do not think it even needs to be a cell.
(db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (update-from-view cells:self)))))
The opening bit of update-from-view says:
(unless (slot-value self 'db-obj) .....)
Actually, the c? macro offers any existing value as a read macro:
(db-obj :accessor db-obj :initarg :db-obj :cell t :initform (cells:c? (unless .cache. (update-from-view cells:self))))
I've seen the variable but was quite happy to find out the above way ;-)
That is fine if you do not mind "unsupported", ie, your code collapsing in a heap if Cells changes in some relevant way. the larger point is that, either way, after the second time this rule runs there will be no dependencies and the cell (and rule) will get optimized away. So I still do not see Cell-ish dataflow. That said,.....
...and then do not check for an existing slot-value in u-f-v. Now I do have rare occasion to write code like that, but the interesting thing here is that this rule only runs once, after which it would always return the same value. So there is no dataflow here, where one thing changes (by a SETF of some c-input) and then a bunch of other things get updated automatically in a cascade of rule evaluations.
I do not understand that. If the view changes e.g if I use the back button of my browser I'll be back to the old view. The data will get filled from the then actual Database view, if I change something again it will get propagated again from the View to the Backend.
I believe you! :) I just do not see the back button in the code or how this is working! I have a guess, though. I think somehow each time you are allocating all new instances, so the new cells / rules run once (the initial "awaken" pass started by TO-BE) and things show up nicely. Cells are all about long-lived state, where the same instance would survive back buttons and forward buttons and sideways buttons and still manage to stay current. That said <g>.......
Maybe I missed something. My first question, does this code work for you? If so, what are the things you see happening that tell you it work? Just give me a simple scenario, such as "I start by reading in this stuff. Then I change this description field, then I exit, and when I look at the DB I see the new description text." Provide the sample code and explain where necessary which code does which step.
See above, the back button of the browser makes it possible to return to the view.
A big problem here is that I do not know SQL or cl-sql. For example, is a view just in-memory, or does it refer to a screen view? I know a relational view is just an abstraction built atop physical tables, so maybe you are just talking about that. Well, I do see:
(defcomponent example-view (simple-window-component) ((db-obj :initarg :db-obj :reader db-obj) (tag :accessor tag :initarg :tag :component (text-field :size 20 :maxlength 20)) (description :type string :accessor description :initarg :description :component (text-area-field :width 20 :height 10)) (other :accessor other :component (text-field :size 20 :maxlength 20))))
...and that looks like a GUI view component. Maybe the term is used both ways? if you are updating a description field in a GUI view and then seeing it written back out to the DB, maybe you could lay out for me the code path by which that happens.
That is the view-component, I just included the db-obj to start the whole thing, I see from you comments that I probably could add it in the model and there the view-obj slot.
I this a decent use of 'cells and is it cells-ish?
Pending a better understanding of the above questions, as I said, I do not see Cells doing very much, and so I would be surprised if they help in this case. But let's see what your feedback is on the above.
Well Cells does the following for me here. I sketch the control-flow.
- the first things which is called is a view which shows two textfields
and one text area
- On the first run the view object should be filled with data from the
backend
- so I got a view with the slots filled by database values
- Now I may change one, two or three fields. Aftar I send the form the
database should be updated, this is done by cells here.
- After that the content of both the view and the database are shown
- Now it happens that I found that I made a bug and hit Back on my
browser
- the browser will display me the first view again, but with the
changed database values
- I change them again hit submit and the stuff updates my Database
again.
Agreed, cells does not do much here, but it's to learn how to let those objects interact. And for that it works quite nicely ;-)
I am going to go waaaaaaaaaaay out on a limb here and guess that the only thing Cells did was force you to structure things in a declarative way, or at least a nicely organized way, and that that itself is a big win. So it is not an issue of how long-lived is a model instance, or how many times a Cell rule runs, but how the data structures interact (as you said).
I have been doing Cells for ten years, but this is the first time I have encountered this. Interesting result. Thx.