Database applications and OOness

P

Pete Yadlowsky

Hi,

I'm a Perl -> Python -> Ruby convert and new to this mailing list.

I like Ruby very much except for one thing: all those "end" tokens scattered
everywhere. For my style of coding, they are superfluous and, in my opinion,
only serve to clutter the code. I very much like Python's indent blocking
style and would like to use it with Ruby. Indenting does everything I need it
to do in terms of establishing structure and enhancing readability. Once you
get used to this style (I've been using it for just about all languages and
for longer than Python has existed), delimiter tokens become unnecessary and
unwanted.

I'm sure the topic of Python-style blocking in Ruby has been brought up
before. Is there a general consensus on this in the community? Before I
totter off to write my own Ruby preprocessor, does such a thing already
exist? Thanks.
 
X

Xavier Noria

I like Ruby very much except for one thing: all those "end" tokens
scattered
everywhere. For my style of coding, they are superfluous and, in my
opinion,
only serve to clutter the code. I very much like Python's indent
blocking
style and would like to use it with Ruby. Indenting does everything I
need it
to do in terms of establishing structure and enhancing readability.
Once you
get used to this style (I've been using it for just about all
languages and
for longer than Python has existed), delimiter tokens become
unnecessary and
unwanted.

I'm sure the topic of Python-style blocking in Ruby has been brought up
before. Is there a general consensus on this in the community? Before I
totter off to write my own Ruby preprocessor, does such a thing already
exist? Thanks.

As a simple workaround, I wrote this little code to hide ends in a row
and collapse their lines in Emacs. Useful for reading but not for
writing:

-- fxn

(defvar ruby-ends-hide-regexp-overlays nil "")
(make-variable-buffer-local 'ruby-ends-hide-regexp-overlays)

(defun hide-ruby-ends ()
"Hide Ruby end keywords."
(interactive)
(let ((regexp "^\\(?:[ \t]*\\(?:end\\|}\\)\n\\)+"))
(save-excursion
(goto-char (point-min))
(while (and (< (point) (point-max))
(re-search-forward regexp nil t))
(let ((overlay (make-overlay (match-beginning 0) (match-end
0))))
(overlay-put overlay 'invisible 't)
(overlay-put overlay 'intangible 't)
(overlay-put overlay 'before-string "")
(overlay-put overlay 'after-string "")
(setq ruby-ends-hide-regexp-overlays
(cons overlay ruby-ends-hide-regexp-overlays)))))))

(defun unhide-ruby-ends ()
"Unhide Ruby end keywords."
(interactive)
;; remove all overlays in the buffer
(while (not (null ruby-ends-hide-regexp-overlays))
(delete-overlay (car ruby-ends-hide-regexp-overlays))
(setq ruby-ends-hide-regexp-overlays (cdr
ruby-ends-hide-regexp-overlays))))

(defvar ruby-ends-are-hidden nil "")
(make-variable-buffer-local 'ruby-ends-are-hidden)

(defun toggle-ruby-ends ()
"Hide/unhide Ruby end keywords."
(interactive)
(cond (ruby-ends-are-hidden (unhide-ruby-ends)
(setq ruby-ends-are-hidden nil))
(t (hide-ruby-ends)
(setq ruby-ends-are-hidden t))))
 
D

David Tillman

Pete said:
I'm a Perl -> Python -> Ruby convert and new to this mailing list.

Myself also.

ActuallY I am a C -> PERL -> C++ -> Scheme -> LISP -> Python -> Ruby
convert.
I like Ruby very much except for one thing: all those "end" tokens scattered
everywhere. For my style of coding, they are superfluous and, in my opinion,
only serve to clutter the code.
<snip>


i know what you mean any useless syntax that provides extra visual
clues is a total waste of typing interpreters dont need them and
neither should humans


Almost content free... Nothing to see here, move along people.

-dave
 
T

Tim Bates

1. Regarding subtle differences in query syntax: If I had a
comprehensive list of things to look out for I could write tests
against them. I imagine most of them would be easy to fix.

Okay. I don't have a comprehensive list, I'd imagine most of them would
be found through testing. The ones I know of off the top of my head are:

MySQL's "RLIKE" and "NOT RLIKE" correspond to PostgreSQL's ~ and !~
operators.

PostgreSQL doesn't like "OFFSET x,y" syntax, it insists upon
"OFFSET x LIMIT y".

I don't know what the SQL standard says in either of these cases.
2. Regarding transactions: I haven't done this, but I don't imagine it
would be difficult. A Ruby-like style for it might be something like:

objectStore.runTransaction {
account1743.balance -= 100
account1743.commit
account329.balance += 100
account329.commit
}

That's exactly how DBI and Vapor deal with it. That would be ideal.
.... and then I'd just write an ObjectStore#runTransaction method like:

def runTransaction
beginTransaction
yield
commitTransaction
end

def runTransaction
@dbhandle.transaction do |dbh|
yield
end
end

Assuming that your DBI::DatabaseHandle is called @dbhandle.
right? One question: When using DBI/Postgres, do you issue begin and
commit commands as separate lines, or do they need to be mixed in with
your SQL strings?

You don't need to worry about that, DBI handles it for you. ;) But just
FYI, there's a "BEGIN;" SQL statement, a "COMMIT;" SQL statement and a
"ROLLBACK;" SQL statement.
The more I think about it, the more this sort of interface makes me
nervous. Maybe Criteria users can pipe in here with their perspective,
but it seems to me that once you tell the programmer that she can
write code like

(tbl.bday == "2003/10/04").update:)age => tbl.age + 1)

then it's natural for her to assume she can write the opposite:

(tbl.bday != "2003/10/04").update:)age => tbl.age + 1)

.... but the second case will fail, and probably it will fail quietly
since (I think) there's no way for a Table object to detect negation
like that.

It does fail, and it doesn't do it quietly either; watch this:

irb(main):001:0> require 'criteria/sql'
=> true
irb(main):002:0> include Criteria
=> Object
irb(main):003:0> tbl = SQLTable.new('people')
=> #<Criteria::SQLTable:0x400ea780 @criterion_type=Criteria::SQLCriterion,
@_typemap=nil, @table="people">
irb(main):004:0> (tbl.bday == "2003/10/04")
=> (== :bday "2003/10/04")
irb(main):005:0> (tbl.bday == "2003/10/04").update:)age => tbl.age + 1)
=> "UPDATE people SET age = (people.age + 1) WHERE (people.bday = '2003/10/04')"
irb(main):006:0> (tbl.bday != "2003/10/04")
=> false
irb(main):007:0> (tbl.bday != "2003/10/04").update:)age => tbl.age + 1)
NoMethodError: undefined method `update' for false:FalseClass
from (irb):7
from :0

So basically it just gives up. :) This is because Ruby translates it to
!(tbl.bday == "2003/10/04")
and (tbl.bday == "2003/10/04") is true, therefore the expression
evaluates to false. There is really no way around this other than
altering the query syntax, as you suggest next.
I'm starting to think I'd want a query syntax that trades
some cleverness for clarity, something like maybe

(tbl.bday.equals( "2003/10/04" ) ).update:)age => tbl.age + 1)
(tbl.bday.equals( "2003/10/04" ).not! ).update:)age => tbl.age + 1)

Or maybe that's trading one sort of ugliness for another. I'm not sure
yet.

It'd need some more thought. Once you start doing this sort of thing, I
start wondering why I shouldn't just write raw SQL, because this is
looking a lot like SQL crammed into Ruby syntax, rather than an abstract
Ruby query-specification syntax which happens to translate to SQL rather
nicely, which is what Criteria was in the first place. I'm of the
opinion that if I'm going to write something that close to SQL, I may as
well write SQL itself. If I'm going to write Ruby, I want to think in
Ruby, not SQL. I want to write it without stopping to think how this
translates to SQL and whether that's really what I want.
One more point of disclosure in the interest of not wasting your time,
Tim: Lafcadio does almost no handling of group functions yet. I
suspect it wouldn't be too difficult to add on, but I haven't thought
about the problem much yet so I can't really be certain of it.

Again, the trick would be to make it Ruby, rather than just tacking SQL
group functions onto it like Criteria does by accepting literal SQL
strings at the moment.

I very much agree with your earlier comment that those libraries which
continue to exist in this problem domain are going to have to deal with
all these issues sooner or later. I think Lafcadio and Vapor have many
of the answers to one aspect of the problem, and Criteria has answers to
another; a marriage or cross-pollination of the two would make a lot of
sense.

Tim Bates
 
B

Bret Jolly

Pete Yadlowsky said:
I'm a Perl -> Python -> Ruby convert and new to this mailing list.

I like Ruby very much except for one thing: all those "end" tokens scattered
everywhere. [...]
I'm sure the topic of Python-style blocking in Ruby has been brought up
before. Is there a general consensus on this in the community? Before I
totter off to write my own Ruby preprocessor, does such a thing already
exist? Thanks.

I also followed the Perl -> Python -> Ruby route, and
I'm afraid I have to tell you that the Ruby way is the
right way. Python's syntactically-significant
indentation is partly responsible for the reputation
Python has of being "executable pseudocode" which has
lured so many unwary programmers into its coils; but
much I as liked it in my Python days, I know see that
it was a mistake.

Consider what syntactically-significant indentation
means in the context of a vigorous hacking session in
emacs or vim. Hack, hack, hack. Gotta refactor:
cut this here, paste it there...oops! Now the indentation
is all wrong. Pretty soon you find that you are spending
time and mental energy horsing around with indentation
(especially if some of your code contains tabs). This
is not programmer heaven.

Furthermore, syntactically-significant indentation
increases the risk of errors, for several reasons.
Explicit block-termination gives the editing session
valuable redundancy. If you screw up your cutting and
pasting during a Ruby refactorfest, the editor will
make this obvious when you tell it to re-indent. And
if you don't notice this (maybe you are programming
drunk), you'll notice it when the program fails to run.
But in an equivalent Python refactorfest, the editor
will not catch the problem by re-indenting, and the
syntax is more likely to be legal even after your blunder.
The program might run, but run incorrectly (this is bad).

I should have been tipped off by the fact that when I
had a Python block which was more than a screenful, I
would end it with an end comment to make the end-of-block
visible, e.g.:

if foo:
# 2 screenfuls of code
# end if

With a little more Ruby experience, I think that you
too will see that the Ruby way is the right way, and
Python will seem like a bad dream.


Happy Rubying! Regards, Bret
 
F

Francis Hwang

< much Lafcadio-specific discussion snipped >

Tim, everything we're talking about here makes sense to me. And the
only reason it's not in Lafcadio now is only because I haven't had the
time to do it, not 'cause I object on principle to including
transactions or grouping functions or whatever. So if you feel like
helping to add this to Lafcadio I'd love to help you help the code.
(Or, you could choose to roll your own, which I wouldn't at all take
personally given the idiosyncratic nature of Lafcadio at parts.) I'd
promise you something more substantive than that, but, again, there's
that chronic busy-ness to tend to ... Maybe we can talk more specifics
over email if you want.

The discussion below, though, I think would benefit from having as
many voices as possible. At RubyConf, I framed the problem like this:
We may bitch about SQL, but it's actually an extremely robust,
powerful, and concise syntax for dealing with RDBMS ... if we want to
mimic it all in Ruby, what is the best way to do it?
It'd need some more thought. Once you start doing this sort of thing, I
start wondering why I shouldn't just write raw SQL, because this is
looking a lot like SQL crammed into Ruby syntax, rather than an abstract
Ruby query-specification syntax which happens to translate to SQL rather
nicely, which is what Criteria was in the first place. I'm of the
opinion that if I'm going to write something that close to SQL, I may as
well write SQL itself. If I'm going to write Ruby, I want to think in
Ruby, not SQL. I want to write it without stopping to think how this
translates to SQL and whether that's really what I want.

Only Criteria query inference isn't really Ruby. You can see the
relation to Ruby, but it's barely the same thing. It's like the
difference between English and Creole. Let's take "&", which you use
in Criteria because you can't override "&&". Only it has a different
operator precedence and

t.foo > t.bar & t.baz < t.quux

will parse differently from what you might expect so you have to
remember to use

(t.foo > t.bar) & (t.baz < t.quux)

instead. And it's significant that in every other context, nobody
types "&" when they want "boolean AND". They type "&&" instead,
perhaps because "&&" always means "boolean AND" and "&" can mean set
intersection (for Arrays) and bitwise AND (for Fixnum).

I don't mean to beat up on Criteria. It seems to me that given the
sort of design Ryan's pursuing, and the way Ruby introspection works,
he's done as well as anybody could do. Criteria seems like it's very
well-done, and it's obviously useful since there are a lot of people
using it. Since I haven't had the chance to use it for anything
serious, I guess I don't have a clear sense of what it's like to use
Criteria. So I hope everybody reads what I'm posting not as a
criticism of Criteria but an attempt to understand how it works in
your head when you use it.

Here's my concern: Seems to me than when you have a syntax that looks
_sort of_ like normal Ruby, but is different in all these tiny subtle
ways, using it might involve a lot of "mental housekeeping" about why
things work and don't work. In particular, the idea of teaching a
moderately skilled programmer how to use Criteria is pretty daunting.

Is this not a problem for Criteria users? Am I just worrying too much?

Francis
 
R

Ryan Pavlik

Here's my concern: Seems to me than when you have a syntax that
looks _sort of_ like normal Ruby, but is different in all these tiny
subtle ways, using it might involve a lot of "mental housekeeping"
about why things work and don't work. In particular, the idea of
teaching a moderately skilled programmer how to use Criteria is
pretty daunting.

Well, for me, it comes down to Criteria---albeit not perfect,
especially in the ways you mentioned---being better than embedding SQL
text into Ruby. Secondly, it's an abstraction, which means primarily
it doesn't necessarily generate SQL, which is useful (at least in
theory).
Is this not a problem for Criteria users? Am I just worrying too
much?

Of course "it's less bad" doesn't answer your question. I'd say you
only need to be especially aware of 2 things to use Criteria:

1) Method operators (&, |, etc) vs syntax operators (&&, ||, etc)
2) Operator precedence

The latter isn't really so much of an issue either, at least for
me... I tend to explicitly specify parens anyway, just because I like
the way it looks on the screen.

This isn't to say Criteria isn't tricky. To be honest, because of the
way it wraps back into the language, there are a lot of weird things
that you can do, and a lot of things that happen "magically". I don't
think anyone has to wrap their head around the whole thing to use it,
though. (At least, I hope not, because I use it, and I don't always
see all the possibilities. ;)

I can't come up with a better way to integrate abstract query
notation, though. I've tried other various things and they're all
uglier. That's not to say someone smarter can't come up with
something simpler and more flexible. They just need to implement it
for us. ;-)
 
A

amnesiacx

Python's syntactically significant white space is a bore, I don't mind
the "end" delimeter at all, although a different word may have been
nice, say... PERL ?
 
G

GGarramuno

Pete Yadlowsky said:
Hi,

I'm a Perl -> Python -> Ruby convert and new to this mailing list.

I like Ruby very much except for one thing: all those "end" tokens scattered
everywhere. For my style of coding, they are superfluous and, in my opinion,
only serve to clutter the code. I very much like Python's indent blocking
style and would like to use it with Ruby. Indenting does everything I need it
to do in terms of establishing structure and enhancing readability.

Noooooo! If you really believe that's a language feature, you really
should stick with python.

My experience is similar in scripting languages:
Basic->Perl->TCL->Perl->Python->Ruby with C/C++/assembler mixed in
along the way.

Over the past 2 years, at a previous employer (one of python's oldest
companies using the language in the world, which is quoted in the back
of Programming Python), I dealt with LOTS of python code previously
written by other people.
I came to the conclusion that whitespace as a delimiter is a neat
idea, but it truly works only when you wrote that code yourself ( I
also came to the conclusion that python was an extremely powerful
language but that being a legible language down the line is also a
doubtful statement, if you ask me).

The truth is that when picking other people's code, whitespace as a
delimiter was a complete and absolute evil.

Albeit I was afraid that whitespace as a delimiter would create all
sort of problems when someone tabulated something wrong, the truth is
that I can only recall one occasion in over 2 years when this happened
and lead to a somewhat hard to track bug. I was surprised about it
working so well.
But there were other issues....

Whitespace as a delimiter did act as a way for a lot of people to
avoid learning the language, thou. Why? Because it FORCES people to
learn a good text editor a la emacs or vi. Surely, not a bad idea,
but nobody wants to be learning both things at the same time. You
would not believe how many newbies use things such as notepad, jot or
something silly like that for editing code. Those people plain and
simply could never learn a white space aligned language.

The real issues I saw that turned me off against python's syntax
overall was when dealing with code longer than a page. Sure, in a
perfect world, refactoring would be a way of life and not a single
routine would ever take over 80 lines. In reality, it does not happen
(particularly, when the code is very dynamic and is being updated by
multiple hands). I also found it hilarious when I saw code (sometimes
written by people with more python experience than myself) with
comments of the form "# end loop1" to indicate where each block ended.

The second issue that turned me off against that syntax was when
dealing with code generated on the fly (for later eval). As an
exercise, when I started learning python, I tried doing something
similar to what I did now with ruby. I picked Damian Conway's
Getopt::Declare and tried porting it from perl. I literally pulled my
hair out and after two weeks I abandoned the project. Part of this
was the ugly regex of python, but another issue was having to
prototype code on the fly that ALSO had to follow tabulation syntax in
order to eval properly. It was a nightmare experience.
With that, I became convinced that beautifying the code should never
be a language syntax feature.

A third issue that is silly but could never get over was editing
python and how much typing was needed because of ws. An editor
dealing with python can do two things. It can try to be smart and
tabulate automatically for you (so you type if XXX: and then when hit
enter, you are inside the if block). This works badly for me as many
times I write conditions as stubs which I later fill in so the
automatic tab was more of a headache than a benefit. The othre
alternative is that the text editor does not tabulate automatically,
in which case you end typing more in the end (sure, just tabs/ws but
still more characters).

Personally, I'd like to see ruby use {} for normal blocks a la perl or
C, too, but I will not ask for that it. It would indeed create more
headaches for the parser and even for the user for still keeping the
distinction between blocks, too. So... I'd rather set a hotkey like
F1 to enter "end" for me with a macro and do it all as a single key
and less typing.

For all the reasons above (plus regex, plus python's not that great
OO, plus its lack of speed, etc), I started looking for a better
language.
Only after a week of using ruby (with its relatively poor docs in
comparison to perl or python), I already did something I could not do
as a newbie to either language.
I have already fallen head over heels for ruby.

As some previous poster said succintly before....
ruby with whitespace as a block delimiter will also be a ruby without
me.
 
G

gabriele renzi

il Thu, 8 Jan 2004 09:50:14 +0100, "Robert Klemme" <[email protected]>
ha scritto::

What exactly is the difference between the "shared and abstract ruby/DBMS
api" and DBI? IMHO DBI is exactly an abstract DBMC API, albeit only for
relational databases. Do you want to unify the different SQL dialects?
Or do you want only certain things unified, e.g. date and time formats
(like JDBC tries with its escape sequences)?

actually, I meant having at least a JDBC like interface, or, what in
python is the DB-api (I suppose).
I mean, if you have to connect to various db you may find:

# first find in google for each dbms
PGconn.connect "localhost", 5432, "", "", "test1"
ORAconn.logon "foo", "bar", "db"
Mysql.new host, user, passwd
Interbase.connect database,username,password,charset


Now, I know different dbms have different features, but ate least some
convention on a basic set of available methods would be good.
If we, as a community, could agree on a general dbms interface (dbi
fits well to me :) hat would be better than a separate wrapper
package.

ATM, Joe De Veloper has to choose beetween dbi-api, DBMS-foo api,
DBMS-bar api. Then he have to get DBMS-(foo|bar) api, dbi wrapper,
and finally start coding.

With a common api Joe just download a binding, find an already common
and documented interface, and start coding.
Then if he want to switch to DBMS-bar he could have (potentially)
working code without the need for changes.

Obviously just in a ideal world :)
 
D

David Heinemeier Hansson

I've build an implementation of Martin Fowler's ActiveRecord pattern
[1] with support for single-table inheritance [2]. It's designed with
the notion of "Convention Over Configuration", which basically means
that you follow a set of naming conventions to get a bunch of behavior
for free. Best to show with an example:

CREATE TABLE posts (
id int(11) unsigned NOT NULL auto_increment,
title varchar(255),
body text,
posted_on datetime,
PRIMARY KEY (id)
)

CREATE TABLE comments (
id int(11) unsigned NOT NULL auto_increment,
post_id int(11) unsigned NOT NULL,
body text,
PRIMARY KEY (id)
)

class Post < ActiveRecord
def comments
Comments.find_all "post_id = #{id}"
end

protected
def before_create
self.posted_on = Time.now
end

def before_destroy
Comments.destroy_all "post_id = #{id}"
end
end

class Comment < ActiveRecord
end

The code above shows a couple of things. First, there's no build-in
mapping for foreign key object relations (I had to make Post#comments
myself). Second, much of the behavior of the ActiveRecord can be
customized through callback hooks, like before_create (which tellingly
is called just before a row is created in the database) and
before_destroy. Third, "Post" automatically match up with the "posts"
table -- this behavior can be overwritten for things like
Person/people.

Anyway, some usage examples:

post = Post.new
post.title = "My new post"
post.body = "Active Records are easy"
post.save # since the post has no id, a INSERT-sql statement is executed

print post.id # prints the auto_id assigned by MySQL
print post.posted_on # prints the time of creation

post.title = "I've changed"
post.save # an id exists, so an UPDATE-sql statement is executed

post.attribute_that_doesnt_exist # Throws a NameError exception

# Objects can also be initialized with a hash, which is especially
convenient
# in web-apps that can just pass on the POST-parameters
first_comment = Comment.new({ "body" => "hello world", "post_id" =>
post.id })
first_comment.save

second_comment = Comment.new({ "body" => "hello world", "post_id" =>
post.id })
second_comment.save

print post.comments.length # prints 2
post.comments[0].body == first_comment.body # true

...and then there's a wide range of class/table-level methods, like:

Comment.update_all "body = 'all are changed'"
Comment.find(1).body == Comment.find(2).body # true (find uses SELECT,
btw)

print Comment.count # prints 2

post_with_comment = Post.find_by_sql(
"SELECT post.*, comment.body as comment_body " +
"FROM posts LEFT JOIN comments ON posts.id = comments.post_id " +
"ORDER BY comments.id DESC"
)

post_with_comment.comment_by # will print the body of the last comment

I think that's the basics. On top of that, there's support for simple
inheritance, like Company < ActiveRecord, Firm < Company, Client <
Company, which does correct type instantiations. There's also
validation support with error reporting -- think automatic form
validation from Strut's ActionForm[3] classes but on the model instead
of controller.

Caveats:
* Id generation is tied to MySQL's autoID functionality, which
currently binds it to MySQL -- but through use of DBI.
* No build-in transaction support

I've used a similar design in a couple of PHP web-apps and it has
worked very well. I'm currently finishing up a Ruby web-app called
Basecamp for 37signals[4] that uses this all the way through.

I plan on releasing this as soon as I've wrapped up Basecamp, but if
anyone is interested now (which means little documentation besides
inline comments and unit tests), I could easily package up a version.

[1] http://www.martinfowler.com/eaaCatalog/activeRecord.html
[2] http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
[3]
http://jakarta.apache.org/struts/userGuide/
building_controller.html#action_form_classes
[4] Sneak peak:
http://www.37signals.com/svn/archives/000505.php?29#comments
 
G

gabriele renzi

il Sat, 10 Jan 2004 08:28:50 +0900, David Heinemeier Hansson
I've build an implementation of Martin Fowler's ActiveRecord pattern
[1] with support for single-table inheritance [2]. It's designed with
the notion of "Convention Over Configuration", which basically means
that you follow a set of naming conventions to get a bunch of behavior
for free. Best to show with an example:
just two things:

the auto_id functionality may be achieved with SERIAL type in standard
sql, I suppose, or at least as a stored procedure. Am I wrong?.
Maybe you could write various driver for various db :)

did you see SPL on RAA ? it adds automagic persistence to objects via
a mixin, and it seem to me that it's really similar to your design
 
A

Aredridel

I've build an implementation of Martin Fowler's ActiveRecord pattern
[1] with support for single-table inheritance [2]. It's designed with
the notion of "Convention Over Configuration", which basically means
that you follow a set of naming conventions to get a bunch of behavior
for free. Best to show with an example:

Whoa, me too -- I came up with it while coding an MVC-structured web app
this week. My code works like so:

class Foo < SQLObject
key_field :id
field :name
field :amount
field :date
field :quantity
calculated_field: total
end

and there's a get, put & find method. field defines accessors for the
values, and sets up an array of fields in the class instance.

The table that this comes from is defined to be class.name.lower+'s' --
overridable by overriding the class' table method.

It works well for me -- it hides enough of the SQL to be "OO enough" for
me, and lets me use inheritance to show relation.

Ari
 
I

Ian Macdonald

I like Ruby very much except for one thing: all those "end" tokens scattered
everywhere. For my style of coding, they are superfluous and, in my opinion,
only serve to clutter the code.

They are not superfluous. You need a tangible block delimiter in order
to be able to chain methods that take blocks. Take, for example, the
following Ruby code:

foo = %w(f e d c b a)
foo.map do |x|
x = rand(10).to_s + x
end.sort

=> ["2b", "2c", "4f", "5a", "5e", "6d"]

In Python, there's no delimiter to signify the end of the block, so you
can't chain the output of methods that take blocks onto other methods.
In the above case, chaining the map to the sort can't be done.
I very much like Python's indent blocking style and would like to use
it with Ruby. Indenting does everything I need it to do in terms of
establishing structure and enhancing readability.

But not in terms of language functionality.

Ian
--
Ian Macdonald | "Absolutely nothing should be concluded
System Administrator | from these figures except that no
(e-mail address removed) | conclusion can be drawn from them." (By
http://www.caliban.org | Joseph L. Brothers, Linux/PowerPC Project)
|
 
M

Martin Hart

I don't know. Probably an array of arrays or an array of hashes - which,
I know, is exactly what DBI would return for such a query. The point I'm
trying to make is I'd like the system to be able to handle this sort of
query _as_well_as_ the "SELECT * FROM table WHERE property = ?" type
return-a-list-of-objects query. I don't know of any system that can do
that, or even if it could be done neatly. Possibly such a system would
have to accept two sorts of query and handle both separately, but that
introduces its own ugliness.

forgive me for jumping in late in this thread...
I have recently been working on a persistence layer for our product. After
spending some time looking through the projects available on RAA I was not
entirely satisfied with any of them - so we rolled our own that meets our
current needs

I can do things like:

allPeopleAsAnArrayOfPersonObjects = store.get(Person) # select * from persons
peopleOlderThan30 = store.get(Person, :age, :>, 30) # select * from persons
where age > 30
peopleBetween30And60 = store.get(Person, :age, :>, 30, :age, :<, 60) # select
* from persons where age > 30 and age < 30
or - store.get(Person, :age, :between?, [30, 60])
peopleWithNameStartingWithFre = store.get(Person, :name, :=~, "Fre") # using
the =~ operator is misleading here - it currently does "LIKE '#{arg}%'" :)
...yada yada...

The store object takes care of creating an SQL query. While the interface is
still pretty ugly, it sure beats embedded sql code everywhere, and is less
verbose.

The code only does the bare minimum to satisfy my needs at the moment and is
being actively developed, but there is capability for:
* relationships between tables (although i do make assumptions about how
tables are related). For example, if a Widget contains a single Part, then
we assume a table of widgets and a table of parts - where the widget table
has a "part-id" field When saving, we save the part, then the widget. If a
widget contains an array of parts then the relationship is reversed - the
part table has a "widget-id" field, etc etc.
* returning data as arrays of hashes and/or as objects.
* arbitrary query execution using get(field, operator, value(s)) - although
this is fairly limited at the moment.

I have avoided the issue of joining tables when running queries - we simply
create a view which joins the tables as required and then run a query on
that.

While what we have done is certainly not robust enough - nor generic enough
for general purpose use, I'd be happy to post some (barely) working code if
anybody is interested.

Cheers,
Martin

--
Martin Hart
Arnclan Limited
53 Union Street
Dunstable, Beds
LU6 1EX
http://www.arnclanit.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,792
Messages
2,569,639
Members
45,348
Latest member
RoscoeNevi

Latest Threads

Top