Welcome to Giant Robots Smashing Into Other Giant Robots — a weblog about development, business, design and technology — written by thoughtbot.
constant annoyance
Recently Ive been running into some strange behavior with Ruby and its class constants and methods.
For example, the following works:
1 2 3 4 5 6 7 8 9 10 |
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:1 2 3 4 5 6 7 8 9 10 11 |
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'] |
1 2 3 4 5 6 7 8 9 |
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?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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.
About this entry
You're reading an entry on GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS, the company weblog of thoughtbot, inc.
- Author:
- Jared Carroll
- Published:
- August 15th 07:00 PM
- Updated:
- September 30th 09:57 AM
- Sections:
- Development
thoughtbot is hiring
We are hiring web developers and web designers in both Boston and New York, NY.
What are we up to?
We built Shoulda, an eclectic set of additions to Test::Unit; Paperclip to manage uploaded files without hassle; Jester, a REST/ActiveResource client library written in Javascript, and Squirrel, an enhancement for ActiveRecord's find syntax; — amongst some other projects.

Chad (President) and Jon (CTO) co-authored a technical book titled Pro Active Record: Databases with Ruby and Rails, which explores the ins and outs of the ActiveRecord ruby library. You can buy it today at Amazon.com.
About thoughtbot, inc.
We are a small web application development consulting business, with offices in Boston, MA and New York, NY. If you're looking to find a team for your next web development project or your new web application — get in touch.
9 comments
Jump to comment form