class Ably::Models::IdiomaticRubyWrapper

Wraps Hash objects returned by Ably service to appear as Idiomatic Ruby Hashes with symbol keys It recursively wraps containing Hashes, but will stop wrapping at arrays, any other non Hash object, or any key matching the ‘:stops_at` options It also provides methods matching the symbolic keys for convenience

@example

ruby_hash = IdiomaticRubyWrapper.new({ 'keyValue' => 'true' })
# or recommended to avoid wrapping wrapped objects
ruby_hash = IdiomaticRubyWrapper({ 'keyValue' => 'true' })

ruby_hash[:key_value] # => 'true'
ruby_hash.key_value # => 'true'
ruby_hash[:key_value] = 'new_value'
ruby_hash.key_value # => 'new_value'

ruby_hash[:none] # => nil
ruby_hash.none # => nil

@!attribute [r] stop_at

@return [Array<Symbol,String>] array of keys that this wrapper should stop wrapping at to preserve the underlying Hash as is

Attributes

stop_at[R]

Public Class Methods

new(mixedCaseHashObject, options = {}) click to toggle source

Creates an IdiomaticRubyWrapper around the mixed case Hash object

@attribute [Hash] mixedCaseHashObject mixed case Hash object @attribute [Array<Symbol,String>] stop_at array of keys that this wrapper should stop wrapping at to preserve the underlying Hash as is

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 54
def initialize(mixedCaseHashObject, options = {})
  stop_at = options.fetch(:stop_at, [])

  if mixedCaseHashObject.kind_of?(IdiomaticRubyWrapper)
    $stderr.puts "<IdiomaticRubyWrapper#initialize> WARNING: Wrapping a IdiomaticRubyWrapper with another IdiomaticRubyWrapper"
  end

  @attributes = mixedCaseHashObject
  @stop_at = Array(stop_at).each_with_object({}) do |key, object|
    object[convert_to_snake_case_symbol(key)] = true
  end.freeze
end

Public Instance Methods

==(other) click to toggle source

Compare object based on Hash equivalent

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 126
def ==(other)
  return false unless other.kind_of?(self.class) || other.kind_of?(Hash)

  other = other.to_hash if other.kind_of?(self.class)
  to_hash == other
end
[](key) click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 67
def [](key)
  value = attributes[source_key_for(key)]
  if stop_at?(key) || !value.kind_of?(Hash)
    value
  else
    IdiomaticRubyWrapper.new(value, stop_at: stop_at)
  end
end
[]=(key, value) click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 76
def []=(key, value)
  attributes[source_key_for(key)] = value
end
as_json(*args) click to toggle source

Takes the underlying Hash object and returns it in as a JSON ready Hash object using camelCase for compability with the Ably service. Note name clashes are ignored and will result in loss of one or more values @example

wrapper = IdiomaticRubyWrapper({ 'mixedCase': true, mixed_case: false, 'snake_case': 1 })
wrapper.as_json => { 'mixedCase': true, 'snakeCase': 1 }
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 157
def as_json(*args)
  attributes.each_with_object({}) do |key_val, new_hash|
    key                      = key_val[0]
    mixed_case_key           = convert_to_mixed_case(key)
    wrapped_val              = self[key]
    wrapped_val              = wrapped_val.as_json(args) if wrapped_val.kind_of?(IdiomaticRubyWrapper)

    new_hash[mixed_case_key] = wrapped_val
  end
end
attributes() click to toggle source

@!attribute [r] Hash @return [Hash] Access to the raw Hash object provided to the constructor of this wrapper

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 148
def attributes
  @attributes
end
dup() click to toggle source

Method to create a duplicate of the underlying Hash object Useful when underlying Hash is frozen

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 189
def dup
  Ably::Models::IdiomaticRubyWrapper.new(attributes.dup, stop_at: stop_at.keys)
end
each() { |key, value| ... } click to toggle source

Method ensuring this {IdiomaticRubyWrapper} is {ruby-doc.org/core-2.1.3/Enumerable.html Enumerable}

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 115
def each
  return to_enum(:each) unless block_given?

  attributes.each do |key, value|
    key = convert_to_snake_case_symbol(key)
    value = self[key]
    yield key, value
  end
end
empty?() click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 98
def empty?
  attributes.empty?
end
fetch(key, default = nil) { |key| ... } click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 80
def fetch(key, default = nil)
  if has_key?(key)
    self[key]
  else
    if default
      default
    elsif block_given?
      yield key
    else
      raise KeyError, "key not found: #{key}"
    end
  end
end
freeze() click to toggle source

Freeze the underlying data

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 194
def freeze
  attributes.freeze
end
has_key?(key) click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 110
def has_key?(key)
  attributes.has_key?(source_key_for(key))
end
hash() click to toggle source

@!attribute [r] hash @return [Integer] Compute a hash-code for this hash. Two hashes with the same content will have the same hash code

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 204
def hash
  attributes.hash
end
keys() click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 102
def keys
  map { |key, value| key }
end
method_missing(method_sym, *arguments) click to toggle source
Calls superclass method
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 133
def method_missing(method_sym, *arguments)
  key = method_sym.to_s.gsub(%r{=$}, '')
  return super if !has_key?(key)

  if method_sym.to_s.match(%r{=$})
    raise ArgumentError, "Cannot set #{method_sym} with more than one argument" unless arguments.length == 1
    self[key] = arguments.first
  else
    raise ArgumentError, "Cannot pass an argument to #{method_sym} when retrieving its value" unless arguments.empty?
    self[method_sym]
  end
end
size() click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 94
def size
  attributes.size
end
to_hash(*args) click to toggle source

Generate a symbolized Hash object representing the underlying Hash in a Ruby friendly format. Note name clashes are ignored and will result in loss of one or more values @example

wrapper = IdiomaticRubyWrapper({ 'mixedCase': true, mixed_case: false, 'snake_case': 1 })
wrapper.to_hash => { mixed_case: true, snake_case: 1 }
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 179
def to_hash(*args)
  each_with_object({}) do |key_val, object|
    key, val    = key_val
    val         = val.to_hash(args) if val.kind_of?(IdiomaticRubyWrapper)
    object[key] = val
  end
end
to_json(*args) click to toggle source

Converts the current wrapped mixedCase object to JSON using snakedCase syntax as expected by the Realtime API

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 170
def to_json(*args)
  as_json(args).to_json
end
to_s() click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 198
def to_s
  attributes.to_s
end
values() click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 106
def values
  map { |key, value| value }
end

Private Instance Methods

source_key_for(symbolized_key) click to toggle source

We assume by default all keys are interchangeable between :this_format and ‘thisFormat’ However, this method will find other fallback formats such as CamelCase or :symbols if a matching key is not found in mixedCase.

# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 216
def source_key_for(symbolized_key)
  format_preferences = [
    lambda { |key_sym| convert_to_mixed_case(key_sym) },
    lambda { |key_sym| key_sym.to_sym },
    lambda { |key_sym| key_sym.to_s },
    lambda { |key_sym| convert_to_mixed_case(key_sym).to_sym },
    lambda { |key_sym| convert_to_lower_case(key_sym) },
    lambda { |key_sym| convert_to_lower_case(key_sym).to_sym },
    lambda { |key_sym| convert_to_mixed_case(key_sym, force_camel: true) },
    lambda { |key_sym| convert_to_mixed_case(key_sym, force_camel: true).to_sym }
  ]

  preferred_format = format_preferences.detect do |format|
    attributes.has_key?(format.call(symbolized_key))
  end || format_preferences.first

  preferred_format.call(symbolized_key)
end
stop_at?(key) click to toggle source
# File lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb, line 209
def stop_at?(key)
  @stop_at.has_key?(key)
end