Shahzad Bhatti Welcome to my ramblings and rants!

August 4, 2006

Enums and Lookups in Ruby and Java

Filed under: Computing — admin @ 9:18 pm

Enums and Lookups in Ruby and Java
Though, Java inherited many of its syntax and features from C++, but it
shunned enums until 1.5 release. Similarly, there is no support of enums in
Ruby, though there is
RCR 178
to add this feature. Another need most software need
is lookups such as list of states, airports, range of ages, etc. Neither
language has built-in support for lookups. Though, both languages have
very good collection support and simple applications can use Map (Java)
or Hash (Ruby). Though, such arrangement can work for small teams where
code is shared by relatively few developers, but when such shared definition
of constants and lookups is shared by hundreds of programmers, it can be
hard to maintain. Thus many large organizations use database or xml files
to store files. Such arrangement in Java can result in cumbersome synax
and maintenance. For example, though we use Java 1.5 at work, but we
have our own way of defining enums similar to how Java’s enum class works,

  • Define an inteface that returns name and description.
  • For each enum type, define a class that implements this interface.
  • Store values of enum in an xml file.
  • The runtime environment loads these classes and xml files and provides
    lookup and caching.

This can be a lot of work for programmers, who are defining these enums or
using it. Part of the problem is Java is not dynamic and does not has
features like to change types at runtime. For example, here is a small
example, how Ruby can provide type safe enums or lookups:

Define method_missing in Hash

The method_missing is called when method does not exist. In this case,
the key name is used as a method name, and this method will return hash

1 class Hash
2   def method_missing(key, *args)
3     self[key]
4   end
5 end

Define Storage mechanism for enums

Here I am using simply Hash to store enums and lookup data, though database
can be used as well (with some operator overloading to provide hash like

 2  #
 3  ###
 4  #
 5  module LookupMemoryStorage
 6    @@ChargeTypeCode = {
 7         :ChargeBack             => :CB,
 8         :ServiceFee             => :SR,
 9         :ExchangeFee            => :EX,
10         :HighTouchFee           => :HT,
11         :ExecutiveHighTouchFee  => :ET,
12         :CarServiceFee          => :CF,
13         :HotelServiceFee        => :HF,
14         :TelesalesServiceFee    => :TS,
15         :ShippingFee            => :SH,
16         :BookingFee             => :BK,
17         :ExchangeAddCollectFee  => :XA,
18         :CustomerRefund         => :CR,
19         :MerchantHotel          => :HM,
20         :MerchantCar            => :CM,
21         :MechantInsurance       => :IN,
22         :MerchantAir            => :MA,
23    }
25    @@ProductTypeCode = {
26         :AIR                    => :AIR,
27         :HOTEL                  => :HOT,
28         :CAR                    => :CAR,
29    }
31    @@FeeTypeCode = {
32         :AirlinePaperTicketFee  => :APF,
33         :ServiceFee             => :SV,
34    }
36    @@PostAuthTypeCode = {
37         :FAILED                 => :F,
38         :SUCCESS                => :S,
39    }
41    @@storage = {
42      : ChargeTypeCode           =>      @@ChargeTypeCode,
43      : ProductTypeCode          =>      @@ProductTypeCode,
44      : FeeTypeCode              =>      @@FeeTypeCode,
45      : PostAuthTypeCode         =>      @@PostAuthTypeCode,
46    }
47  end

Lookup Class

Lookup class is helper class for looking up enums and key/value pair, e.g.

 1  class Lookup
 2    include LookupMemoryStorage 
 4    def self.method_missing(sym, *args)
 5      hash = @@storage[sym]
 6      raise "Could not find category #{sym}" unless hash
 7      hash
 8    end
 9  end

Lookup Class

Lookup class is helper class for looking up enums and key/value pair, e.g.

Client Code

Finally, following code shows how client will use Lookup class. The method
after Lookup is used as a type of lookup and method after type is used as
name of lookup key.

1 puts Lookup.ChargeTypeCode.PreAuth
2 puts Lookup.ChargeTypeCode.InvalidPreAuth
3 puts Lookup.ProductTypeCode.AIR
4 puts Lookup.ProductTypeCode.HOTEL

In this case, when type is not found an exception is raised, howevery when
key is not found it returns nil.

No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URL

Sorry, the comment form is closed at this time.

Powered by WordPress