I was reviewing multiple ORMs, Og, ActiveRecord, Class::DBI, DBIx::Class, et al, and I was wondering if anyone knows of a more a Postgres centric way of solving the problems that ORMs are supposed to solve.
The purpose of my investigation was to incorporate an ORM into an MVC. I like what rails did mutating the both of them into one. But, I think they choose the worst ORM to do so. I don't like the fact that I'm supposed to design in an app, and roll changes to a db. I would much rather design in the db, and have the application adapt. Any form of validation should first and foremost be present in the db, and secondly in the app. Is there any ORM in existence that supports deducing column/table constraints from utilities like the information_schema. I was thinking of taking on the task of redesigning an ORM. The first purpose of this post is to see if there a consensus on a non-crappy ORM in existence, and then to get critique on a few ideas I've had.
-
Firstly, the ORM should support Postgres to the best of its ability, I don't care about supporting other DBs, or the support for other DBs.
-
The ORM should deduce at the bare minimum the table relations, the columns and their data-types, the constraints, etc.
-
It should start off by converting the information_schema, itself into an internal instance, and allow plugins to further deduce from the database.
-
Some MVC web frameworks supports scaffolding on the view, this should be thought of ideologically as scaffolding on the model.
-
The structure of the files could/should be significant to the structure of the db.
-
foo/bar/baz should imply the database foo, the schema bar, the table baz.
-
setting the connect string in the file foo should set a dynamic scaffolding model for all schemas and tables in the db foo
-
`touch`ing foo/bar should disable the dynamic scaffolding for all schemas except bar.
-
`touch`ing foo/bar/baz should likewise, disable dynamic scaffolding for all tables in schema bar except foo/bar/baz
-
Instances of the models should not necessitate a query on the database, Foo::bar::baz.quuz = 5; should translate into 'update bar.baz set quuz = 5', in rails a select must first be performed.
These are just some ideas, of how I would design it, I have a script that assembles an array of objects for each database, containing arrays of schema objects, which contain arrays of table objects, which contain arrays of column objects, which store things like constraints etc. This seems like a good start, I might take it further if others like this idea.
As a side note indigo on freenod, pointed me to python's sqlalchemy, an ORM that appears to offer some functionality with the information_schema using an AutoLoad=True arguement. http://www.sqlalchemy.org/docs/metadata.myt#metadata
So monks, any ideas, and what ORM comes closest to a feature set like this?
Evan Carroll www.EvanCarroll.com
Re: Non-retarded ORMs, and a general ORM discussions.
by perrin (Chancellor) on Jun 16, 2006 at 19:32 UTC
|
Rose::DB::Object supports some of PostgreSQL's proprietary features and has a system for reading schema information from the database that you can extend to suit your needs. | [reply] |
Re: Non-retarded ORMs, and a general ORM discussions.
by CountZero (Bishop) on Jun 16, 2006 at 21:36 UTC
|
DBIx::Class has Postgres-support (but not having had to use the Postgres bits, I don't know how good it is) and DBIx::Class::Schema::Loader allows for dynamic discovering your tables, fields and keys. Relationships are still a bit of an unexplored area, but hey, DBIx::Class is still in full development so there is a lot of room to add, amend and update what is missing!
CountZero "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law
| [reply] |
Re: Non-retarded ORMs, and a general ORM discussions.
by runrig (Abbot) on Jun 16, 2006 at 17:57 UTC
|
The last I checked, Alzabo was PostgreSQL and MySQL specific, and sounds like it may be what you are looking for. | [reply] |
|
| [reply] |
|
You need an example? It's just a method. There you go. This creates one schema object based on whatever is in your database. To read a PostgreSQL database and create a schema that can be used by Alzabo. If you feel like it, it looks like there's a ->runtime_clone method on the Alzabo::Create::Schema object as well. You wouldn't use that for normal runtime but it might be convenient for your maintenance scripts.
my $schema = Alzabo::Create::Schema->reverse_engineer(
name => ...,
rdbms => "PostgreSQL",
user => ...,
password= > ...
);
$schema->save_to_file; # I forget how the save directory is configured
Your runtime code: my $schema = Alzabo::Runtime::Schema->load_from_file( name => ... ); | [reply] [d/l] [select] |
|
|
|
Re: Non-retarded ORMs, and a general ORM discussions.
by Joost (Canon) on Jun 16, 2006 at 22:57 UTC
|
The purpose of my investigation was to incorporate an ORM into an MVC. I like what rails did mutating the both of them into one. But, I think they choose the worst ORM to do so. I don't like the fact that I'm supposed to design in an app, and roll changes to a db.
First off, Rails doesn't mutate the ORM into an MVC - rails just makes it easy to generate a Model View and Controller classes based on a database table. You don't have to generate each, and in my view the Model classgeneration is probably the most useful.
Secondly, If you don't change the DB, you're free to change the (possibly generated) classes as you see fit, but if you do change a DB table's fields, the model changes automatically with it (via ActiveRecord).
Maybe I'm misinterpreting that part of your post, but I don't really see what you mean there.
| [reply] |
|
Rails makes the ORM an intergal part of the framework. The ORM sucks; hence, by proxy, the framework sucks. That is what I mean.
First off, Rails doesn't mutate the ORM into an MVC - rails just makes it easy to generate a Model View and Controller classes based on a database table.
If the egg comes before the chicken it is anything but "easy." Rails doesn't generate a model, it generates a file for you to statically type the model. Now, before I started this rant, I was unaware of Alzabo, DBIx::Class's Schema::Loader, or Rose::DB, I'm currently setting up Rose::DB and liking it a lot. - And thanks to the monks with info - These frameworks do what you mentioned, "generate a model ... based on a database table." Rails simply adds getter/setter methods for the table. Big deal. In the rails community they teach DRY like it is a religion, and then they make the assumption that every DB lacks constriants, and that every programmer wishes to treat the DB as if it had the feature set of SQL lite, or MySQL 3.2. Every programmer doesn't -- I don't. Furthermore, rails doesn't generate a a Model, View, or Controller based on a database table, it generates them based on the arguement you give to the generator, wheither or not they exist is your problem. (though again, like most ORMs it can transparently add the getter/setters for the instances at run time)
Secondly, If you don't change the DB, you're free to change the (possibly generated) classes as you see fit, but if you do change a DB table's fields, the model changes automatically with it (via ActiveRecord).
You're obviously misguided. ActiveRecord does not change the model to reflect changes in the db, ever. The only thing the model automatically does, is generate
</quote>
Alright then, change the primary key, change a check constraint, change a foreign key, change a data type. Oh, look, ActiveRecord proves how adaptive it is yet again. In AR if you create a table with an int column, you can rightfully, or wrongfully attempt to insert a string. The following comes from a ruby bot I was writing with a rails interface, my second rails project. Observe:
channel.population = 'foo'
channel.save
Yields this:
UPDATE channel SET "name" = '#debian-uy', "descr" = 'Debian Uruguay | http://debianuruguay.org | Si quieres pegar código: http://debian-uy.pastebin.com/ | Gran Campaña Pro-Mirror: http://debianuruguay.org/node/129', "population" = 0 WHERE pkid = 3
Thats right, I inserted into an int, the value 'foo', and rails converted that to a numeric 0. I once again, did not tell rails to update name, descr, or pkid. I told it to update population and it generated this statement. What a waste, without a .save(), it won't flush the instance, and with a .save() it flushes the object dispite the content, how primitive.
Ruby syntax is clean, it is a fun language, and I look forward to a more advanced framework that is flexible and reflects the richness and cleanliness of Ruby's grammer. Rails isn't it.
Evan Carroll www.EvanCarroll.com
| [reply] [d/l] [select] |
Re: Non-retarded ORMs, and a general ORM discussions.
by stonecolddevin (Parson) on Jun 16, 2006 at 21:35 UTC
|
| [reply] |
|
| [reply] |
Re: Non-retarded ORMs, and a general ORM discussions.
by davorg (Chancellor) on Jun 19, 2006 at 08:49 UTC
|
You might be interested in my talk What's Wrong with ORM. I gave it to london.pm back in March and I'm giving it again to GLLUG this coming Saturday. I'll be wheeling it out one last time at YAPC::Europe in August. I really should get round to turning it into an article.
--
< http://dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] |
|
++ Nice slides, in terms of both content and presentation.
| [reply] |
Re: Non-retarded ORMs, and a general ORM discussions.
by eric256 (Parson) on Jun 16, 2006 at 21:54 UTC
|
I'll expose my ignorance. What is an ORM? What is wrong with the existing ones? And how would you use one?
P.S. anything that just supports one DB with no care for others is probably going to loose opensource support ;) Probably, maybe not though.
| [reply] |
|
Object-Relational Mapping/Manager, I suspect. (I'm used to seeing it as ORML = Object-Relational Mapping Layer.) Basically a layer of code that automates the work of moving data back and forth between in-memory objects and a relational database.
| [reply] |
Re: Non-retarded ORMs, and a general ORM discussions.
by rvosa (Curate) on Jun 23, 2006 at 03:27 UTC
|
I think the big problem is that ORMs usually consider 1 table == 1 object. | [reply] |
|
|