From: InetDavid on
Apologies for the complicated setup, but there *is* actually method
behind my madness here!

I'm currently working to implement the Active Record pattern for
TclOO, modeled after the Ruby on Rails (RoR) implementation. (http://
api.rubyonrails.org/files/vendor/rails/activerecord/README.html). So
far, by using classmethod and classvar from TclOO Tricks (http://
wiki.tcl.tk/21595) I've been able to get a proof of concept
ActiveRecord::Base class working with only a small derived class for
each model, just like RoR. This allows me to retrieve records from a
MySQL database with just one statement and have the resulting row(s)
returned as a list of TclOO model instances with access methods for
each table column:

% set result [Model find last]
::oo::Obj5
% $result id
703
% $result name
Some Name
% $result name "New Name"
New Name
% $result save
1
%

My current problem is that I'm now trying to implement the
ActiveRecord::Base "new" and "create" methods which will return a new
(unsaved) row object or will create a new row in the database and
return that row.

I want my own "new" and "create" class methods, but I also need to be
able to use the original "new" method to build new model instances. I
can easily create a new "new" method, but how can I call the previous
"new" method to get an instance of the derived, Model class?

oo::class create ActiveRecord::Base {
classmethod new args {
set model_class [lindex [self caller] 0] ;# kludge to get model
class name from class method
set model_instance [????] ;# How can I get a new Model
instance here???
[...]
}
}

oo::class create Model {
superclass ActiveRecord::Base
classmethod unknown args { ::ActiveRecord::Base {*}$args } ;# since
classmethods aren't inherited yet
}

I've tried using "oo::objdefine Model rename create old_create" but
got the error "method create does not exist", probably because it's
defined in oo::class. I was able to create a forward to the original
with "oo::objdefine Model forward old_create oo::class::create", but
when I try to use it with "Model old_create" I get "empty command name
""".

Does anyone have a way for me to make my own create/new methods and
still be able to find the old methods from within my class?

David Schmidt
From: tom.rmadilo on
On Apr 19, 10:38 am, InetDavid <dav...(a)tower-mt.com> wrote:
> Apologies for the complicated setup, but there *is* actually method
> behind my madness here!
>
> I'm currently working to implement the Active Record pattern for
> TclOO, modeled after the Ruby on Rails (RoR) implementation.  (http://
> api.rubyonrails.org/files/vendor/rails/activerecord/README.html).  So
> far, by using classmethod and classvar from TclOO Tricks (http://
> wiki.tcl.tk/21595) I've been able to get a proof of concept
> ActiveRecord::Base class working with only a small derived class for
> each model, just like RoR.  This allows me to retrieve records from a
> MySQL database with just one statement and have the resulting row(s)
> returned as a list of TclOO model instances with access methods for
> each table column:
>
> % set result [Model find last]
> ::oo::Obj5
> % $result id
> 703
> % $result name
> Some Name
> % $result name "New Name"
> New Name
> % $result save
> 1
> %
>
> My current problem is that I'm now trying to implement the
> ActiveRecord::Base "new" and "create" methods which will return a new
> (unsaved) row object or will create a new row in the database and
> return that row.
>
> I want my own "new" and "create" class methods, but I also need to be
> able to use the original "new" method to build new model instances.  I
> can easily create a new "new" method, but how can I call the previous
> "new" method to get an instance of the derived, Model class?
>
> oo::class create ActiveRecord::Base {
>   classmethod new args {
>     set model_class [lindex [self caller] 0]   ;# kludge to get model
> class name from class method
>     set model_instance [????]     ;# How can I get a new Model
> instance here???
>     [...]
>   }
>
> }
>
> oo::class create Model {
>   superclass ActiveRecord::Base
>   classmethod unknown args { ::ActiveRecord::Base {*}$args }  ;# since
> classmethods aren't inherited yet
>
> }
>
> I've tried using "oo::objdefine Model rename create old_create" but
> got the error "method create does not exist", probably because it's
> defined in oo::class.  I was able to create a forward to the original
> with "oo::objdefine Model forward old_create oo::class::create", but
> when I try to use it with "Model old_create" I get "empty command name
> """.
>
> Does anyone have a way for me to make my own create/new methods and
> still be able to find the old methods from within my class?

There must be a good reason why most sophisticated organizations store
their data in relational databases. My guess is that the data model is
much more powerful than the OO model. Trying to equate the two is a
hopeless pursuit. If anyone wants a good relational to OO model, try
JDBC. For Tcl, AOLserver has ns_db, which represents row data as an
ns_set. The key differences with OO is that correct relational models
allow multiple columns with the same name and columns are ordered (of
course the result rows are also structurally ordered). JDBC follows
this model, most other OO systems do not.

One key concept of OO is modeling. Model the data in a relational
database, don't take shortcuts. One option is to offer multiple
accessor APIs: one API covers the usual case when columns are
referenced by name, the second accesses columns by their order in the
query result. Only the second is guaranteed to return valid results,
only the second represents the query result.
From: InetDavid on
On Apr 19, 12:43 pm, "tom.rmadilo" <tom.rmad...(a)gmail.com> wrote:
> On Apr 19, 10:38 am, InetDavid <dav...(a)tower-mt.com> wrote:
>
>
>
> > Apologies for the complicated setup, but there *is* actually method
> > behind my madness here!
>
> > I'm currently working to implement the Active Record pattern for
> > TclOO, modeled after the Ruby on Rails (RoR) implementation.  (http://
> > api.rubyonrails.org/files/vendor/rails/activerecord/README.html).
> > [...]

> There must be a good reason why most sophisticated organizations store
> their data in relational databases. My guess is that the data model is
> much more powerful than the OO model. Trying to equate the two is a
> hopeless pursuit. If anyone wants a good relational to OO model, try
> JDBC. For Tcl, AOLserver has ns_db, which represents row data as an
> ns_set. The key differences with OO is that correct relational models
> allow multiple columns with the same name and columns are ordered (of
> course the result rows are also structurally ordered). JDBC follows
> this model, most other OO systems do not.
>
> One key concept of OO is modeling. Model the data in a relational
> database, don't take shortcuts. One option is to offer multiple
> accessor APIs: one API covers the usual case when columns are
> referenced by name, the second accesses columns by their order in the
> query result. Only the second is guaranteed to return valid results,
> only the second represents the query result.

Regardless of whether you think the ActiveRecord model is valid (it
*does* address the issues you raise and I invite you to read the web
page above thoroughly), I would still like to know if it's possible to
create my own "new" method and still be able to call the
oo::object::new method. In particular, "new" is difficult because it
uses the name of the class used to determine which object to
instantiate ("[Model new]" creates a new instance of Model). Can that
be accomplished within the TclOO framework or must I choose different
method names?

David
From: tom.rmadilo on
On Apr 19, 1:13 pm, InetDavid <dav...(a)tower-mt.com> wrote:
> On Apr 19, 12:43 pm, "tom.rmadilo" <tom.rmad...(a)gmail.com> wrote:
>
>
>
>
>
> > On Apr 19, 10:38 am, InetDavid <dav...(a)tower-mt.com> wrote:
>
> > > Apologies for the complicated setup, but there *is* actually method
> > > behind my madness here!
>
> > > I'm currently working to implement the Active Record pattern for
> > > TclOO, modeled after the Ruby on Rails (RoR) implementation.  (http://
> > > api.rubyonrails.org/files/vendor/rails/activerecord/README.html).
> > > [...]
> > There must be a good reason why most sophisticated organizations store
> > their data in relational databases. My guess is that the data model is
> > much more powerful than the OO model. Trying to equate the two is a
> > hopeless pursuit. If anyone wants a good relational to OO model, try
> > JDBC. For Tcl, AOLserver has ns_db, which represents row data as an
> > ns_set. The key differences with OO is that correct relational models
> > allow multiple columns with the same name and columns are ordered (of
> > course the result rows are also structurally ordered). JDBC follows
> > this model, most other OO systems do not.
>
> > One key concept of OO is modeling. Model the data in a relational
> > database, don't take shortcuts. One option is to offer multiple
> > accessor APIs: one API covers the usual case when columns are
> > referenced by name, the second accesses columns by their order in the
> > query result. Only the second is guaranteed to return valid results,
> > only the second represents the query result.
>
> Regardless of whether you think the ActiveRecord model is valid (it
> *does* address the issues you raise and I invite you to read the web
> page above thoroughly), I would still like to know if it's possible to
> create my own "new" method and still be able to call the
> oo::object::new method.  In particular, "new" is difficult because it
> uses the name of the class used to determine which object to
> instantiate ("[Model new]" creates a new instance of Model).  Can that
> be accomplished within the TclOO framework or must I choose different
> method names?

Right, so just explain how to handle a row that has two columns with
the same name, and how do you enforce column order?

This is a simple thing, but very important. If you can't do these two
things, you haven't successfully represented/mapped a relation in/to
OO.

The link you provided does not address either of these two issues. I
assume that means failure. If you disagree, please provide an example,
not an API reference.


From: tom.rmadilo on
On Apr 20, 2:26 am, "Donal K. Fellows"
<donal.k.fell...(a)manchester.ac.uk> wrote:
> On 19 Apr, 20:43, "tom.rmadilo" <tom.rmad...(a)gmail.com> wrote:
>
> > There must be a good reason why most sophisticated organizations store
> > their data in relational databases. My guess is that the data model is
> > much more powerful than the OO model.
>
> I'd guess that you're a bit off-base there. Often, I'd expect to see a
> more prosaic foundation such as "We store data in the database because
> that's what we've always done". I'd argue that the additional power of
> a relational database comes in theory from the ability to support non-
> trivial ad hoc queries, and in practical terms the real bonus is that
> someone else (the DB vendor) has figured out how to perform ACID
> updates. (Atomic, Consistent, Isolated, Durable data handling is a
> good thing.)

Not going to disagree with off-base. But the reason large
organizations use relational databases is because of the ability to
normalize data and to query the data, producing new objects from the
base objects. ACID just deals with creating and maintaining data in a
consistent state. Most of the power is in dynamic querying. What
really screws up the relational to OO mapping is the dynamic query
language and the dynamic result table structure. Base tables insert/
update/delete work very well with object systems. In fact, it is very
simple to automate insert/update/delete operations when given the data
model. The big problem is select.

> > Trying to equate the two is a
> > hopeless pursuit. If anyone wants a good relational to OO model, try
> > JDBC.
>
> That's an interface to an SQL database, not a relational-object
> mapping.

Never claimed it was a mapping. You can map insert/update/delete, but
not select.

> For mappings in the Java world, look at things like EJB
> (especially Entity Beans). Most of the successful ORMs tend to be
> class-first though, using the class(es) to create the DB schema as
> that allows forcing things like unique column names.

The original schema must have unique column names for base tables, but
not so for derived tables or queries. Solving the base table interface
is not interesting, although it is important. Solving the select query/
result table interface is difficult.

> Object-Relational Mapping is not just about doing queries and getting
> the results back. It's about conceptually having the same model and
> instances in both the database and the object world.

Since queries dynamically create new objects, the OO model suffers.
Relational "objects" are constructed by the query.

> It's arguably the
> case that it is impossible in general, but there are significant
> subsets of the universe for which it is practical.

The universe includes all insert/update/delete queries on base tables,
plus most select queries on a single base table.

The above isn't quite true. Any time you have to deal with multiple
classes of users with different permissions on tables and columns, you
run into real trouble with direct relational to object mapping. You
need an intermediate mapping. Fortunately such a mapping can double as
an user interface definition. This still doesn't help with select
queries.