---
title: constant annoyance
teaser:
tags: web,rails
author: Jared Carroll
published_on: 2007-08-15
---

Recently Ive been running into some strange behavior with Ruby and its class
constants and methods.

For example, the following works:

```ruby
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:

```ruby
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:

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