Recently Ive been running into some strange behavior with Ruby and its class constants and methods.
For example, the following works:
class User
def self.blah
puts 'blah'
end
end
User.blah => 'blah'
User::blah => 'blah'
Somebody tell me why that works.
My only idea is that its some implementation bug about the way Ruby stores its class methods.
Either way, invoking a class method like you’d reference a class or module is too confusing, so don’t use it.
Another one is that defining a class constant via #class_eval
, really declares
a top level constant:
class User
end
TYPES => uninitialized constant TYPES
User.class_eval do
TYPES = ['admin', 'non-admin']
end
TYPES => ['admin', 'non-admin']
User::TYPES => warning toplevel constant TYPES referenced by
User::TYPES ['admin', 'non-admin']
In some Ruby I was trying to do the following:
User.class_eval do
TYPES = ['admin', 'non-admin']
end
Event.class_eval do
TYPES = ['meeting', 'interview']
end
TYPES => ['meeting', 'interview']
In other words I wanted to define a constant with the same name via
#class_eval
in 2 different classes (nevermind why I was doing this via
#class_eval
, just know it was necessary and for a good reason). Of course the
problem is there’s only ever going to be 1 constant named TYPES defined, there
won’t be 2 (1 scoped to User and 1 scoped to Event).
Now how else could I do this?
How about class variables?
User.class_eval do
@@types = ['admin', 'non-admin']
def self.types
@@types
end
end
Event.class_eval do
@@types = ['meeting', 'interview']
def self.types
@@types
end
end
No.
Those are ugly. I never use class variables in Ruby.
How about class methods who’s name’s are in uppercase?
User.class_eval do
def self.TYPES
['admin', 'non-admin']
end
end
Event.class_eval do
def self.TYPES
['meeting', 'interview']
end
end
User.TYPES => ['admin', 'non-admin']
Event.TYPES => ['meeting', 'interview']
That’s a little better but invoking a class method who’s name is in all caps is bizarre.
Wait, how about that above hack I mentioned. According to that I should be able to invoke a class method using a syntax like referencing a class constant.
Order::TYPES
Nope, it doesn’t work. It looks like that hack only works if the class method name is in all lower case, it can’t even be capitalized either.
What a total waste of time.