Skip to content

Instantly share code, notes, and snippets.

@brentd
Created April 8, 2010 20:31
Show Gist options
  • Select an option

  • Save brentd/360506 to your computer and use it in GitHub Desktop.

Select an option

Save brentd/360506 to your computer and use it in GitHub Desktop.

Revisions

  1. brentd created this gist Apr 8, 2010.
    61 changes: 61 additions & 0 deletions gistfile1.ru
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@
    # Allows you to build a Hash in a fashion very similar to Builder. Example:
    #
    # HashBuilder.build! do |h|
    # h.name "Brent"
    # h.skillz true
    # h.location do
    # h.planet "Earth"
    # end
    # end
    #
    # produces:
    #
    # {:name => "Brent", :skillz => true, :location => {:planet => "Earth"}}
    #
    class HashBuilder
    instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|^object_id$)/ }

    def initialize
    @hash = {}
    @target = @hash
    end

    def self.build!
    builder = HashBuilder.new
    yield builder
    builder.to_h
    end

    def to_h
    @hash
    end

    def inspect
    to_h.inspect
    end

    def attr!(key, value=nil)
    if block_given?
    parent = @target
    @target = {}
    yield
    parent[key] = @target
    @target = parent
    else
    @target[key] = value
    end
    @hash
    end

    def method_missing(key, value=nil, &block)
    attr!(key, value, &block)
    end
    end

    class Hash
    unless method_defined?(:build!)
    def build!(&block)
    ::HashBuilder.build!(&block)
    end
    end
    end