Search code examples
rubyconfigattr-accessor

Create custom accessor at run time


I'm working on a Ruby project. Since I'm learning , I'm trying to do the right way. I want to parse a simple config file ( param = value ), this part is done. Now I would like to do something like :

class ConfigFile
     def self.parse_file s
          # gem parsing the file
          ParseConfig.new(s)
     end 
     parse_file "config.cfg"
end

puts ConfigFile::default_port
puts ConfilgFile::default_ip
# etc

In fact, I want every parameter in the config file to be accessible like this. It's just my first thought, because it seems nice, and ruby seems the kind of language that could do it. If you have better idea, I take ;) (I've also thought of a stupid hash, but it's long to write ConfigFile::h[:default_ip])

I know I should use attr_accessor , somewhere. But my metaprogramming skill is very limited, so if some one could share some light on this, I'd be very grateful !

Thank you

Nikko

Edit 1:

For now I've done it like this , but this doesn't look so nice to me :

class EMMConfig
       require 'parseconfig'

       PATH = "config.cfg"
       @@C = {}
       def self.parse
               @@C = ParseConfig.new(PATH)
      end

      def self.[](param)
               @@C[param]
      end

      def self.list_param
              @@C.get_params
      end

      parse
end

Solution

  • You could do metaprogramming here, but there are much bettter option.

    For instance, you could use OpenStruct, that basically do already what you wan (but using metaprogramming internally)t: convert an hash to an object

    Example:

    cfg={:default_port=>88,:default_ip=>"1.2.3.4"}
    cfg=OpenStruct.new cfg
    

    Then you have access to

    cfg.default_port
    cfg.default_ip
    

    So I would rewrite it as:

    class ConfigFile < OpenStruct
      @@cfg=nil
      def self.parse_file s
           # gem parsing the file
           ConfigFile.new(ParseConfig.new(s))
      end 
      def self.get_default_config
         if @@cfg||(@@cfg=parse_file("config.cfg"))
      end
    end
    

    And use it like this

    cfg=ConfigFile.get_default_config
    cfg.default_ip
    

    If you really want to do by yourself, you need to check "method_missing" ( http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing )

    Basically you do (and I strongly suggest you to do it on variable instance, not class instance)

    def method_missing(methId)
       cfg[methId]
    end