Compare Date with PORO - ruby

I have implemented the null object pattern (with the MissingDate class)on a Ruby app to handle a specific case when a Date object is not available.
Now, I need to compare instances of Date and MissingDate and have MissingDate always bigger than Date. Therefore, I have included the Comparable module.
class MissingDate
include Comparable
...
def <=>(other)
if [Date, MissingDate].include?(other.class)
1
else
nil
end
end
end
However, I get comparison of Date with MissingDate failed. What am I missing?

Related

In Ruby, how do I assign a value to a class instance

I want to create a class instance that has a value such that I can do something like puts a = Example.new(1) where a's value is specified in initialize.
I expect that this is a simple problem since all predefined Ruby classes allow this, but I'm unable to figure out how to do it for my classes.
Class#new and Return Values
Your example doesn't quite work because Ruby treats Class#new as a special case, and is expected to invoke the #initialize method and return an object. If it didn't, calling #new on a class would surprise a lot of people by returning the last evaluation of the initializer from your class, or from Object#new if it's otherwise undefined for your class. In either case, this would violate the principle of least surprise.
However, you can do what you want pretty easily by simply creating an accessor method and then chaining off of Example#new. For example, in Ruby 3.1.0:
class Example
attr_reader :int
def initialize(int) = (#int = int)
end
# prints `1` to STDOUT and assigns the value to *a*,
# but returns nil because you're using Kernel#puts
# which always returns nil
puts a = Example.new(1).int
# shows that the local variable *a* is set to the value
# returned by the Example#int accessor for the class'
# #int instance variable
a
#=> 1
To avoid the confusion of having a nil return value (even though this is expected with Kernel#puts, just change your puts statement to use Kernel#p instead:
p a = Example.new(2).int
#=> 2
Refactoring the Example Class for Older Rubies
If you're using an older Ruby than 3.0, you can't use an endless method or the improved handling for them in Ruby 3.1. The only difference is that rather than an inline method, you need to specify it with the standard def...end syntax, e.g.:
class Example
attr_reader :int
def initialize(int)
#int = int
end
end
Otherwise, the points above are valid as far back as any currently-supported Ruby version.

const_defined? vs. defined? in Ruby

To test, whether a constant (say: a class) is known at a certain point in the code, I can write for instance:
if defined? :String
or I can write
if self.class.const_defined? :String
Is there a situation where I these two ways of testing would make a difference? Note that I don't ask about the case where I have an explicit receiver, such as MyModule.const_defined? :Something, but only for the case where I want to test whether a certain constant (which in my case happens to be a constant denoting a class) is already defined.
First things first, defined? is a keyword which behaves a bit similar similar to a method. It receives the name of the thing (variable, constant, ...) to check. What makes this method different from all others is that the parser will not resolve the value of the given name but rather check directly for whether it is defined (hence the keyword property). To check if a constant is defined, you thus have to pass the actual name (rather than a Symbol):
if defined?(String)
The const_defined? on the oither hand is more regular. It expects a Symbol or String with the name of a constant and checks whether it is defined on the receiver.
Now as for the differences between the two (when used correctly): if you use them both within the context of an instance method to check for the existence of a constant, they work the same.
When running e.g. in a class definition (such that self is e.g. a class), you need to make sure to use the correct receiver for your const_defined method, e.g. if self.const_defined? :String.
Also, defined? can check for a lot more than just constants (e.g. methods, expressions, variables, ...)
If you want to use this to make sure you actually have the name of a constant at hand in a given variable, you need to use const_defined?. If you want to "statically" check whether an constant was defined, you can use defined?.
defined? is a keyword that will check if an expression exists in the current scope.
const_defined? is a method that will check if a constant exists through the ancestor chain of the receiver.
planet = "Earth"
class Experiment
def diff
""
end
def show
puts "defined" if defined?(diff)
puts "Earth not found" if !defined?(planet)
puts "String constant defined" if self.class.const_defined?(:String)
end
end
Experiment.new.show
#=> defined
#=> Earth not found
#=> String constant defined
p Experiment.ancestors #=> [Experiment, Object, Kernel, BasicObject]
p String.superclass #=> Object
Here's an example of situations where this will make a difference:
Using defined?(Nothing's printed)
class Lab
class Coco
end
end
class Experiment
def diff
""
end
def show
puts "defined" if defined?(Coco) #=> Nothing printed
end
end
Experiment.new.show
Using self.class.const_defined? (Something's printed)
class Lab
class Coco
end
end
class Experiment < Lab
def diff
""
end
def show
puts "defined" if self.class.const_defined? :Coco #=> defined
end
end
Experiment.new.show
p Experiment.ancestors #=> [Experiment, Lab, Object, Kernel, BasicObject] We find 'Lab' class in the ancestor chain.
To test, whether a constant (say: a class) is known at a certain point in the code, I can write for instance:
if defined? :String
or I can write
if self.class.const_defined? :String
Is there a situation where I these two ways of testing would make a difference?
These two really do two completely different things. The first tests whether the Symbol literal :String is defined. Obviously, a literal will always be defined, so this expression will always be true.
The second will check whether the constant String is defined, but not starting at the current constant lookup scope, instead starting at the class of self.
TL;DR
There may be cases where you can use them interchangeably, but one is a keyword and the other a method. In addition, the semantics and return values of the two are quite different.
Keywords vs. Methods
Among other things, one key difference is that Module#const_defined? is a method on a class or module that looks up constants in a class and its ancestors, while defined? is a keyword that determines whether its argument is currently known at the calling point in your code.
For example:
char = 'a'
char.const_defined?
#=> NoMethodError (undefined method `const_defined?' for "a":String)
defined? char
#=> "local-variable"
Exceptions vs. Return Values
If you're only concerned about constants, then the main difference is that you can use defined? to determine whether a constant is currently in scope without triggering a NoMethodError exception. For example:
defined? String
#=> "constant"
defined? FooBarBaz
#=> nil
As a bonus, defined? will tell what type of object you're passing as an argument (e.g. "constant"), while #const_defined? returns a truthy value.
Float.constants
#=> [:ROUNDS, :RADIX, :MANT_DIG, :DIG, :MIN_EXP, :MAX_EXP, :MIN_10_EXP, :MAX_10_EXP, :MIN, :MAX, :EPSILON, :INFINITY, :NAN]
defined? Float::NAN
#=> "constant"
Float.const_defined? :NAN
#=> true
As a rule of thumb, it's often considered best practice to reserve exceptions for handling something unexpected that may require your application to halt. Introspection or branching should generally rely on return values or Booleans, so defined? is usually a better choice if you aren't already expecting a given class to already be defined and available within the current scope.
Is there a situation where I these two ways of testing would make a difference?
const_defined? only checks the receiver and its ancestors, but it doesn't take the current module nesting into account:
module Foo
ABC = 123
class Bar
def self.test
p defined?(ABC) #=> "constant"
p const_defined?(:ABC) #=> false
end
end
end
In order to do so, you have to traverse Module.nesting:
module Foo
ABC = 123
class Bar
def self.test
p defined?(ABC) #=> "constant"
p Module.nesting.any? { |m| m.const_defined?(:ABC) } #=> true
end
end
end

Avoiding method overloading in Ruby

Due to the fact that Ruby doesn't support overloading (because of several trivial reasons), I am trying to find a way to 'simulate' it.
In static typed languages, you mustn't use instanceof, (excepting some particular cases of course...) to guide the application.
So, keeping this in mind, is this the correct way to overload a method in which I do care about the type of the variable? (In this case, I don't care about the number of parameters)
class User
attr_reader :name, :car
end
class Car
attr_reader :id, :model
end
class UserComposite
attr_accessor :users
# f could be a name, or a car id
def filter(f)
if (f.class == Car)
filter_by_car(f)
else
filter_by_name(f)
end
end
private
def filter_by_name(name)
# filtering by name...
end
def filter_by_car(car)
# filtering by car id...
end
end
There are cases where this is a good approach, and Ruby gives you the tools to deal with it.
However your case is unclear because your example contradicts itself. If f.class == Car then filter_by_car accepts a _car, not a _car_id.
I'm assuming that you're actually passing instances of the class around, and if so you can do this:
# f could be a name, or a car
def filter(f)
case f
when Car
filter_by_car(f)
else
filter_by_name(f)
end
end
case [x] looks at each of its when [y] clauses and executes the first one for which [y] === [x]
Effectively this is running Car === f. When you call #=== on a class object, it returns true if the argument is an instance of the class.
This is quite a powerful construct because different classes can define different "case equality". For example the Regexp class defines case equality to be true if the argument matches the expression, so the following works:
case "foo"
when Fixnum
# Doesn't run, the string isn't an instance of Fixnum
when /bar/
# Doesn't run, Regexp doesn't match
when /o+/
# Does run
end
Personally, I don't see a big problem in branching that way. Although it would look cleaner with a case
def filter(f)
case f
when Car
filter_by_car(f)
else
filter_by_name(f)
end
end
Slightly more complicated example involves replacing branching with objects (ruby is oop language, after all :) ). Here we define handlers for specific formats (classes) of data and then look up those handlers by incoming data class. Something along these lines:
class UserComposite
def filter(f)
handler(f).filter
end
private
def handler(f)
klass_name = "#{f.class}Handler"
klass = const_get(klass_name) if const_defined?(klass_name)
klass ||= DefaultHandler
klass.new(f)
end
class CarHandler
def filter
# ...
end
end
class DefaultHandler # filter by name or whatever
def filter
# ...
end
end
end
There could be a problem lurking in your architecture - UserComposite needs to know too much about Car and User. Suppose you need to add more types? UserComposite would gradually become bloated.
However, it's hard to give specific advice because the business logic behind filtering isn't clear (architecture should always adapt to your real-world use-cases).
Is there really a common action you need to do to both Cars and Users?
If not, don't conflate the behavior into a single UserComposite class.
If so, you should use decorators with a common interface. Roughly like this:
class Filterable
# common public methods for filtering, to be called by UserComposite
def filter
filter_impl # to be implemented by subclasses
end
end
class FilterableCar < Filterable
def initialize(car)
#car = car
end
private
def filter_impl
# do specific stuff with #car
end
end
class DefaultFilterable < Filterable
# Careful, how are you expecting this generic_obj to behave?
# It might be better replace the default subclass with a FilterableUser.
def initialize(generic_obj)
# ...
end
private
def filter_impl
# generic behavior
end
end
Then UserComposite only needs to care that it gets passed a Filterable, and all it has to do is call filter on that object. Having the common filterable interface keeps your code predictable, and easier to refactor.
I recommend that you avoid dynamically generating the filterable subclass name, because if you ever decide to rename the subclass, it'll be much harder to find the code doing the generating.

Why does Ruby not have boolean class, instead using TrueClass and FalseClass? [duplicate]

I was working on serializing values when found out about this one. Ruby has a TrueClass class, and a FalseClass class, but it has no Boolean class. I'd like to know why is this.
I see some advantages in using a Boolean; for example, string parsing could be centralized on it.
Ruby developers are smarter than me, so there must be a lot of good reasons that I just don't see. But right now it looks to me like having OneClass and a TwoClass instead of Fixnum.
The purpose of a class is to group similar objects, or objects with similar behavior together. 1 and 2 are very similar, therefore it makes perfect sense for them to be in the same class. true and false however are not similar. In fact, their whole point is that they are exactly the opposite of each other and have opposite behavior. Therefore, they don't belong in the same class.
Can you give an example of what sort of common behavior you would implement in a Boolean class? I can't think of anything.
Let's just look at the behavior that TrueClass and FalseClass have: there's exactly four methods there. No more. And in every single case, the two methods do exactly the opposite. How and why would you put that in a single class?
Here's how you implement all those methods:
class TrueClass
def &(other)
other
end
def |(_)
self
end
def ^(other)
!other
end
def to_s
'true'
end
end
And now the other way around:
class FalseClass
def &(_)
self
end
def |(other)
other
end
def ^(other)
other
end
def to_s
'false'
end
end
Granted, in Ruby, there is a lot of "magic" that is going on behind the scenes and that is not actually handled by TrueClass and FalseClass but rather hardwired into the interpreter. Stuff like if, &&, || and !. However, in Smalltalk, from which Ruby borrowed a lot including the concept of FalseClass and TrueClass, all of these are implemented as methods as well, and you can do the same thing in Ruby:
class TrueClass
def if
yield
end
def ifelse(then_branch=->{}, _=nil)
then_branch.()
end
def unless
end
def unlesselse(_=nil, else_branch=->{})
ifelse(else_branch, _)
end
def and
yield
end
def or
self
end
def not
false
end
end
And again the other way around:
class FalseClass
def if
end
def ifelse(_=nil, else_branch=->{})
else_branch.()
end
def unless
yield
end
def unlesselse(unless_branch=->{}, _=nil)
ifelse(_, unless_branch)
end
def and
self
end
def or
yield
end
def not
true
end
end
A couple of years ago, I wrote the above just for fun and even published it. Apart from the fact that the syntax looks different because Ruby uses special operators while I use only methods, it behaves exactly like Ruby's builtin operators. In fact, I actually took the RubySpec conformance testsuite and ported it over to my syntax and it passes.
It seems that Matz himself answered this question on a mailing list message in 2004.
Short version of his answer: "right now it works ok, adding a Boolean doesn't give any advantage".
Personally I don't agree with that; the aforementioned "string parsing" is one example. Another one is that when you are applying different treatment to a variable depending on its type, (i.e. a yml parser) having a "Boolean" class is handy - it removes one "if". It also looks more correct, but that's a personal opinion.
Quoting Matz on Ruby forum (2013):
...There's nothing true and false commonly share, thus no Boolean class.
Besides that, in Ruby, everything behave as Boolean value....
true and false could be managed by a Boolean class that held multiple values, but then the class object would have to have internal values, and therefore have to be de-referenced with every use.
Instead, Ruby treats true and false as long values (0 and 1), each of which corresponds to a type of object class (FalseClass and TrueClass). By using two classes instead of a single Boolean class, each class does not require any values and therefore can be distinguished simply by its class identifier (0 or 1). I believe this translates to significant speed advantages internal to the Ruby engine, because internally Ruby can treat TrueClass and FalseClass as long values that require zero translation from their ID value, whereas a Boolean object would have to be de-referenced before it could be evaluated.
Since everything but false and nil evaluate to true in Ruby by default, you would only need to add parsing to String.
Something like this could work:
class Object
## Makes sure any other object that evaluates to false will work as intended,
## and returns just an actual boolean (like it would in any context that expect a boolean value).
def trueish?; !!self; end
end
class String
## Parses certain strings as true; everything else as false.
def trueish?
# check if it's a literal "true" string
return true if self.strip.downcase == 'true'
# check if the string contains a numerical zero
[:Integer, :Float, :Rational, :Complex].each do |t|
begin
converted_number = Kernel.send(t, self)
return false if converted_number == 0
rescue ArgumentError
# raises if the string could not be converted, in which case we'll continue on
end
end
return false
end
end
When used, this would give you:
puts false.trueish? # => false
puts true.trueish? # => true
puts 'false'.trueish? # => false
puts 'true'.trueish? # => true
puts '0'.trueish? # => false
puts '1'.trueish? # => true
puts '0.0'.trueish? # => false
puts '1.0'.trueish? # => true
I believe part of the “big idea” behind Ruby is to just make the behavior you desire inherent to your program (e.g. boolean parsing), rather creating a fully encapsulated class that lives in it's own namespace world (e.g. BooleanParser).
The main reason is simply the fact that this is far quicker and simpler to implement boolean expressions as it is currently than with a Boolean class which would imply a conversion.
As Mongus Pong told you, when you write "if ", you ask the interpretor to evaluate the thing and then branch. If you had Boolean class, you'd have to convert the evaluation of thing into a Boolean before branching (one more step).
Remember that such a ->Boolean conversion would be available as a Ruby method in the Boolean class. This method could then be changed dynamically as any other Ruby method, allowing developer to mess up things completely (which is not so serious indeed) but clearly, this wouldn't allow the interpretor to optimize tests as they should.
Do you realize that it would replace a few CPU instructions operation by a complete method call, which is costly in Ruby (remember the "send" method processing)...
Joining TrueClass and FalseClass with a kind of Boolean super-class breaks the LSP (Liskov Substitution Principle, lsp) - then "any code using Boolean should be able use any it's descendant transparently". It is not achievable for TrueClass and FalseClass since they have opposite behavior.
Btw, LSP is the (L) of SOLID.
Looks like it is the good example of LSP in real life.
UPD#1: regarding does LSP broken or not
COMMON_EXPECTED_VALUE = x
def test_LSP(klass)
assert klass.new.value == COMMON_EXPECTED_VALUE
end
test_LSP(FooClass)
test_LSP(BarClass)
Once you have got both green - you have chances to not break the LSP joining this classes with the common superclass, of course if you will get double green for all features of future superclass.
In Ruby nil and false are false and everything else is true. Hence there is no need for a specific boolean class.
You can try it :
if 5
puts "5 is true"
end
5 evaluates to true
if nil
puts "nil is true"
else
puts "nil is false"
end
Will print "nil is false"
As others have said, you could "patch" Ruby. Create your own class. Here is something I came up with. The methods on the Boolean class are a bit silly, but they could be useful programmatically at some point.
class Boolean
def self.new(bool)
bool
end
def self.true
true
end
def self.false
false
end
end
class FalseClass
def is_a?(other)
other == Boolean || super
end
def self.===(other)
other == Boolean || super
end
end
class TrueClass
def is_a?(other)
other == Boolean || super
end
def self.===(other)
other == Boolean || super
end
end

Constants in classes created with Class.new

I'm writing a little piece of code in Ruby (1.9.3), and I use a pair of simple "enum-like" classes, that define some constants with const_set and some behavior of these constants (e.g. the class Days may have the constants MON, TUE... and Days::MON.succ should evaluate to TUE).
I'm really comfortable with these classes. However, while growing my code, i sometimes need to add more of them, and I don't like the idea of having five or more classes that share 99% of source code, e.g.:
class Days
NAMES = %w( MON TUE ... )
INSTANCES = []
def initialize(num)
#num = num
end
# An example operation
def +(n)
INSTANCES[(#num + n) % INSTANCES.length]
end
# Another example operation
def succ
self + 1
end
def to_s
NAMES[#num]
end
NAMES.each_with_index do |name, idx|
instance = new(idx)
INSTANCES[idx] = instance
const_set name, instance
end
end
class Months
NAMES = %w( JAN FEB ... )
...
end
I was wondering if Ruby's metaprogramming capabilities could be used to generate these classes. However, I'm having an hard time creating NAMES, INSTANCES and the "enum-named" constants (e.g. MON, TUE, ...).
Being const_set a class method of Class, in this code it's context (the value of self) is respectively Days and Months.
When creating a factory method, I'm compelled to do something like this:
def enum_new(names_array)
Class.new do
const_set "NAMES" []
names_array.each_with_index do |name, idx|
NAMES[idx] = name
end
...
end
end
Days = enum_new(%w| MON TUE ... |)
Months = enum_new(%w| JAN FEB ... |)
but this won't work (at least, not like i hoped it to), because const_set won't be called in the context of the class whose name is magically set (i.e. Days and Months), but apparently in the context of Class; therefore, not only it won't be accessible from the instance methods, but it will be overwrited every time enum_new is called with a new array of names as argument. A similar problem shows up when using class variables, because they'll be shared between any class generated with the method (because they'll become class variables of Class, i guess).
Is there any way to create constants in a class generated with Class.new, obtaining this way classes identical in everything to the original Days and Months classes, without having to pollute my code with almost identical classes?
Thanks for your attention and patience! :)
Yes. Do your initialization in a class_exec block, into which you can pass your name data and where self refers to the right class:
theClass=Class.new
theClass.class_exec(names) do |names|
#initialize constants here...
end

Resources