#define rubyfied 0

Posted by Matt Williams

Remember #defined FOO = 1; from your C days? Or public static int FOO = 1; from java? Well, I recently had reason to use this functionality within Ruby when I wanted to define a series of types which would each have a unique id used in a database, but I really didn't want to waste the space on a string.

I ended up with two methods, the first which takes a name and an enumerable, sets class variables for each element of an array (such as %w(The fat cat sat on a hat)) as well as a method for resolving an integer to a string.

Taking the following class:

1
2
3
4
5
6

require 'definer'
class Project
  define_class_types :states, %w(planning development testing production)
  define :myself, 1
end

you would have the following definitions:

  • Project.planning
  • Project.development
  • Project.testing
  • Project.prodution
  • Project.@@states(not accessible outside of class, but that's easily remedied)
  • Project.myself

Additionally, you would have a method Project.state_name(state) which would take a integer and return the string associated with that state. So, Project.state_name(0) or Project.state_name(Project.planning) would both return "planning".

In the define_class_types method, the name can be either pluralized or singular. The array of the types will be pluralized (as in states above) and the method for getting the string singularized (as in Project.state_name above.

There is one dependency -- it uses ActiveSupport's pluralize and singularize. The code follows below or you can download it here: definer.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

require 'active_support'

class Module
  def class_attr_reader(*symbols)
    symbols.each do |symbol|
      self.class.send(:define_method, symbol) do
        self.class_eval "@@#{symbol}"
      end
    end
  end

  def define(name,value)
    name = name.to_s
    class_variable_set("@@#{name}",value)
    class_attr_reader(name)
  end

  def add_class_types(name, types = [])
    name = name.to_s
    class_variable_set("@@#{name.pluralize}",types)
    types.each_with_index do |type, index|
      class_variable_set("@@#{type}", index)
      class_attr_reader(type)
    end
    self.class.send(:define_method,"#{name.singularize}_name") do |arg|
      self.class_eval "@@#{name.pluralize}[#{arg}]"
    end
  end
end
Comments

Leave a response

Comment