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
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.
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.