[LRUG] Comparable Null Objects

Duncan Stuart dgmstuart at gmail.com
Wed Jul 15 07:58:45 PDT 2015


Thanks Frederick and Rob

Defining to_date doesn't suffice: the <=> method on Date doesn't try and
coerce the argument into a date, which is why Date.today > Time.now fails,
even though Time responds to to_date.

If I were to define a coercion method, I think it would have to be on Date,
which feels wrong.

On 15 July 2015 at 13:21, Rob Isenberg <robisenberg at me.com> wrote:

> Hi Duncan, if you want your class to be comparable with other built-in
> objects, I think you need to implement any #to_* methods that make sense.
>
> I think you need to write a #to_date method which with then automatically
> be coerced when the comparison is done starting with a Date object.
>
> Sent from my iPhone
>
> On 15 Jul 2015, at 13:04, Duncan Stuart <dgmstuart at gmail.com> wrote:
>
> Sorry that last code snippet should be:
>
> def sort_by_expected_date
>   sort do |a, b|
>     if b.class = NoExpectedDate
>       1
>     else
>       a <=> b
>     end
>   end
> end
>
> On 15 July 2015 at 13:03, Duncan Stuart <dgmstuart at gmail.com> wrote:
>
>> Hi LRUG - hopefully an interesting little problem:
>>
>> I have an Event class which has an "expected_date" attribute.
>> Some events don't have an expected date, so like a good little OO
>> programmer i've created a Null object:
>>
>> class NoExpectedDate
>>   def to_s(format=:default)
>>     "Unknown"
>>   end
>> end
>>
>> This works great for printing the values, but when it comes to sorting
>> the list I of course get:
>>    ArgumentError: comparison of Date with NoExpectedDate failed
>>
>> If I include Comparable and define <=> then one comparison works, but the
>> other doesn't :
>>
>> class NoExpectedDate
>>   include Comparable
>>   def to_s(format=:default)
>>     "Unknown"
>>   end
>>   def <=>(other_date)
>>     1 # Treat it as after every other date
>>   end
>> end
>>
>> $ NoExpectedDate.new > Date.today
>> => true
>>
>> $ Date.today > NoExpectedDate.new
>> ArgumentError: comparison of Date with NoExpectedDate failed
>>
>> I think this is because Date's <=> method expects it's argument to be a
>> Date object or a number ("a numeric value as an astronomical Julian day
>> number"). I've tried defining to_i and to_r on NoExpectedDate, but no dice.
>>
>> Can I get NoExpectedDate to pretend to be a Date (like SimpleDelegator
>> lies about it's class)? Is that evil?
>>
>> I suppose I could always just define a method on Event to do this
>> particular sort, but that seems nasty for all sorts of reasons:
>>
>> def sort_by_expected_date sort do |a, b|
>>
>>     if b.class = NoExpectedDate
>>
>>       1
>>
>>     else
>>
>>       a <=> b
>>
>>     end
>>
>>   end
>>
>> end
>>
>>
>>
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> Archives: http://lists.lrug.org/pipermail/chat-lrug.org
> Manage your subscription: http://lists.lrug.org/options.cgi/chat-lrug.org
> List info: http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>
>
> _______________________________________________
> Chat mailing list
> Chat at lists.lrug.org
> Archives: http://lists.lrug.org/pipermail/chat-lrug.org
> Manage your subscription: http://lists.lrug.org/options.cgi/chat-lrug.org
> List info: http://lists.lrug.org/listinfo.cgi/chat-lrug.org
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lrug.org/pipermail/chat-lrug.org/attachments/20150715/3aa9ff03/attachment-0003.html>


More information about the Chat mailing list