class Beaneater::FasterOpenStruct

Borrowed from: github.com/dolzenko/faster_open_struct/blob/master/lib/faster_open_struct.rb

Up to 40 (!) times more memory efficient version of OpenStruct

Differences from Ruby MRI OpenStruct:

  1. Doesn't `dup` passed initialization hash (NOTE: only reference to hash is stored)

  2. Doesn't convert hash keys to symbols (by default string keys are used, with fallback to symbol keys)

  3. Creates methods on the fly on `OpenStruct` class, instead of singleton class. Uses `module_eval` with string to avoid holding scope references for every method.

  4. Refactored, crud clean, spec covered :)

@private

Public Class Methods

new(hash = nil) click to toggle source
# File lib/beaneater/stats/fast_struct.rb, line 26
def initialize(hash = nil)
  @hash = hash || {}
  @initialized_empty = hash == nil
end

Public Instance Methods

==(other) click to toggle source

Compare this object and other for equality.

# File lib/beaneater/stats/fast_struct.rb, line 81
def ==(other)
  return false unless other.is_a?(self.class)
  @hash == other.instance_variable_get(:@hash)
end
__new_ostruct_member__(method_name_sym) click to toggle source
# File lib/beaneater/stats/fast_struct.rb, line 51
    def __new_ostruct_member__(method_name_sym)
      self.class.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
      def #{ method_name_sym }
        @hash.fetch("#{ method_name_sym }", @hash[:#{ method_name_sym }]) # read by default from string key, then try symbol
                                                                          # if string key doesn't exist
      end
      END_EVAL

      unless method_name_sym.to_s[-1] == ?? # can't define writer for predicate method
        self.class.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
        def #{ method_name_sym }=(val)
          if @hash.key?("#{ method_name_sym }") || @initialized_empty       # write by default to string key (when it is present
                                                                            # in initialization hash or initialization hash
                                                                            # wasn't provided)
            @hash["#{ method_name_sym }"] = val                             # if it doesn't exist - write to symbol key
          else
            @hash[:#{ method_name_sym }] = val
          end
        end
        END_EVAL
      end
    end
empty?() click to toggle source
# File lib/beaneater/stats/fast_struct.rb, line 74
def empty?
  @hash.empty?
end
inspect() click to toggle source

Returns a string containing a detailed summary of the keys and values.

# File lib/beaneater/stats/fast_struct.rb, line 89
def inspect
  str = "#<#{ self.class }"
  str << " #{ @hash.map { |k, v| "#{ k }=#{ v.inspect }" }.join(", ") }" unless @hash.empty?
  str << ">"
end
Also aliased as: to_s
method_missing(method_name_sym, *args) click to toggle source
# File lib/beaneater/stats/fast_struct.rb, line 31
def method_missing(method_name_sym, *args)
  if method_name_sym.to_s[-1] == ?=
    if args.size != 1
      raise ArgumentError, "wrong number of arguments (#{args.size} for 1)", caller(1)
    end

    if self.frozen?
      raise TypeError, "can't modify frozen #{self.class}", caller(1)
    end

    __new_ostruct_member__(method_name_sym.to_s.chomp("="))
    send(method_name_sym, args[0])
  elsif args.size == 0
    __new_ostruct_member__(method_name_sym)
    send(method_name_sym)
  else
    raise NoMethodError, "undefined method `#{method_name_sym}' for #{self}", caller(1)
  end
end
to_s()
Alias for: inspect