Hi Geert, The MVC approach is ideal. Yes, the app has evolved from a relative simple web form to a more sophisticated state-machine driven application. The question is always, "At what point is the additional effort cost-effective and necessary to enhance reusability and to reduce the time required for maintaining the code and adding new features?" For now I reckon what I have is good enough, but I will keep your suggestion into mind.
~Tim -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Geert Josten Sent: Saturday, September 17, 2011 12:53 PM To: General MarkLogic Developer Discussion Subject: Re: [MarkLogic Dev General] How to effectively pass variables by reference to an xquery function? Hi Tim, I might have some other reasons to want to do things differently. Don't get me wrong, I would have written similar code to get something working at first. But once you start extending things, you will find this approach limiting, and not of best design. The most important concern is that it looks like you are mingling database access, control flow, and presentation all in one piece of code. Moving database knowledge into the working-value function could worsen this in fact. I would really recommend taking an MVC kind of approach here. The model (preferably a separate, reusable module) would also help with shielding data access. It would hold any knowledge necessary to produce new and database values. The main module could serve as controller in your case, delegating between request information and model to get the model updated if necessary. The view (another separate, reusable module) would take care of putting values into an editable form, and showing it to the user. The main logic could look something like this: let $action := xdmp:get-request-field("action") let $type := xdmp:get-request-field("type") let $id := xdmp:get-request-field("id") let $changed-values:= map:map() let $get-changed-values := for $n in xdmp:get-request-field-names() where not($n = ('action', 'id', 'type')) return map:put($changed-values, $n, xdmp:get-request-field($n)) let $is-saved := if ($action = "Save") then m:update-model($type, $id, $changed-values) else false() let $show-values := if ($action = "Save") then $changed-values else if ($action = "New") then m:get-new-values($type, $id) else m:get-db-values($type, $id) return v:show-form($type, $id, $is-saved, $show-values) Kind regards, Geert -----Oorspronkelijk bericht----- Van: [email protected] [mailto:[email protected]] Namens Tim Meagher Verzonden: donderdag 15 september 2011 19:45 Aan: 'General MarkLogic Developer Discussion' Onderwerp: Re: [MarkLogic Dev General] How to effectively pass variables by reference to an xquery function? Hi Geert, I don't need to build the XML document if no changes occurred, unless I do it exclusively to perform a deep equal. Also, there are some updated status values (save date, save name, etc) that would cause a deep-equal to fail. That's very perceptive of you to notice that I don't need to perform a database fetch if the action is New. I haven't figured out how to pass in the document nodepath to query the database within the function without a nice juicy if-else action as a function of the request field name. Any suggestions? Thanks! Tim -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Geert Josten Sent: Thursday, September 15, 2011 1:19 PM To: General MarkLogic Developer Discussion Subject: Re: [MarkLogic Dev General] How to effectively pass variables by reference to an xquery function? Hi Tim, I think I understand why you put all that $action and if logic inside the function, but I also think your problem could be less complex if you didn't. Next to this, you are checking for changes for each value individually. But how about building your XML first, and simply doing a deep-equal to compare it with the database doc? If your form-values cover most of your XML, and the XML isn't very big, that could work equally fast. You don't need the db-values by the way if $action is 'New', so you could save yourself the effort looking for them in that case. But only if you put the if logic outside the function. ;-) (or the logic to retrieve them inside the function..) HTH! Kind regards, Geert -----Oorspronkelijk bericht----- Van: [email protected] [mailto:[email protected]] Namens Tim Meagher Verzonden: donderdag 15 september 2011 17:33 Aan: 'General MarkLogic Developer Discussion' Onderwerp: Re: [MarkLogic Dev General] How to effectively pass variables by reference to an xquery function? Hi Geert, It makes sense, but I'd like to call just one function that receives multiple parameters: - existing database value - request field name - action - new value When invoked, the function uses the action to determine what value should be assigned to a local variable and sets a status if the values differ. So rewriting my example we have: xquery version "1.0-ml"; declare namespace t = "test"; declare variable $t:changed := false(); declare function t:working-value($action, $db-value, $request-field, $new-value) { let $form-value := if ($action eq ("Get", "Save")) then xdmp:get-request-field($request-field) else () return if ($action eq "New") then $new-value else if ($action eq "Retrieve") then ( $db-value, if (not($t:changed) and $db-value ne $form-value) then xdmp:set($t:changed, true()) else () ) else if ($action eq "Save") then ( $form-value, if (not($t:changed) and $db-value ne $form-value) then xdmp:set($t:changed, true()) else () ) }; let $name := t:working-value("Save", "Joe", "Name", "") let $position := t:working-value("Save", "Joe", "Name", "") (: let $local-var := t:working-value(...) :) return ( if ($save) then (: build XML document using name, position, ... and insert it into the database :) else (), (: populate form :) ) Cool? Tim -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Geert Josten Sent: Thursday, September 15, 2011 10:54 AM To: General MarkLogic Developer Discussion Subject: Re: [MarkLogic Dev General] How to effectively pass variables by reference to an xquery function? Hi Tim, Ah. In that case I would have written a 'has-changed' function, that returns a Boolean. You apply that to all values first, and check for trues and falses after that. You can do that more fixed, but you could also collect Boolean in a sequence and look for a true in that as well. Makes sense? Kind regards, Geert _______________________________________________ General mailing list [email protected] http://developer.marklogic.com/mailman/listinfo/general _______________________________________________ General mailing list [email protected] http://developer.marklogic.com/mailman/listinfo/general _______________________________________________ General mailing list [email protected] http://developer.marklogic.com/mailman/listinfo/general _______________________________________________ General mailing list [email protected] http://developer.marklogic.com/mailman/listinfo/general _______________________________________________ General mailing list [email protected] http://developer.marklogic.com/mailman/listinfo/general
