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.

Jamey