
Hi Chris, I like the new url generator package, which should also be useful in focusing an application around the models. In Yesod one would currently check a form for errors and if there aren't any then insert the model, and this is all done from the controller. This puts model logic into the form. We did have techniques (not sure what the state of it is at the moment) to declare fields as required in the schema, and to have that automatically reflected in a form for a model. But a model may have more complex logic than that- a field may be required based on the value of another. This could be handled by indicating a validation function in the schema rather than just a boolean as to whether it should be required. This would also help handle more complex validations than whether just a field is required. One idea behind putting this in the schema, is that the logic is separate from a form. However, the normal way of creating a new model is just a simple insert. insert User { name = "Chris", email = "e", requiredCheckbox = False } So if that is done, but not first from a form (an API perhaps), we have nothing to validate our model. In Rails, in my model file, I can declare validations of arbitrary complexity. To save a model, I have to call model.save, which will run any validations and any callbacks in general (There could be a before_create callback that automatically sends an e-mail). So we could start in Yesod by having a convention of calling save User { name = "Chris", email = "e", requiredCheckbox = False } which would run validations and return a boolean. However, we wouldn't have our list of errors from that. In Rails, calling save would return a boolean, but also have the side effect of either setting the model id or creating an errors variable containing a list of errors that you can inspect and that the form can use. We could return instead return an Either, with the alternative result of the key (id) or the errors for the model. And ideally those errors could be propagated back to a form. Rails also has save! which will throw an exception if the model is not saved- this gets around having to check for errors if you believe there won't be any. There is a data storage library on hackage that supports triggers. http://hackage.haskell.org/packages/archive/TCache/0.8.0.2/doc/html/Data-TCa... One can emulate trigger callback behavior by writing their own save function, however the problem is that this allows multiple possible entries into saving a model because they can write multiple different save functions. Real enforcement of a single entry point with triggers is possible in something like TCache where triggers are tied into the persistence layer.
From my limited Ruby experience, it is the triggers and validations that one attaches to the models, that really define the business logic of the model, (lets ignore for now how one deals with relationships to other models). Much of the rest of putting code into models is about having a nicer way to share, organize, and test code.
Greg Weber
On Mon, Jun 20, 2011 at 4:07 AM, Christopher Done
On 10 June 2011 16:12, Greg Weber
wrote: I would like to come up with a good system for maintaining invariants and propagating violations to forms, and other useful systems for doing more than just taking the query out of the controller. Let us know if there is anything stopping you from separating out code into a Models directory right now.
An example of managing invariants and propagating violations to forms?