Stefano Crocco
3/7/2008 3:12:00 PM
Alle Friday 07 March 2008, coigner ha scritto:
> Asking for ideas here but let me preface...
>
> There's an application with a sqlite3 database that I'm building Ruby
> classes and methods for accessing. ActiveRecord was close but no cigar
> because I have no control over the database and there are quirks in there
> I want to "hide". Besides, I'm still newish to Ruby and want the exercise
> of doing it myself even at the risk of re-inventing the wheel. <g>
>
> Okay so tables are objects and rows are objects. I have a table class and
> a row class and specific tables and rows inherit from them. At the end,
> you get nice little methods like:
>
> table.find(some_search_criteria)
>
> that returns an array of row objects.
>
> Over time, as I've worked on this and picked up more on Ruby, I've been
> moving more things up into the table superclass. Noticing as I've gone
> along that a great deal of code was identical in the subclasses. I'm
> actually down to something fairly simple that takes the array of records
> (an array of hashes actually) sqlite returns and "packages" them into row
> objects then returns them.
>
> This code is pretty much identical in all cases *except* that the row
> objects are different. That is, something like this in the subclass:
>
> def find(criteria)
> results = []
> do_find(criteria).each { |res|
> results << Transaction.new(res)
> }
> return results
> end
>
> "do_find" being inherited and containing all the contortions and hoop
> jumping that results in a SQL statement from the "criteria".
>
> The only difference now between the different subclasses is the line:
>
> results << Transaction.new(res)
>
> Such as, say there's a table for "accounts" then the line is:
>
> results << Account.new(res)
>
> The table classes are plural (rather Railsish I guess <g>) of the row
> classes. Transaction being the row class, Transactions being the table
> class, etc.
>
> So it occurs to me that deriving the row class from the name of the table
> class is trivial. So I could generalize this all even further if I could
> figure out a way to create a new row object of the class that is singular
> of the table class.
>
> Having bopped about Ruby a while now, I have a sneaking suspicion there's
> a way to do this. If I "self.class" in the superclass' code, I'm getting
> the name of the table instance ("Transactions" for instance). I can...
> what's the word... "singularize" (?) it and have "Transaction" so I know
> the name of the row class I need to instantiate.
>
> But there I'm stuck. I have the name of the class as a string but that
> doesn't do me any good. I keep thinking (and have been digging through
> several Ruby books but I'm not tumbling to this yet) that there's some
> way to do something sort of:
>
> results << magical_thing_here.new(res)
>
> Where "magical_thing_here" takes that string and lets Ruby know I mean
> "this is a name of a class".
>
> What am I missing?
>
> I mean, besides a lot more experience with Ruby. <G>
You want Kernel.const_get. As the name suggests, it takes a string and returns
the value of the constant with that name. For instance:
class C
end
Kernel.const_get('C').new
=> #<C:0xb7c55064>
If your classes are defined top-level, that's all you need. If they're defined
inside a module, you need to call const_get for that module:
module M
class C
end
end
M.const_get('C').new
I hope this helps
Stefano