Jamey Cribbs
3/4/2006 6:04:00 PM
Jamey Cribbs wrote:
> dblack@wobblini.net wrote:
>
>> Hi --
>>
>> On Sun, 5 Mar 2006, James Edward Gray II wrote:
>>
>>> I'm examining Kirbybase for use it a project and was surprised to
>>> find this bit of code in it:
>>>
>>> #---------------------------------------------------------------------------
>>>
>>> # NilClass
>>> #---------------------------------------------------------------------------
>>>
>>> class NilClass
>>>
>>> def method_missing(method_id, *stuff)
>>> return nil
>>> end
>>> end
>>>
>>> This has been a popular discussion lately, but I just don't think
>>> loading a database library should fundamentally change the
>>> language. ActiveRecord doesn't hack NilClass and we seem to do okay
>>> with that. Why can't the above example just be coded as:
>>>
>>> select { |r| r.speed and r.speed > 300 }
>>>
>>> or:
>>>
>>> select { |r| r.speed > 300 rescue false }
>>
>>
>>
>> Or, depending on circumstances: r.speed.to_i > 300. I would ...
>
>
> Thanks very much for the feedback on my overriding
> NilClass#medthod_missing in KirbyBase. I don't think the three
> examples shown above would really be acceptable, because, could you
> imagine having to do this for every query where there was a chance
> that a #method_missing could be thrown? I think that would get old
> very fast.
>
> However, the last example does give me an idea. I'm going to take a
> look at the KBTable#select method and see if I can wrap the query
> processing logic in a begin/rescue block. It may be as simple as what
> David shows here, have the rescue return false. The problem I can see
> is when there is an OR condition in the block, i.e.:
>
> #select { |r| r.speed > 300 or r.range < 900 }
>
> Now, here's a *very* simplified version of KBTable#select, with a
> proposed adding of a begin/rescue block around the query instead of
> the current redefining of NilClass#method_missing:
>
> def select(&query_block)
> valid_matches = []
> table_records.each do |table_record|
> begin
> if query_block(table_record)
> valid_matches << table_record
> end
> rescue NoMethodError
> end
> end
> end
>
> Now, lets say we are looping through the table records and we get to a
> record where :speed is nil and :range is 800. According to the query
> block, this record should qualify as a valid match. But, if I don't
> override NilClass#method_missing to return fasle, but, instead, try to
> catch it with a begin/rescue block like I show in the code above, the
> record will *not* be added to valid matches. The problem with the
> code above is that I can't get granular enough. There is no way to
> get inside the query block and put a begin/rescue around *each*
> condition within the block.
> If I could get enough info about the calling method, when I'm inside
> NilClass#method_missing, then maybe I could conditionally return a
> false only when it was apparent that the #method_missing exception was
> raised in KBTable#select. But, the arguments passed into
> #method_missing are the symbol of the method, in this case :> and an
> array containing the arguments passed to the missing method, in this
> case [300]; not enough info for me to determine if this came from
> KBTable#select.
>
> I would be very interested in any suggestions, ideas, or feedback on
> this issue.
Hey, I think I will just respond to myself with a suggestion. :-)
What has been kicked around when this question has come up before is for
me to create something like a NULL class and use this to designate a
null value in the database, instead of using nil. This would take care
of having to override NilClass#method_missing. It would bring up a few
other problems, namely, what if someone wants to store the string value
NULL in a field. But I imagine these could be overcome.
If this is indeed a really big issue (meaning KirbyBase's overriding of
NilClass#method_missing), then I could get to work on this. Thoughts?
Jamey