DRY Ruby Initialization with Hash Argument

后端 未结 6 2101

I find myself using hash arguments to constructors quite a bit, especially when writing DSLs for configuration or other bits of API that the end user will be exposed to. Wha

6条回答
  •  悲哀的现实
    2020-11-29 17:26

    There are some useful things in Ruby for doing this kind of thing. The OpenStruct class will make the values of a has passed to its initialize method available as attributes on the class.

    require 'ostruct'
    
    class InheritanceExample < OpenStruct
    end
    
    example1 = InheritanceExample.new(:some => 'thing', :foo => 'bar')
    
    puts example1.some  # => thing
    puts example1.foo   # => bar
    

    The docs are here: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html

    What if you don't want to inherit from OpenStruct (or can't, because you're already inheriting from something else)? You could delegate all method calls to an OpenStruct instance with Forwardable.

    require 'forwardable'
    require 'ostruct'
    
    class DelegationExample
      extend Forwardable
    
      def initialize(options = {})
        @options = OpenStruct.new(options)
        self.class.instance_eval do
          def_delegators :@options, *options.keys
        end
      end
    end
    
    example2 = DelegationExample.new(:some => 'thing', :foo => 'bar')
    
    puts example2.some  # => thing
    puts example2.foo   # => bar
    

    Docs for Forwardable are here: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/forwardable/rdoc/Forwardable.html

提交回复
热议问题