Class: Ably::Models::IdiomaticRubyWrapper
- Inherits:
-
Object
- Object
- Ably::Models::IdiomaticRubyWrapper
- Includes:
- Ably::Modules::Conversions, Ably::Modules::MessagePack, Enumerable
- Defined in:
- lib/ably/models/idiomatic_ruby_wrapper.rb
Overview
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
Instance Attribute Summary collapse
-
#hash ⇒ Integer
readonly
Compute a hash-code for this hash.
-
#Hash ⇒ Hash
readonly
Access to the raw Hash object provided to the constructer of this wrapper.
-
#stop_at ⇒ Array<Symbol,String>
readonly
Array of keys that this wrapper should stop wrapping at to preserve the underlying Hash as is.
-
#stop_at array of keys that this wrapper should stop wrapping at to preserve the underlying Hash as is(arrayofkeysthatthiswrappershouldstopwrappingattopreservetheunderlyingHashasis) ⇒ Object
readonly
Creates an IdiomaticRubyWrapper around the mixed case Hash object.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Compare object based on Hash equivalent.
- #[](key) ⇒ Object
- #[]=(key, value) ⇒ Object
-
#as_json(*args) ⇒ Object
Takes the underlying Hash object and returns it in as a JSON ready Hash object using snakeCase for compability with the Ably service.
-
#attributes ⇒ Hash
Access to the raw Hash object provided to the constructer of this wrapper.
-
#dup ⇒ Object
Method to create a duplicate of the underlying Hash object Useful when underlying Hash is frozen.
-
#each ⇒ Object
Method ensuring this Ably::Modules::Conversions#IdiomaticRubyWrapper is Enumerable.
- #fetch(key, default = nil) ⇒ Object
-
#freeze ⇒ Object
Freeze the underlying data.
- #has_key?(key) ⇒ Boolean
-
#initialize(mixedCaseHashObject, options = {}) ⇒ IdiomaticRubyWrapper
constructor
Creates an IdiomaticRubyWrapper around the mixed case Hash object.
- #keys ⇒ Object
- #method_missing(method_sym, *arguments) ⇒ Object
-
#mixedCaseHashObject mixed case Hash object=(mixed) ⇒ Object
Creates an IdiomaticRubyWrapper around the mixed case Hash object.
- #size ⇒ Object
-
#to_hash(*args) ⇒ Object
Generate a symbolized Hash object representing the underlying Hash in a Ruby friendly format.
-
#to_json(*args) ⇒ Object
Converts the current wrapped mixedCase object to JSON using mixedCase syntax as expected by the Realtime API.
- #to_s ⇒ Object
- #values ⇒ Object
Methods included from Ably::Modules::MessagePack
Constructor Details
#initialize(mixedCaseHashObject, options = {}) ⇒ IdiomaticRubyWrapper
Creates an IdiomaticRubyWrapper around the mixed case Hash object
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 53 def initialize(mixedCaseHashObject, = {}) stop_at = .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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_sym, *arguments) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 128 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 |
Instance Attribute Details
#hash ⇒ Integer (readonly)
Returns Compute a hash-code for this hash. Two hashes with the same content will have the same hash code.
199 200 201 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 199 def hash attributes.hash end |
#Hash ⇒ Hash (readonly)
Returns Access to the raw Hash object provided to the constructer of this wrapper.
143 144 145 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 143 def attributes @attributes end |
#stop_at ⇒ Array<Symbol,String> (readonly)
Returns array of keys that this wrapper should stop wrapping at to preserve the underlying Hash as is.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 41 class IdiomaticRubyWrapper include Enumerable include Ably::Modules::Conversions include Ably::Modules::MessagePack attr_reader :stop_at # 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 # def initialize(mixedCaseHashObject, = {}) stop_at = .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 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 def []=(key, value) attributes[source_key_for(key)] = value end 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 def size attributes.size end def keys map { |key, value| key } end def values map { |key, value| value } end def has_key?(key) attributes.has_key?(source_key_for(key)) end # Method ensuring this {IdiomaticRubyWrapper} is {http://ruby-doc.org/core-2.1.3/Enumerable.html Enumerable} 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 # Compare object based on Hash equivalent 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 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 # @!attribute [r] Hash # @return [Hash] Access to the raw Hash object provided to the constructer of this wrapper def attributes @attributes end # Takes the underlying Hash object and returns it in as a JSON ready Hash object using snakeCase 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 }) 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 # Converts the current wrapped mixedCase object to JSON # using mixedCase syntax as expected by the Realtime API def to_json(*args) as_json(args).to_json end # 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 }) 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 # Method to create a duplicate of the underlying Hash object # Useful when underlying Hash is frozen def dup Ably::Models::IdiomaticRubyWrapper.new(attributes.dup, stop_at: stop_at.keys) end # Freeze the underlying data def freeze attributes.freeze end def to_s attributes.to_s end # @!attribute [r] hash # @return [Integer] Compute a hash-code for this hash. Two hashes with the same content will have the same hash code def hash attributes.hash end private def stop_at?(key) @stop_at.has_key?(key) end # 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. def source_key_for(symbolized_key) format_preferences = [ proc { |key_sym| convert_to_mixed_case(key_sym) }, proc { |key_sym| key_sym.to_sym }, proc { |key_sym| key_sym.to_s }, proc { |key_sym| convert_to_mixed_case(key_sym).to_sym }, proc { |key_sym| convert_to_lower_case(key_sym) }, proc { |key_sym| convert_to_lower_case(key_sym).to_sym }, proc { |key_sym| convert_to_mixed_case(key_sym, force_camel: true) }, proc { |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 end |
#stop_at array of keys that this wrapper should stop wrapping at to preserve the underlying Hash as is(arrayofkeysthatthiswrappershouldstopwrappingattopreservetheunderlyingHashasis) ⇒ Object (readonly)
Creates an IdiomaticRubyWrapper around the mixed case Hash object
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 53 def initialize(mixedCaseHashObject, = {}) stop_at = .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 |
Instance Method Details
#==(other) ⇒ Object
Compare object based on Hash equivalent
121 122 123 124 125 126 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 121 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) ⇒ Object
66 67 68 69 70 71 72 73 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 66 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) ⇒ Object
75 76 77 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 75 def []=(key, value) attributes[source_key_for(key)] = value end |
#as_json(*args) ⇒ Object
Takes the underlying Hash object and returns it in as a JSON ready Hash object using snakeCase for compability with the Ably service. Note name clashes are ignored and will result in loss of one or more values
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 152 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 ⇒ Hash
Returns Access to the raw Hash object provided to the constructer of this wrapper.
143 144 145 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 143 def attributes @attributes end |
#dup ⇒ Object
Method to create a duplicate of the underlying Hash object Useful when underlying Hash is frozen
184 185 186 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 184 def dup Ably::Models::IdiomaticRubyWrapper.new(attributes.dup, stop_at: stop_at.keys) end |
#each ⇒ Object
Method ensuring this Ably::Modules::Conversions#IdiomaticRubyWrapper is Enumerable
110 111 112 113 114 115 116 117 118 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 110 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 |
#fetch(key, default = nil) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 79 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 ⇒ Object
Freeze the underlying data
189 190 191 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 189 def freeze attributes.freeze end |
#has_key?(key) ⇒ Boolean
105 106 107 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 105 def has_key?(key) attributes.has_key?(source_key_for(key)) end |
#keys ⇒ Object
97 98 99 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 97 def keys map { |key, value| key } end |
#mixedCaseHashObject mixed case Hash object=(mixed) ⇒ Object
Creates an IdiomaticRubyWrapper around the mixed case Hash object
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 53 def initialize(mixedCaseHashObject, = {}) stop_at = .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 |
#size ⇒ Object
93 94 95 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 93 def size attributes.size end |
#to_hash(*args) ⇒ Object
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
174 175 176 177 178 179 180 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 174 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) ⇒ Object
Converts the current wrapped mixedCase object to JSON using mixedCase syntax as expected by the Realtime API
165 166 167 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 165 def to_json(*args) as_json(args).to_json end |
#to_s ⇒ Object
193 194 195 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 193 def to_s attributes.to_s end |
#values ⇒ Object
101 102 103 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 101 def values map { |key, value| value } end |