Janko,
Thanks for fixing the truncated lines on the tutorial. After completing the tutorial I have a couple of questions: #1) Where would I hook in data validations? #2) UrlResolver: This is slick in a small tutorial but doesn't it mean I can not scale past a single image? It seems like it would also mean I have to use image persistence because the urlResolver is holding a reference to all the objects. I'm hoping I'm way off the mark here. _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
Hi Elliot,
On 11. 04. 2011 22:33, Elliot Finley wrote: > Janko, > Thanks for fixing the truncated lines on the tutorial. After > completing the tutorial I have a couple of questions: Nice to hear that! > > #1) Where would I hook in data validations? See the WebDemoApp>>ajaxValidationExample : ... field := e cell addInputFieldAspect: #year for: self size: 4. field onChangePost; validIfTrue: [:value | value asInteger = Date today year]; errorText: 'Wrong!'. e newCell add: field errorElement. So, #validIfTrue: aBlock is the main thing for making a validation of your data. If this block doesn’t pass, submitting of a whole form is blocked. Only until all fields on form are valid, submitting will succeed. What you see in above demo is an additional ajaxified validation and error reporting immediately after data entry. > #2) UrlResolver: This is slick in a small tutorial but doesn't it mean > I can not scale past a single image? It seems like it would also mean > I have to use image persistence because the urlResolver is holding a > reference to all the objects. I'm hoping I'm way off the mark here. URLResolver is only one of possible resolvers and you can add you own of you really need it. There is a WebRouter where you can register an additional one and where you can see some more already. URLResolver itself is also a two way resolver: url->object and also very important object->url. Later is what makes navigation in Aida apps so easy so powerful. URLResolver itself is capable to resolve up to about 100K objects, after this it becomes slow because of hashing, specially in object->url way. But funny thing is that I didn't yet got so big web app to need more that so much objects. URLResolver is also meant for long living objects. For image persistency or GLASS therefore. For relational mapping where you usually have very short living objects in image just representing the data in relational database, the standalone App approach is maybe a better path to go. Idea is to have one App for all objects of one class you are presenting. Say you have a table of persons, you prepare a PersonApp class and register it as a class on some url: AIDASite default register: PersonApp onUrl: /persons Hope this helps a bit Janko > _______________________________________________ > Aida mailing list > [hidden email] > http://lists.aidaweb.si/mailman/listinfo/aida > -- Janko Mivšek Aida/Web Smalltalk Web Application Server http://www.aidaweb.si _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
2011/4/11 Janko Mivšek <[hidden email]>:
>> #1) Where would I hook in data validations? > > See the WebDemoApp>>ajaxValidationExample : > ... > field := e cell addInputFieldAspect: #year for: self size: 4. > field > onChangePost; > validIfTrue: [:value | value asInteger = Date today year]; > errorText: 'Wrong!'. > e newCell add: field errorElement. > > So, #validIfTrue: aBlock is the main thing for making a validation of > your data. If this block doesn’t pass, submitting of a whole form is > blocked. Only until all fields on form are valid, submitting will succeed. > > What you see in above demo is an additional ajaxified validation and > error reporting immediately after data entry. how would I do a validation based on another form field. For example if I had a scheduling application and I had a startDate and endDate. I would want to validate that both dates were in the future and I would want to validate that startDate < endDate. >> #2) UrlResolver: This is slick in a small tutorial but doesn't it mean >> I can not scale past a single image? It seems like it would also mean >> I have to use image persistence because the urlResolver is holding a >> reference to all the objects. I'm hoping I'm way off the mark here. > > URLResolver is only one of possible resolvers and you can add you own of > you really need it. There is a WebRouter where you can register an > additional one and where you can see some more already. URLResolver > itself is also a two way resolver: url->object and also very important > object->url. Later is what makes navigation in Aida apps so easy so > powerful. Looking at URLResolver, it looks like if I want to scale past a single image, I would need to persist allWebPages and allURLLinks to my database (Magma for example). The only problem is allWebPages is an identityDictionary. The identity will change each time it is brought in from the database. Am I looking at this the right way? If so, do you know of a way to solve this? > URLResolver itself is capable to resolve up to about 100K objects, after > this it becomes slow because of hashing, specially in object->url way. > But funny thing is that I didn't yet got so big web app to need more > that so much objects. perhaps a btree structure rather than a hash structure? a little slower with few objects but much much faster after the hash starts to degrade. > URLResolver is also meant for long living objects. For image persistency > or GLASS therefore. This makes sense but, I'd also like to be able to use Magma as an option. It appears that the only obstacle is the allWebPages IdentityDictionary. I don't know how to persist that in Magma since the identity of an object will change each time it's resurrected from the database. Any thoughts on this would be appreciated. Elliot _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
Elliot Finley <[hidden email]> writes:
> 2011/4/11 Janko Mivšek <[hidden email]>: >>> #1) Where would I hook in data validations? >> >> See the WebDemoApp>>ajaxValidationExample : >> ... >> field := e cell addInputFieldAspect: #year for: self size: 4. >> field >> onChangePost; >> validIfTrue: [:value | value asInteger = Date today year]; >> errorText: 'Wrong!'. >> e newCell add: field errorElement. I think this block is not "enough". I've checked also with Iliad and both Aida/Web and Iliad are just using a block. I think one should use a class hierachy for that. Pseudo Code Klasse Validiation validate .... Maybe this Validatian stuff needs some link or relationship to other fields and or business rules. One can see the "shortcomings" of this block int he book a mentoring course in smalltal from Andres Vallhoud. I suggest checking his SUnit based Validation code. Just so much if we use ths blocks we'll have code duplication over and over and over again validIfTrue: [:value | value asInteger = Date today year]; errorText: 'Wrong!'. and it will end in somethin like validIfTrue: [:value | (((value isEmpty not) and: (value isNumeric))) and: value isFractional not .... ... ... .... errorText: 'Value must be a non empty numeric value I think we'd better have classes which encapsulate the Validations. class Validaor class NotISmptyValidator and we just have to instantiate the proper classes and not "just" copy& paste code blocks around. > > how would I do a validation based on another form field. For example > if I had a scheduling application and I had a startDate and endDate. > I would want to validate that both dates were in the future and I > would want to validate that startDate < endDate. difficult with just von value indeed but if you'd have validators you could have DateValidatorWithDataRange fromDate: toDate: validate fromDate <= toDate if.... vl := DateValidatorWirthDataRange new vl fromDate: vl toDate form addValidator: vl.... there ist still another problem the presenting of date. we have code like: columnAspects: #(#tanNr #date #amount #comment nil); column: 1 addBlock: [ :each | (WebElement new) addLinkTo: each text: each tanNr]; column: 2 addBlock: ... each date asString !!! column: 3 addBlock each amount transferAmountIntoString column: 5 addBlock: [ :each | | el nL | We need to "know" the class of all "variables." and so we can not get this better automated. Now compare it to: Presenter present ^ someStrinpresentation. We'd just have to write than columnAspects: #(#tanNr #date #amount #comment nil); and the column calls the present message.... So we'd may be able not having to write this code over an over again. In the end we probably can put all the Elements in another class and just write thisClass present..... The problem comes if you see how the "transformation" between objects and String are done: autoConvertString: aString toObject: anObject "try to convert string depending on object type" (anObject isKindOf: String) ifTrue: [^aString]. (anObject isKindOf: Integer) ifTrue: [^aString asInteger]. (anObject isKindOf: FixedPoint) ifTrue: [^aString asFixedPoint: anObject scale]. (anObject isKindOf: Date) ifTrue: [^Date readSloFrom: aString readStream]. anObject isNil ifTrue: [^aString]. ^aString There's no way to change the presentation of Date but to add to rewrite this method. Blocks are surly fine but I think they are not good enough for such repeating tasks. We should use classes for it and we'd have much more "reusability". I know you mileage may vary. However I'm not alone with that suggestions.... This also was implemented in CL-HTTP and CLIM earlier, so it's IMHO a worthwhile pattern which is IMHO undervalued: http://www.cl-http.org:8000/cl-http/frame.html The different validators and Accepters are surely collectable and would make it easier to build larger functional blocks. Regards Friedrich -- Q-Software Solutions GmbH; Sitz: Bruchsal; Registergericht: Mannheim Registriernummer: HRB232138; Geschaeftsfuehrer: Friedrich Dominicus _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
In reply to this post by Elliot Finley
On 18. 04. 2011 06:54, Elliot Finley wrote:
>>> #2) UrlResolver: This is slick in a small tutorial but doesn't it mean >>> I can not scale past a single image? It seems like it would also mean >>> I have to use image persistence because the urlResolver is holding a >>> reference to all the objects. I'm hoping I'm way off the mark here. >> >> URLResolver is only one of possible resolvers and you can add you own of >> you really need it. There is a WebRouter where you can register an >> additional one and where you can see some more already. URLResolver >> itself is also a two way resolver: url->object and also very important >> object->url. Later is what makes navigation in Aida apps so easy so >> powerful. > > Looking at URLResolver, it looks like if I want to scale past a single > image, I would need to persist allWebPages and allURLLinks to my > database (Magma for example). The only problem is allWebPages is an > identityDictionary. The identity will change each time it is brought > in from the database. Yes, in case of ODB persistence the best way is to persist all AIDASite, even more, start with SwazooServer then cut the persistence for things that are transient. In SwazooServer #servers instvar, in Aida session application state (instances of App classes in WebSession instvar #appsForObjects), etc. I have similar solution developed for Gemstone (GS) on VisualWorks (VW) (not GLASS) long time ago, in this case GS objects are replicated to VW image. GS uses special methods with directives on class side to determine, which instance variables should be made persistent and which not. I'm pretty interested to use Magma for persistency of Aida based projects and if you are interested to help here, it would be really nice. I think also Chris Muller, author of Magma will be happy to help. Best regards Janko > > Am I looking at this the right way? If so, do you know of a way to solve this? > >> URLResolver itself is capable to resolve up to about 100K objects, after >> this it becomes slow because of hashing, specially in object->url way. >> But funny thing is that I didn't yet got so big web app to need more >> that so much objects. > > perhaps a btree structure rather than a hash structure? a little > slower with few objects but much much faster after the hash starts to > degrade. > >> URLResolver is also meant for long living objects. For image persistency >> or GLASS therefore. > > This makes sense but, I'd also like to be able to use Magma as an > option. It appears that the only obstacle is the allWebPages > IdentityDictionary. I don't know how to persist that in Magma since > the identity of an object will change each time it's resurrected from > the database. Any thoughts on this would be appreciated. > > Elliot -- Janko Mivšek Aida/Web Smalltalk Web Application Server http://www.aidaweb.si _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
In reply to this post by Elliot Finley
Hi Elliot,
Let me split this thread in two branches, first one about validation: On 18. 04. 2011 06:54, Elliot Finley wrote: > 2011/4/11 Janko Mivšek <[hidden email]>: >>> #1) Where would I hook in data validations? >> >> See the WebDemoApp>>ajaxValidationExample : >> ... >> field := e cell addInputFieldAspect: #year for: self size: 4. >> field >> onChangePost; >> validIfTrue: [:value | value asInteger = Date today year]; >> errorText: 'Wrong!'. >> e newCell add: field errorElement. >> >> So, #validIfTrue: aBlock is the main thing for making a validation of >> your data. If this block doesn’t pass, submitting of a whole form is >> blocked. Only until all fields on form are valid, submitting will succeed. >> >> What you see in above demo is an additional ajaxified validation and >> error reporting immediately after data entry. > > how would I do a validation based on another form field. For example > if I had a scheduling application and I had a startDate and endDate. > I would want to validate that both dates were in the future and I > would want to validate that startDate < endDate. If you do Ajax single field posting as in above example, you have value of first field already saved into domain object, so you can use it in validation of second field, something like: field ... validIfTrue: [:endDate | self observee startDate < endDate ] ... Best regards Janko -- Janko Mivšek Aida/Web Smalltalk Web Application Server http://www.aidaweb.si _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
2011/4/20 Janko Mivšek <[hidden email]>:
> Hi Elliot, > > Let me split this thread in two branches, first one about validation: > > On 18. 04. 2011 06:54, Elliot Finley wrote: >> 2011/4/11 Janko Mivšek <[hidden email]>: >>>> #1) Where would I hook in data validations? >>> >>> See the WebDemoApp>>ajaxValidationExample : >>> ... >>> field := e cell addInputFieldAspect: #year for: self size: 4. >>> field >>> onChangePost; >>> validIfTrue: [:value | value asInteger = Date today year]; >>> errorText: 'Wrong!'. >>> e newCell add: field errorElement. >>> >>> So, #validIfTrue: aBlock is the main thing for making a validation of >>> your data. If this block doesn’t pass, submitting of a whole form is >>> blocked. Only until all fields on form are valid, submitting will succeed. >>> >>> What you see in above demo is an additional ajaxified validation and >>> error reporting immediately after data entry. >> >> how would I do a validation based on another form field. For example >> if I had a scheduling application and I had a startDate and endDate. >> I would want to validate that both dates were in the future and I >> would want to validate that startDate < endDate. > > If you do Ajax single field posting as in above example, you have value > of first field already saved into domain object, so you can use it in > validation of second field, something like: > > field > ... > validIfTrue: [:endDate | self observee startDate < endDate ] > ... Okay. This leads to another question though. If the first field is already committed to the domain object by the time they are at the second field, then you have the possibility of leaving a domain object in an invalid state. i.e. the user could update some fields and not others. Ideally, you'd want to have an all or nothing approach. Is there a way to do total form validation before the fields are committed to the domain model? perhaps some non-javascript way? Thanks, Elliot _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
Hi Elliot,
EF> others. Ideally, you'd want to have an all or nothing approach. Is EF> there a way to do total form validation before the fields are EF> committed to the domain model? perhaps some non-javascript way? while I accept the arguments on validation of Friedrich and see their usefulness, just let me state two things: - Ajax was a move away from whole form posts for good reasons. But I'm sure you can still make every action a Form post in Aida. - In my own application the web interface always works on a copy of the model object which is only committed when it's in proper state regarding the whole domain model. For example an appointment may itself be in a valid state but may block the necessary travel time to the next appointment in the calendar. So for me validation is not a matter of the web interface. Again, I'm not arguing against Friedrich's proposals on validation, maybe you even want to scan the list archives for those validation discussions. I just describe the way I'm doing it today. Cheers, Herbert mailto:[hidden email] _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
Herbert König <[hidden email]> writes:
> Hi Elliot, > > > EF> others. Ideally, you'd want to have an all or nothing approach. Is > EF> there a way to do total form validation before the fields are > EF> committed to the domain model? perhaps some non-javascript way? > > while I accept the arguments on validation of Friedrich and see their > usefulness, just let me state two things: > > - Ajax was a move away from whole form posts for good reasons. But I'm > sure you can still make every action a Form post in Aida. > > - In my own application the web interface always works on a copy of > the model object which is only committed when it's in proper state > regarding the whole domain model. For example an appointment may > itself be in a valid state but may block the necessary travel time to > the next appointment in the calendar. > > So for me validation is not a matter of the web interface. > > Again, I'm not arguing against Friedrich's proposals on validation, > maybe you even want to scan the list archives for those validation > discussions. I just describe the way I'm doing it today. presentatan and getting form/to a string representation of some object. And if we follow the rules of having difference defence walls we surely should have validation on the view side (and this is what we are talking here) and validation on the model site.. So in the end we probably have three levels of validation 1) validaton based on the input in one "input area" 2) validation based on all the input files of a form 3) validaton on the model side. You copy of the model side is somewhere between 2-3. My proposal especially handles this sorry not very extensible autoConvert function. autoConvertToString: anObject "try to convert object to string depending on object type" "Squeak specific!" (anObject isKindOf: String) ifTrue: [^anObject]. (anObject isKindOf: Integer) ifTrue: [^anObject printString]. (anObject isKindOf: Point) ifTrue: [^anObject printDotString]. "???" "Squeak specific!" (anObject isKindOf: Date) ifTrue: [^anObject shorterPrintSloString]. anObject aidaIsAssociation ifTrue: [^anObject]. "multilingual" ^anObject printString You can not have a different presentation here but you "must" use shorterPrintSloString. This is not good. In the end one must admit. Validation is not really easy and sorry it often just feels like an afterthought. Therfor I suggests an alternative approach which I think is at least better than what there currently is... YMMV of course. Friedrich -- Q-Software Solutions GmbH; Sitz: Bruchsal; Registergericht: Mannheim Registriernummer: HRB232138; Geschaeftsfuehrer: Friedrich Dominicus _______________________________________________ Aida mailing list [hidden email] http://lists.aidaweb.si/mailman/listinfo/aida |
Free forum by Nabble | Edit this page |