Class: TaintedHash
- Inherits:
-
Hash
- Object
- Hash
- TaintedHash
- Defined in:
- lib/tainted_hash.rb
Defined Under Namespace
Modules: Controller, RailsMethods Classes: UnexposedError
Constant Summary collapse
- VERSION =
"0.3.0"
Class Attribute Summary collapse
-
.default_hash_class ⇒ Object
Returns the value of attribute default_hash_class.
Class Method Summary collapse
Instance Method Summary collapse
-
#[](key) ⇒ Object
Public: Gets the value for the key but does not expose the key for the Hash.
-
#[]=(key, value) ⇒ Object
Public: Attempts to set the key of a frozen hash.
-
#delete(key) ⇒ Object
Public: Deletes the value from both the internal and current Hash.
-
#dup ⇒ Object
Public: Produces a copy of the current Hash with the same set of exposed keys as the original Hash.
-
#each ⇒ Object
Public: Enumerates through the exposed keys and valuesfor the hash.
-
#expose(*keys) ⇒ Object
Public: Exposes one or more keys for the hash.
-
#expose_all ⇒ Object
Public: Exposes every key of the hash.
-
#extra_keys ⇒ Object
Public: Gets the unexposed keys from the original Hash.
-
#fetch(key, *default) ⇒ Object
Public: Fetches the value in the hash at key, or a sensible default.
-
#include?(key) ⇒ Boolean
(also: #key?, #has_key?)
Public: Checks whether the given key has been exposed or not.
-
#initialize(hash = nil, new_class = nil) ⇒ TaintedHash
constructor
A Tainted Hash only exposes expected keys.
- #inspect ⇒ Object
-
#merge(hash) ⇒ Object
Public: Merges the given hash with the internal and a dup of the current Hash.
-
#original_hash ⇒ Object
Public: Gets the original hash that is being wrapped.
-
#to_hash ⇒ Object
Public: Builds a normal Hash of the exposed values from this hash.
-
#update(hash) ⇒ Object
(also: #merge!)
Public: Updates the internal and current Hash with the given Hash.
-
#values_at(*keys) ⇒ Object
Public: Returns the values for the given keys, and exposes the keys.
- #with_indifferent_access ⇒ Object
Constructor Details
#initialize(hash = nil, new_class = nil) ⇒ TaintedHash
A Tainted Hash only exposes expected keys. You can either expose them manually, or through common Hash methods like #values_at or #slice. Once created, the internal Hash is frozen from future updates.
hash - Optional Hash used internally. new_class - Optional class used to create basic Hashes. Default: Hash.
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/tainted_hash.rb', line 42 def initialize(hash = nil, new_class = nil) @new_class = new_class || (hash && hash.class) || self.class.default_hash_class @original_hash = (hash && hash.dup) || @new_class.new @exposed_nothing = true @original_hash.keys.each do |key| key_s = key.to_s next if key_s == key @original_hash[key_s] = @original_hash.delete(key) end end |
Class Attribute Details
.default_hash_class ⇒ Object
Returns the value of attribute default_hash_class.
15 16 17 |
# File 'lib/tainted_hash.rb', line 15 def default_hash_class @default_hash_class end |
Class Method Details
.on_no_expose(&block) ⇒ Object
20 21 22 |
# File 'lib/tainted_hash.rb', line 20 def self.on_no_expose(&block) @on_no_expose = block end |
.trigger_no_expose(hash) ⇒ Object
24 25 26 |
# File 'lib/tainted_hash.rb', line 24 def self.trigger_no_expose(hash) @on_no_expose.call hash if @on_no_expose && (!block_given? || yield) end |
Instance Method Details
#[](key) ⇒ Object
Public: Gets the value for the key but does not expose the key for the Hash.
key - A String key to retrieve.
Returns the value of at the key in Hash.
112 113 114 115 116 |
# File 'lib/tainted_hash.rb', line 112 def [](key) key_s = key.to_s return if !@original_hash.key?(key_s) get_original_hash_value(key_s) end |
#[]=(key, value) ⇒ Object
Public: Attempts to set the key of a frozen hash.
key - String key to set. value - Value of the key.
Returns nothing
124 125 126 127 |
# File 'lib/tainted_hash.rb', line 124 def []=(key, value) key_s = key.to_s super(key_s, set_original_hash_value(key_s, value)) end |
#delete(key) ⇒ Object
Public: Deletes the value from both the internal and current Hash.
key - A String key to delete.
Returns the value from the key.
134 135 136 137 138 |
# File 'lib/tainted_hash.rb', line 134 def delete(key) key_s = key.to_s super(key_s) @original_hash.delete key_s end |
#dup ⇒ Object
Public: Produces a copy of the current Hash with the same set of exposed keys as the original Hash.
Returns a dup of this TaintedHash.
165 166 167 168 169 |
# File 'lib/tainted_hash.rb', line 165 def dup super.tap do |duplicate| duplicate.instance_variable_set :@original_hash, @original_hash.dup end end |
#each ⇒ Object
Public: Enumerates through the exposed keys and valuesfor the hash.
Yields the String key, and the value.
Returns nothing.
200 201 202 203 204 |
# File 'lib/tainted_hash.rb', line 200 def each self.class.trigger_no_expose(self) { @exposed_nothing && size.zero? } block = block_given? ? Proc.new : nil super(&block) end |
#expose(*keys) ⇒ Object
Public: Exposes one or more keys for the hash.
*keys - One or more String keys.
Returns this TaintedHash.
59 60 61 62 63 64 65 66 |
# File 'lib/tainted_hash.rb', line 59 def expose(*keys) @exposed_nothing = false keys.each do |key| key_s = key.to_s self[key_s] = @original_hash[key_s] if @original_hash.key?(key_s) end self end |
#expose_all ⇒ Object
Public: Exposes every key of the hash.
Returns this TaintedHash.
71 72 73 74 75 76 77 |
# File 'lib/tainted_hash.rb', line 71 def expose_all @exposed_nothing = false @original_hash.each do |key, value| self[key] = value end self end |
#extra_keys ⇒ Object
Public: Gets the unexposed keys from the original Hash.
Returns an Array of String keys.
82 83 84 |
# File 'lib/tainted_hash.rb', line 82 def extra_keys @original_hash.keys - self.keys end |
#fetch(key, *default) ⇒ Object
Public: Fetches the value in the hash at key, or a sensible default.
key - A String key to retrieve. default - A sensible default.
Returns the value of the key, or the default.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/tainted_hash.rb', line 92 def fetch(key, *default) raise ArgumentError, "wrong number of arguments (#{default.size + 1} for 1..2)" if default.size > 1 key_s = key.to_s if @original_hash.key?(key_s) self[key_s] elsif block_given? yield elsif !default.empty? default[0] else raise KeyError, "key not found: #{key}" end end |
#include?(key) ⇒ Boolean Also known as: key?, has_key?
Public: Checks whether the given key has been exposed or not.
key - A String key.
Returns true if exposed, or false.
145 146 147 |
# File 'lib/tainted_hash.rb', line 145 def include?(key) super(key.to_s) end |
#inspect ⇒ Object
224 225 226 |
# File 'lib/tainted_hash.rb', line 224 def inspect %(#<#{self.class}:#{object_id} @hash=#{@original_hash.inspect} @exposed=#{keys.inspect}>) end |
#merge(hash) ⇒ Object
Public: Merges the given hash with the internal and a dup of the current Hash.
hash - A Hash with String keys.
Returns a dup of this TaintedHash.
177 178 179 |
# File 'lib/tainted_hash.rb', line 177 def merge(hash) dup.update(hash) end |
#original_hash ⇒ Object
Public: Gets the original hash that is being wrapped.
Returns a Hash.
31 32 33 |
# File 'lib/tainted_hash.rb', line 31 def original_hash untaint_original_hash(@original_hash) end |
#to_hash ⇒ Object
Public: Builds a normal Hash of the exposed values from this hash.
Returns a Hash.
209 210 211 212 213 214 215 216 217 218 |
# File 'lib/tainted_hash.rb', line 209 def to_hash hash = @new_class.new each do |key, value| hash[key] = case value when TaintedHash then value.to_hash else value end end hash end |
#update(hash) ⇒ Object Also known as: merge!
Public: Updates the internal and current Hash with the given Hash.
hash - A Hash with String keys.
Returns this TaintedHash.
186 187 188 189 190 191 |
# File 'lib/tainted_hash.rb', line 186 def update(hash) hash.each do |key, value| self[key.to_s] = value end self end |
#values_at(*keys) ⇒ Object
Public: Returns the values for the given keys, and exposes the keys.
*keys - One or more String keys.
Returns an Array of the values (or nil if there is no value) for the keys.
157 158 159 |
# File 'lib/tainted_hash.rb', line 157 def values_at(*keys) keys.map { |k| self[k] } end |
#with_indifferent_access ⇒ Object
220 221 222 |
# File 'lib/tainted_hash.rb', line 220 def with_indifferent_access self end |