Is there an easy way (i.e. using the spaceship operator) to define comparison in Ruby based on two different attributes? I.e. If I have a class that contains two attributes, attr1 and attr2, is there a Rubyesque way of comparing two instances of this class on attr1, and if they're equal then compare them on attr2?
This is an easily extendible (to more attributes) way:
def <=>(other)
[self.attr1, self.attr2] <=> [other.attr1, other.attr2]
end
The whole point of the comparable mixin is to provide a definition for the spaceship (comparison) operator. So if you want to do a comparison across two attributes, then do it. Here's an overly verbose example:
def <=>(obj)
comparison = self.attr1 <=> obj.attr1
if comparison == 0
return self.attr2 <=> obj.attr2
else
return comparison
end
end
Obviously the above assumes attr1, and attr2 both have definitions for the spaceship operator. As well you'll need to determine what constitutes greater than, and less than, which is likely a bit difficult across two attributes. Which suggests that comparable may not be the proper code for your scenario.
def <=>(obj)
self.attr1 <=> obj.attr1 == 0 ? self.attr2 <=> obj.attr2 : self.attr1 <=> obj.attr1
end
a <=> b :=
if a < b then return -1
if a = b then return 0
if a > b then return 1
if a and b are not comparable then return nil <= I wanted this
Steenslag's solution wasn't giving me the nil when 'not comparable'.
Added extra line for coping with 'not comparable':
def <=> other
return nil unless other.is_a?(self.class)
[self.attr1, self.attr2] <=> [other.attr1, other.attr2]
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With