Friday, June 17, 2011

Unfickle: A new constant way

Through my programming in Ruby I see a lot of people doing things like this:

class SomeClass
SOMECONSTANT = 'somevalue'
...
end
view raw unfickle1.rb hosted with ❤ by GitHub


I really don't like this.. It just seems messy. So, I wrote a gem that I think solves it in a somewhat elegant way. The gem is called Unfickle and can be used like so:

class SomeClass
set_const :someconstant, 'somevalue'
end
view raw unfickle2.rb hosted with ❤ by GitHub


The result is somewhat the same, only it's stored in a hash. This gives users the ability to iterate over that hash to find the constant they want. Example:

> SomeClass::SOMECONSTANT
=> 'somevalue'
> SomeClass.keys
=> [:SOMECONSTANT]
view raw unfickle3.rb hosted with ❤ by GitHub


You can even traverse the constants using the '.each' method provided by the Hash class :D

The entire code for this gem is very simple:

module Unfickle
extend Forwardable
def set_const(key,value)
@hash ||= {}
@hash[key.upcase.to_sym]=value
end
def const_missing(key)
@hash[key]
end
def_delegators :@hash, :each, :values, :keys, :[]
def clear
@hash = {}
end
end


The first method, 'set_const' just creates a new hash, if it doesn't exist, and adds the key/value pair to that hash. 'const_missing' is the method that retrieves the hash value based on the key passed in.

I extended the 'Forwardable' module and delegated four methods to the Hash instance created by the set_const method. This means I don't have to re-implement that.

One of the issues with this code is optimization. Using 'const_missing' means we have to go through a begin/rescue block to figure out a constant is missing. This is a performance hit. The other speed issue comes with the use of delegators. Although these two things can slow down code, I think the speed hit is negligible. If you have a better way, don't hesitate to let me know.

You can find this code on github here.
Install the gem like normal:
gem install unfickle

No comments:

Post a Comment