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 constructor 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 camelCase for compability with the Ably service.
-
#attributes ⇒ Hash
Access to the raw Hash object provided to the constructor 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.
- #empty? ⇒ Boolean
- #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 snakedCase 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
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 54 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
133 134 135 136 137 138 139 140 141 142 143 144 |
# File '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 |
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.
204 205 206 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 204 def hash attributes.hash end |
#Hash ⇒ Hash (readonly)
Returns Access to the raw Hash object provided to the constructor of this wrapper.
148 149 150 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 148 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.
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 230 231 232 233 234 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 42 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 empty? attributes.empty? 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 constructor of this wrapper def attributes @attributes end # 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 } 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 snakedCase 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 = [ 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 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
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 54 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
126 127 128 129 130 131 |
# File '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) ⇒ Object
67 68 69 70 71 72 73 74 |
# File '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) ⇒ Object
76 77 78 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 76 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 camelCase for compability with the Ably service. Note name clashes are ignored and will result in loss of one or more values
157 158 159 160 161 162 163 164 165 166 |
# File '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 ⇒ Hash
Returns Access to the raw Hash object provided to the constructor of this wrapper.
148 149 150 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 148 def attributes @attributes end |
#dup ⇒ Object
Method to create a duplicate of the underlying Hash object Useful when underlying Hash is frozen
189 190 191 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 189 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
115 116 117 118 119 120 121 122 123 |
# File '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? ⇒ Boolean
98 99 100 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 98 def empty? attributes.empty? end |
#fetch(key, default = nil) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File '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 ⇒ Object
Freeze the underlying data
194 195 196 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 194 def freeze attributes.freeze end |
#has_key?(key) ⇒ Boolean
110 111 112 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 110 def has_key?(key) attributes.has_key?(source_key_for(key)) end |
#keys ⇒ Object
102 103 104 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 102 def keys map { |key, value| key } end |
#mixedCaseHashObject mixed case Hash object=(mixed) ⇒ Object
Creates an IdiomaticRubyWrapper around the mixed case Hash object
54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 54 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
94 95 96 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 94 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
179 180 181 182 183 184 185 |
# File '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) ⇒ Object
Converts the current wrapped mixedCase object to JSON using snakedCase syntax as expected by the Realtime API
170 171 172 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 170 def to_json(*args) as_json(args).to_json end |
#to_s ⇒ Object
198 199 200 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 198 def to_s attributes.to_s end |
#values ⇒ Object
106 107 108 |
# File 'lib/ably/models/idiomatic_ruby_wrapper.rb', line 106 def values map { |key, value| value } end |