Class: HashDelegator
- Inherits:
-
Object
- Object
- HashDelegator
- Defined in:
- lib/hash_delegator.rb,
lib/hash_delegator/version.rb
Overview
Provides delegation and basic validation for Hashes
Constant Summary collapse
- MUTATING_METHODS =
Methods that mutate the internal hash, these cannot be called publicly.
Set[ :clear, :delete, :update, :delete_if, :keep_if, :compact!, :filter!, :merge!, :reject!, :select!, :transform_keys!, :transform_values!, :default=, :default_proc=, :compare_by_identity, :rehash, :replace, :initialize_copy, :shift, :store ].freeze
- CLOSED_METHODS =
Methods that are closed (in the algebraic sense) meaning that they will not remove required keys.
Set[ :compact, :merge ].freeze
- VERSION =
"0.1.2"
Class Method Summary collapse
-
.default(value = nil, &block) ⇒ HashDelegator
Specify the default value if the value is a Proc or a block is passed each hash’s default_proc attribute will be set.
-
.default_value ⇒ Object
Return the default value.
-
.key_transformer ⇒ Object
Return the key transformer.
- .require(*attributes) ⇒ Object deprecated Deprecated.
-
.required(*attributes) ⇒ HashDelegator
Specifiy required attributes.
-
.required_attributes ⇒ Array?
Return required attributes or nil.
-
.transform_keys(&block) ⇒ Object
Specify the key transformer.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Return true if the other object is of the same class and the numerical hash of the other object and this object are equal.
-
#===(other) ⇒ Object
Return true if the other object has all of this objects required attributes.
-
#[](key) ⇒ Object
Return the value associated with the given key.
-
#eql?(other) ⇒ Boolean
Return true if the other object has the same numerical hash as this object.
-
#except(*keys) ⇒ Hash, HashDelegator
If the given keys include any required attributes the hash will be duplicated and except will be called on the duplicated hash.
-
#hash ⇒ Integer
Return the numerical hash of the decorated hash.
-
#initialize(hash = EMPTY_HASH) ⇒ HashDelegator
constructor
Initialize the HashDelegator with the given hash.
-
#method_missing(method, *args, &block) ⇒ Object
If the method is a key of the internal hash return it’s value.
-
#respond_to_missing?(method, include_all) ⇒ Boolean
Return true if the superclass responds to the method or if the method is a key of the internal hash or if the hash responds to this method.
-
#slice(*keys) ⇒ Hash, HashDelegator
If the given keys include all of the required attributes a new HashDelegator will be returned with only the specified keys.
-
#to_hash ⇒ Hash
(also: #to_h)
Return a duplicate of the delegated hash.
- #to_s ⇒ Object (also: #inspect)
Constructor Details
#initialize(hash = EMPTY_HASH) ⇒ HashDelegator
Initialize the HashDelegator with the given hash. If the hash is not frozen it will be duplicated. If a key transformer is specified the hashes keys will be processed with it (duplicating the original hash). The hash will be validated for the existance of the required attributes (note that a key with a nil value still exists in the hash).
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 |
# File 'lib/hash_delegator.rb', line 124 def initialize(hash = EMPTY_HASH) raise 'HashDelegator should not be initialized' if instance_of?(HashDelegator) @hash = if self.class.key_transformer hash.transform_keys(&self.class.key_transformer) elsif hash.frozen? hash else hash.dup end if self.class.default_value.is_a?(Proc) @hash.default_proc = self.class.default_value else @hash.default = self.class.default_value end if self.class.required_attributes self.class.required_attributes.each do |attribute| attribute = self.class.key_transformer.call(attribute) if self.class.key_transformer raise "#{attribute.inspect} is required, but is missing" unless key?(attribute) end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
If the method is a key of the internal hash return it’s value. If the internal hash responds to the method forward the method to the hash. If the method is ‘closed’ retrun a new HashDelegator otherwise return the raw result. If none of these conditions hold call the superclass’ method_missing.
273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/hash_delegator.rb', line 273 def method_missing(method, *args, &block) return @hash[method] if @hash.key?(method) if hash_respond_to?(method) result = @hash.public_send(method, *args, &block) return result unless CLOSED_METHODS.include?(method) return self.class.new(result) end super end |
Class Method Details
.default(value = nil, &block) ⇒ HashDelegator
Specify the default value if the value is a Proc or a block is passed each hash’s default_proc attribute will be set.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/hash_delegator.rb', line 46 def default(value = nil, &block) if block @default_value = block return self end if value.is_a?(Proc) && value.lambda? && value.arity != 2 lambda = value value = ->(*args) { lambda.call(*args.slice(0, lambda.arity)) } end @default_value = value self end |
.default_value ⇒ Object
Return the default value
63 64 65 66 67 |
# File 'lib/hash_delegator.rb', line 63 def default_value return @default_value if @default_value superclass.default_value if superclass.respond_to?(:default_value) end |
.key_transformer ⇒ Object
Return the key transformer
75 76 77 78 79 |
# File 'lib/hash_delegator.rb', line 75 def key_transformer return @key_transformer if @key_transformer superclass.key_transformer if superclass.respond_to?(:key_transformer) end |
.require(*attributes) ⇒ Object
35 36 37 38 |
# File 'lib/hash_delegator.rb', line 35 def require(*attributes) warn 'HashDelegator.require is deprecated' required(*attrbutes) end |
.required(*attributes) ⇒ HashDelegator
Specifiy required attributes
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/hash_delegator.rb', line 23 def required(*attributes) @required_attributes = if superclass.respond_to?(:required_attributes) && !superclass.required_attributes.nil? superclass.required_attributes + attributes else attributes end self end |
.required_attributes ⇒ Array?
Return required attributes or nil
13 14 15 16 17 |
# File 'lib/hash_delegator.rb', line 13 def required_attributes return @required_attributes if @required_attributes superclass.required_attributes if superclass.respond_to?(:required_attributes) end |
.transform_keys(&block) ⇒ Object
Specify the key transformer
70 71 72 |
# File 'lib/hash_delegator.rb', line 70 def transform_keys(&block) @key_transformer = block end |
Instance Method Details
#==(other) ⇒ Boolean
Return true if the other object is of the same class and the numerical hash of the other object and this object are equal.
242 243 244 |
# File 'lib/hash_delegator.rb', line 242 def ==(other) other.instance_of?(self.class) && eql?(other) end |
#===(other) ⇒ Object
Return true if the other object has all of this objects required attributes.
229 230 231 232 233 234 |
# File 'lib/hash_delegator.rb', line 229 def ===(other) required = self.class.required_attributes other.respond_to?(:keys) && (common = other.keys & required) && common.size == other.keys.size && common.size == required.size end |
#[](key) ⇒ Object
Return the value associated with the given key. If a key transformer is special the key will be transformed first. If the key is missing the default value will be return (nil unless specified).
203 204 205 206 207 208 209 |
# File 'lib/hash_delegator.rb', line 203 def [](key) if self.class.key_transformer @hash[self.class.key_transformer.call(key)] else @hash[key] end end |
#eql?(other) ⇒ Boolean
Return true if the other object has the same numerical hash as this object.
222 223 224 |
# File 'lib/hash_delegator.rb', line 222 def eql?(other) @hash.hash == other.hash end |
#except(*keys) ⇒ Hash, HashDelegator
If the given keys include any required attributes the hash will be duplicated and except will be called on the duplicated hash. Otherwise a new instance of the HashDelegator will be return without the specified keys.
157 158 159 160 161 162 163 164 165 |
# File 'lib/hash_delegator.rb', line 157 def except(*keys) common = keys & self.class.required_attributes if common.empty? self.class.new(@hash.except(*keys)) else to_hash.except(*keys) end end |
#hash ⇒ Integer
Return the numerical hash of the decorated hash.
214 215 216 |
# File 'lib/hash_delegator.rb', line 214 def hash @hash.hash end |
#respond_to_missing?(method, include_all) ⇒ Boolean
DO NOT USE DIRECTLY
Return true if the superclass responds to the method or if the method is a key of the internal hash or if the hash responds to this method. Otherwise return false.
257 258 259 |
# File 'lib/hash_delegator.rb', line 257 def respond_to_missing?(method, include_all) super || key?(method) || hash_respond_to?(method) end |
#slice(*keys) ⇒ Hash, HashDelegator
If the given keys include all of the required attributes a new HashDelegator will be returned with only the specified keys. Otherwise a internal hash will be duplicated and slice will be called on the duplicated hash.
174 175 176 177 178 179 180 181 182 183 |
# File 'lib/hash_delegator.rb', line 174 def slice(*keys) required = self.class.required_attributes common = keys & required if keys.size == common.size && common.size == required.size self.class.new(@hash.slice(*keys)) else to_hash.slice(*keys) end end |
#to_hash ⇒ Hash Also known as: to_h
Return a duplicate of the delegated hash.
188 189 190 |
# File 'lib/hash_delegator.rb', line 188 def to_hash @hash.dup end |
#to_s ⇒ Object Also known as: inspect
193 194 195 |
# File 'lib/hash_delegator.rb', line 193 def to_s "#<#{self.class} #{@hash.inspect}>" end |