In response to my comments (see CapabilityQuestions) about an alternative to ActiveRecord for the interaction between the model and ActionPack, Florian Weber? writes:
How do you expect this to work? How should the scaffolding feature know how to save, load, etc your model data? It would have to know some kind of
API. Also you would have to give more information about your model data,
than you normaly do with ruby. Simply doing @name = "" wont say anything
about the length of the string. I could see it working when you implement
it for other APIs like Madeleine, but something like a generic target would end
up in a pure mess, imho.
To which I respond:
I am not proposing that that we solve every possible persistence problem in a single class, only that the interface between ActionPack and the model should not assume a SQL data source. In other words, much of the functionality of the base ActiveRecord class would be pulled up into another class which makes no assumptions about the persistence mechanism. Developers could then extend this class instead of using the ActiveRecord base class when using a non-SQL oriented data store. Nothing messy about this at all, its just good design.
— John-Mason P. Shackelford?
Florian Weber? responds:
Well, the problem is still the same: you would need a interface for common persistance tasks. But different apis do things in a different way. For example Madeleine works very different than ActiveRecord. To abstract those differences away would be such a overhead and at the end cause more trouble and kill performance, than actually help.
From a design perspective, imho, i dont think its good design to have something like a common base class, which SQL-less models would extend. What if the the persistence mechanism you are using requires
you to extend one of their own classes, or include the stuff as modules break things.
I think the best solution would probally be to just implement the scaffolding for different model-types..
But i’m also curious: do you have a concrete example of which non-SQL oriented data store you would be using?
Florian Weber?
John-Mason agrees:
I understand that Madeleine and ActiveRecord operate very differently, which is why I am proposing a bare bones minimalist API. Not every model is even persisted—even the persistence assumption is not one I’d want. I just don’t believe that ActionPack should assume (even for a subset of functionality like scaffolding) that model==SQL data source. I should be able to create a simple, even non-persistable object that conforms to a very simplistic interface and have the benefit of the scaffolding functionality. I certainly am not proposing a catch-all persistence engine—the scoffolding feature is more about the controller and view and shouldn’t know much of anything about persistence anyway.
I agree that overuse of extension is not a good thing, this is why I recommended an interface, thinking in Java. In Ruby perhaps this means a module or mix-in. Or perhaps, as you suggest, ActionPack ships with serveral model adaptors, one for SQL-oriented models, one for plain-old-Ruby-objects, one for XML data sources, etc. In either case, we need some simplistic contract between the model and the controller for the sake of the scaffolding functionality. The scaffolding code doesn’t try to solve every problem—it just gets one started, and that is all that I am asking of this contract.
Two concrete examples:
1. Model constants: Model objects that exist as part of the running application and contain core business information, but which do not require any persistence whatsoever.
2. A non-SQL oriented data source: for example, I am writing a front end to the Perforce SCM tool. My API consists of a few predefined data types. Peristence for each must be hand coded since my model is essentially an adaptor to the P4Ruby API.
3. Prototyping / Testing: I commonly start an application, especially one whose primary value-add is the UI, by creating a few key business objects, mocking up data, and sketching out a basic UI. This is the approach DavidHeinemeierHansson uses in the 10 minute video and it is sound. Eventually one adds a connection to the back end data source and makes UI improvements. Having to start with an ActiveRecord object as my model, when a plain-old-Ruby-object would do (especially when the final data source won’t be SQL-oriented anyway) seems awkward. I am not required to use ActiveRecord, but I can’t use scaffolding, at least not out of the box, without it.
DavidHeinemeierHansson’s 10 minute video is very impressive. When I began this project I expected that I would be able to get up and running as quickly (if not more quickly) with a model coded as plain old Ruby objects, since this is really simpler than creating full-blown database persisted objects. Instead I found that in order to benefit from the scaffolding code I had to reverse engineer ActiveRecord.
My only point in all of this is that the assumption, on the part of ActionPack’s scaffolding code, that all model objects are backed by a SQL oriented data store, prevents me from productively using this very attractive feature without significant additional work up front.
—John-Mason P. Shackelford?
Tom Sawyer offers:
The general request developing in this discussion appears to the same wish I make on the Jigsaw page. Namely, the ability to to use an object model prior to a database model. To achieve this, the use of a mixin + direct ORM is preferable to the current superclass + indirect delegation. The optimal solution would allow the same model interface to go in either direction OM → DBM or DBM → OM. Right now I’m playing with some experimental code, based on the old Jigsaw code, which looks promising. If this is a direction Active Record (meaning DavidHeinemeierHansson) is interested in taking then I will glady dontate my work.
Florian Weber? responds:
I have to admit that im still not really convinced to create a common interface for different kind of persistence mechanisms, just so you can one
kind of scaffolding implementation with it.
To crunch different ways of dealing with persistence into one interface feels
very akward to me. Just think of situations where you have to work with a
service-oriented design like for example hibernate uses.
I think at the end you make much more compromises and your design gets
very ugly. For example in the first example you gave: scaffolding would somehow need to know how to know which property of your object is what
kind of type, etc. So you would have to provide a way for scaffolding to figure
that out.
Basically i just think the differences between all those models and how
they are persisted can be so different, to make all that run through one
interface, would be horrible.
Also for your third example, quite frankly i think its simpler to just use
a quick activerecord object instead of mocking it out or using a normal
ruby object. =)
By the way, scaffolding doesn’t assume a sql datastore. It just assumes
the activerecord interface. Plus the scaffolding code is very very simple. So it should be easy to implement it for other kind of models. Thats imho a better idea.
John-Mason P. Shackelford?:
Florian, I think we are still talking past eachother to some extent. I am not suggesting that we have single interface for all persistence mechanisms, just that Rails by fully model-neutral. Persistence is an implementation detail. That an MVC framework should be model-neutral is a well-recognized design goal.
I don’t think many agile practioners would agree that it is easier to setup a database and create a DDL when all one wants is:
class Bird
attr_reader :wingspan, :beak_type, :airspeed_velocity
attr_writer :wingspan, :beak_type, :airspeed_velocity
end
Also see the example code on the MadeleineRecordWish page.
Rather than reimplement scaffolding for every possible model (and if a single, very basic, model contract—model not persistence— is not acceptable) perhaps a simple model adaptor interface, with a couple of basic ones thrown in for free would be a good way to go.
In any case, I like TOnoma‘s idea: lets write some code and let the code speak for itself. David, I’d like to hear your thoughts on this.
Florian Weber? responds:
But when Rails would be fully model-neutral, that would require as single
interface for all persistence mechanisms. How else could scaffolding use the
model then?
attr_accessor :wingspan, :beak_type, :airspeed_velocity =)
Here it is really just as simple to create those fields in the db though. I use cocoamysql to edit the db structure. Basically its just a question of which tools you use..
I have to admit i dont understand why you think that scaffolding is about the model and not persistence. in imho its 99% about persistence. it lists objects, edits them, etc. It doesnt really take care of any domain concerns.
The only part of actionpack which assumes a ar interface is scaffolding. The rest it totally neutral.
John-Mason P. Shackelford? smiles:
The only reason that scaffolding seems more like persistence and less like a model editor is that in the database world the two are the same thing. If your only data source is a database then obviously the current scaffolding / ActiveRecord relationship works great. My reason for bringing this up is that, at least in my development world, the database is not the only data source, if it is a data source at all.
Persistence may be an aspect of the model, but the model (or elements of it) may need to be persisted using a number of different mechanisms. Simply editing a model, i.e. creating, defining, and deleting objects, does not imply persistence at all—though in many cases one wants to persist a upon making such changes. Editing a model and persisting it are really two separate issues. The C in MVC does want to be involved in editing the model, but typically wants to be as isolated as possible from details related to model persistence, other than to say trigger it as an event. As an aside, a model may have its own persistence contoller—but this is not the same thing as the C in a traditional MVC framework which refers to the application controller. A specific persistence mechanism is an aspect of the model, not of the application controller.
Florian Weber? responds:
I have to admit i dont quite understand why you think that scaffolding seems to be more about persistence is because it currently uses a ar/db backend. As far as i can tell scaffolding is all about managing objects during
their lifecycle and providing a way to edit its properties. So the persistence
part definally belongs there. You have to use a datasource for the model
objects you are editing with scaffolding, even when its just a global
variable. How would you otherwise get a list of all your model objects? Persistence is a part of scaffolding..
Simply editing a model, i.e. creating, defining, and deleting objects, does not imply persistence at all
So basically you want to allow thaqt the user creates and defines a object, but thats not saved anywhere and so the create/change is lost right away after he
reloads or goes to the next page? ; )
A specific persistence mechanism is an aspect of the model, not of the application controller.
In a tradtional mvc framework the controller definatelly wants to be taking care of the persistence. Persistence is not a concern of the domain, so why should the model take care of it? It definitely belongs into the application layer.
Myrddin Emrys? comments:
I am very very new to rails (I have done a tutorial!), and I already have similar needs to John-Mason. I have several database tables which are working marvelously with the Rails framework. But one of the object sets in my model is a directory… not a table. I initially assumed this would be really simple with Rails, but it’s turning out far more complicated than I had anticipated.
I want to be able to treat (from the Controller/View side) the model derived from Dir.each as much the same as possible as those based on SQL. Overriding ActiveRecord seems to be the right choice, but there are a lot of dodgy things I’m doing with .connection and .find because those functions assume a SQL backend.
Far too noobish am I to weigh in with an opinion on this debate… but it seemed important that you all know there are more people out there who would like alternatives to SQL for Model persistence.