From: tom.rmadilo on
On Apr 22, 1:26 am, "Donal K. Fellows"
<donal.k.fell...(a)manchester.ac.uk> wrote:
> On 21 Apr, 18:52, InetDavid <dav...(a)tower-mt.com> wrote:

> > As to the other discussion, I'm just going to ignore it since
> > ActiveRecord does *work* for Ruby on Rails just fine, in spite of
> > uninformed, contrary claims.  :-)
>
> I suspect that there are theoretical edge cases where it doesn't work,
> but production code can just ignore them as being irrelevant. ;-)

You want to know why Tcl isn't taken seriously? The above bullshit
should explain it.

You either model the details and succeed or you simplify and fail.

This point seems impossible to explain to pure programmers. A base
table is like a generic object. Most applications require subtyping of
these objects, so you need an additional layer of definition/mapping.

If anyone needs examples, ask me.

From: Donal K. Fellows on
On 22 Apr, 21:06, "tom.rmadilo" <tom.rmad...(a)gmail.com> wrote:
> 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.

You're not cynical enough. There's a *lot* of waste out there...

> ACID just deals with creating and maintaining data in a
> consistent state. Most of the power is in dynamic querying.

Yes, but that's not how a lot of people are using things. In
particular, the large group of people using ORMs tend to avoid the
real power. Also, a lot of database installations are optimized to not
handle ad hoc queries well. Yes, a relational database is overkill in
this situation; when did that ever stop a poor programmer?

> 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.

As long as you've got *some* control over the query, you can alias the
columns to ensure uniqueness of names in the result. That's all you
really need. (The aliases don't change the query, just the
interpretation of it presented in the result set.)

I've never heard of anyone desperate to make an ORM handle the results
of utterly arbitrary queries.

> 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.

That's a subtle thing to do well, especially when the accessing
application (i.e., the one with the object model) is serving multiple
users at once.

> This still doesn't help with select queries.

Do you mean the naming problem (a non-issue really) or something else?

Donal.
From: Donal K. Fellows on
On 21 Apr, 18:52, InetDavid <dav...(a)tower-mt.com> wrote:
> While I wish to override the behavior of "new" for my Model class, I
> also need to be able to instantiate objects from other classmethods,
> like the "find" method.  I'll look over both of your responses to see
> if they give me the clues I need, but for now I still don't see a way
> for [Model new] to call *my* "new" method while still letting the
> "find" classmethod in ActiveRecord::Base still create a new instance
> of Model by invoking the original "new".

I think it can be done and I've got a few (probably half-baked) ideas.
I just apologize that I've had too little time to write up a proper
informative example on how. Keep prodding me, please! (Perhaps this
would be a good thing for me to write for this year's Tcl papers...)

> I did notice something different in your example though.  Is "self
> method ..." a simpler syntax for defining a class (static) method?
> I've been using your classmethod proc from TclOO Tricks (http://
> wiki.tcl.tk/21595) but that looks much cleaner.  Time for some more
> experimentation!

OK, to explain it (in several steps):

oo::class Foo { ... blah ... }

is exactly identical to:

oo::class Foo
oo::define Foo { ... blah ... }

The second equivalence is between:

oo::define Foo {
self method bar ...
}

and:

oo::objdefine Foo {
method bar ...
}

Thus, what I was doing was declaring a method on the Example1 object
*itself*. TclOO, like XOTcl, allows methods to be defined on
instances. Really specific customization, and very useful for the sort
of thing you're trying to do.

I should also note here that despite having written it, I'm still
exploring the capabilities of TclOO. From time to time, I really
surprise myself as I come up with a new way to mix Tcl's capabilities
together...

> As to the other discussion, I'm just going to ignore it since
> ActiveRecord does *work* for Ruby on Rails just fine, in spite of
> uninformed, contrary claims.  :-)

I suspect that there are theoretical edge cases where it doesn't work,
but production code can just ignore them as being irrelevant. ;-)

Donal.
From: InetDavid on
On Apr 20, 12:56 am, "Donal K. Fellows"
<donal.k.fell...(a)manchester.ac.uk> wrote:
> On 19 Apr, 18:38, InetDavid <dav...(a)tower-mt.com> wrote:
>
> > 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?
>
> You're going to be subclassing oo::class (i.e., making metaclasses)
> and you're looking for [next] to use the superclass's implementation
> of the current method. Note that subclassing the class of classes is a
> technique that you might be not so used to (not all languages/object
> systems allow it).
>
> > 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
> > """.
>
> You've tried some interesting techniques there! Alas, none are
> correct. You've identified why for instances of a class (but you could
> use [oo::objdefine] - or [self method] in the definition - to create a
> method on the Model class object which lets you do it) but the reason
> why forwards don't work like that is that methods aren't commands. (It
> would have been nice if they were, but the internal signature required
> for implementation sanity doesn't fit.)
>
> Here's two things that *will* work.
>
>   oo::class create Example1 {
>      self method new {args} {
>         puts "making with customized class object..."
>         set o [next {*}$args]
>         puts "made $o in [self]"
>         return $o
>      }
>      constructor {} {
>         puts "This is [self]"
>      }
>   }
>   [Example1 new] destroy
>
>   oo::class create Metaclass {
>      superclass oo::class
>      method new {args} {
>         puts "making with metaclass..."
>         set o [next {*}$args]
>         puts "made $o in [self]"
>         return $o
>      }
>   }
>   Metaclass create Example2 {
>      constructor {} {
>         puts "This is [self]"
>      }
>   }
>   [Example2 new] destroy
>
> Donal.

Thank you for your reply, Donal.

I *did* slap myself on the forehead when I saw the reference to [next]
as I had forgotten that, but at the same time it doesn't completely
solve the problem.

While I wish to override the behavior of "new" for my Model class, I
also need to be able to instantiate objects from other classmethods,
like the "find" method. I'll look over both of your responses to see
if they give me the clues I need, but for now I still don't see a way
for [Model new] to call *my* "new" method while still letting the
"find" classmethod in ActiveRecord::Base still create a new instance
of Model by invoking the original "new".

I did notice something different in your example though. Is "self
method ..." a simpler syntax for defining a class (static) method?
I've been using your classmethod proc from TclOO Tricks (http://
wiki.tcl.tk/21595) but that looks much cleaner. Time for some more
experimentation!

As to the other discussion, I'm just going to ignore it since
ActiveRecord does *work* for Ruby on Rails just fine, in spite of
uninformed, contrary claims. :-)

David
From: InetDavid 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.)
>
> > 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. 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.
>
> 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. It's arguably the
> case that it is impossible in general, but there are significant
> subsets of the universe for which it is practical.
>
> Donal.

I will add here that in the case of Ruby on Rails, ActiveRecord makes
extensive use of reflection to map objects to the current database
schema. This means that as soon as a column is added to a table, an
accessor method is supported (via the equivalent of "method unknown")
in the model class.

In development mode this means doing frequently querying the database
for current table information with "SHOW FIELDS FROM `<tablename>`".
In production mode these checks are only performed on each table
*once*, requiring that the Rails server be restarted if the database
schema is changed.

This methodology makes writing your code significantly easier as you
don't often need to change your code if a table changes, unless of
course you are actually using the columns that are changed. If you
create a new row object and only set *some* of the column values,
ActiveRecord still sets the values for all columns.

ActiveRecord is probably the most powerful contributor to the growing
popularity of Ruby on Rails, though there are other great features of
RoR in addition.

David