Class: CushionDefaults::DefaultsHash
- Inherits:
-
Hash
- Object
- Hash
- CushionDefaults::DefaultsHash
- Defined in:
- lib/cushion_defaults/defaults_hash.rb
Overview
Slight expansion of @Hash@.
Records a link to @owner@ and will traverse up the chain of owners looking for a default value for @x@ if no default value for @x@ is specified.
In general, a program should treat this class like a normal Hash, with two salient differences:
-
The #+ method has been overridden.
-
The #has_ish_key?, which returns true if this or a parent has the key specified.
Instance Attribute Summary collapse
-
#frozen_defaults ⇒ Object
readonly
Set of defaults frozen.
-
#polite_defaults ⇒ Object
readonly
Set of defaults marked as polite.
-
#pushy_defaults ⇒ Object
readonly
Set of defaults marked as pushy.
Custom/New Hash Methods collapse
-
#+(y) ⇒ DefaultsHash
Allows addition of hashes.
-
#[]=(key, val) ⇒ Object
Custom key/value set method.
-
#clear ⇒ Object
Custom clear method.
-
#delete(key) ⇒ Object
Custom delete method.
-
#has_ish_key?(key) ⇒ Boolean
Determine if this @DefaultsHash@ “ish” has a key.
-
#ish_keys ⇒ Object
Returns the keys of this class’ @defaults@ as well as those of parent classes (if extant).
Frozen Defaults collapse
-
#default_frozen?(key) ⇒ boolean
True if the current default (not its value) is frozen, false otherwise.
-
#freeze_default!(key) ⇒ Set
Freezes the specified default (not its value).
-
#thaw_default!(key) ⇒ Set
Thaws the specified default (not its value).
Pushy Defaults collapse
-
#not_pushy!(sym) ⇒ Object
Mark sym as not pushy / polite.
-
#not_pushy?(sym) ⇒ Boolean
Inverse of #pushy?.
-
#pushy!(sym) ⇒ Object
Mark sym as pushy.
-
#pushy?(sym) ⇒ Boolean
Determine whether this or a parent defaults hash has declared sym to be pushy.
-
#pushy_in_parent?(sym) ⇒ Boolean
Determine whether a parent defaults hash has declared sym to be pushy.
Debug collapse
-
#where_is_that_default_again(sym) ⇒ Object
Returns the nearest class that has a default set for sym, or nil if no default is set for it.
Instance Method Summary collapse
-
#add_methods_as_needed(key) ⇒ Object
Tell owner to add readers and writers for a newly-added key, as configured.
-
#initialize(owner) ⇒ DefaultsHash
constructor
A new instance of DefaultsHash.
-
#remove_methods_as_needed(key) ⇒ Object
Tell owner to remove methods for a newly-deleted key, as configured.
Constructor Details
#initialize(owner) ⇒ DefaultsHash
Returns a new instance of DefaultsHash.
23 24 25 26 27 28 29 30 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 23 def initialize(owner) self.default_proc = proc { |_hash, key| super_defaults[key] } # look in the superclass' @defaults@ hash, if a key is not found in this class' @defaults@ hash @owner = owner @pushy_defaults = Set.new @polite_defaults = Set.new @frozen_defaults = Set.new end |
Instance Attribute Details
#frozen_defaults ⇒ Object (readonly)
Set of defaults frozen
20 21 22 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 20 def frozen_defaults @frozen_defaults end |
#polite_defaults ⇒ Object (readonly)
Set of defaults marked as polite.
18 19 20 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 18 def polite_defaults @polite_defaults end |
#pushy_defaults ⇒ Object (readonly)
Set of defaults marked as pushy.
16 17 18 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 16 def pushy_defaults @pushy_defaults end |
Instance Method Details
#+(y) ⇒ DefaultsHash
This method was incorrectly programmed to modify self in place. In a future release, this will be changed, and the current behavior should not be depended upon.
Allows addition of hashes. Works as expected.
Note that this also enables +=.
If @key@ is in @self@ and @y@, then the value of @y@ will replace that in @self@ in the resulting @Hash@.
45 46 47 48 49 50 51 52 53 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 45 def +(y) y.each do |key, val| if has_key? key CushionDefaults.log("As #{@owner} already has the default #{key} defined, this call to + is overwriting it.", :info) end self[key] = val end self end |
#[]=(key, val) ⇒ Object
Custom key/value set method. Prevents writing a default when a parent has it marked as pushy (and it is not otherwise marked as polite), and it also tells @owner to add methods as needed (if writers or readers are to be automatically added).
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 60 def []=(key,val) key = key.to_sym if !@polite_defaults.include?(key) && pushy_in_parent?(key) raise ArgumentError, 'You cannot set a default value marked as pushy in a parent class without first marking it as polite.' end if has_key?(key) && default_frozen?(key) raise FrozenDefaultError.new(@owner, key), "#{@owner}.defaults[:#{key} is frozen!" end unless has_ish_key?(key) add_methods_as_needed(key) end super(key, val) end |
#add_methods_as_needed(key) ⇒ Object
Tell owner to add readers and writers for a newly-added key, as configured.
231 232 233 234 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 231 def add_methods_as_needed(key) @owner.send :_update_cushion_reader, key @owner.cushion_writer key.to_sym if CushionDefaults.conf.update_writers end |
#clear ⇒ Object
Custom clear method. We need to check whether or not we should delete the methods associated with the keys, and we need to wipe @pushy_defaults and @polite_defaults.
90 91 92 93 94 95 96 97 98 99 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 90 def clear keys.each do |key| remove_methods_as_needed(key.to_sym) @owner.send :_cascade_polite_symbol, key if @pushy_defaults.delete? key @owner.send :_cascade_pushy_symbol, key if @pushy_defaults.delete? key end @frozen_defaults.clear super CushionDefaults.log("All defaults cleared for #{@owner}.", :info) end |
#default_frozen?(key) ⇒ boolean
Returns true if the current default (not its value) is frozen, false otherwise.
136 137 138 139 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 136 def default_frozen? key key = key.to_sym @frozen_defaults.include? key end |
#delete(key) ⇒ Object
Custom delete method. We need to check whether or not we should delete the methods associated with the key, and we need to remove the key from @pushy_defaults and @polite_defaults if it exists.
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 76 def delete(key) key = key.to_sym return unless has_key? key remove_methods_as_needed(key) #TODO Need some better way to handle when @pushy_defaults is emptied or cleared. Need to talk to children. @owner.send :_cascade_polite_symbol, key if @pushy_defaults.delete? key @owner.send :_cascade_pushy_symbol, key if @polite_defaults.delete? key @frozen_defaults.delete(key) super(key) CushionDefaults.log("Default for #{key} in #{@owner} deleted.") end |
#freeze_default!(key) ⇒ Set
Freezes the specified default (not its value).
147 148 149 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 147 def freeze_default! key @frozen_defaults.add? key end |
#has_ish_key?(key) ⇒ Boolean
Determine if this @DefaultsHash@ “ish” has a key. In other words, whether it or any Hashes up the chain of @super_defaults@ has the key @key@.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 105 def has_ish_key?(key) # Obviously, this method gives much better performance than calling @ish_keys.include?(key)@. if has_key?(key) true # super_defaults could theoretically be either a DefaultsHash or a regular Hash elsif super_defaults if super_defaults.respond_to? :has_ish_key? super_defaults.has_ish_key?(key) else super_defaults.has_key?(key) end else false end end |
#ish_keys ⇒ Object
Returns the keys of this class’ @defaults@ as well as those of parent classes (if extant).
124 125 126 127 128 129 130 131 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 124 def ish_keys if super_defaults # super_defaults could be either a DefaultsHash or a regular Hash (keys + (super_defaults.respond_to?(:ish_keys) ? super_defaults.ish_keys : super_defaults.keys)).uniq else keys end end |
#not_pushy!(sym) ⇒ Object
Mark sym as not pushy / polite.
174 175 176 177 178 179 180 181 182 183 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 174 def not_pushy!(sym) @pushy_defaults.delete(sym) @polite_defaults.add(sym) @owner.send :_cascade_polite_symbol, sym # we may need now to define a reader for it @owner.send :_update_cushion_reader, sym CushionDefaults.log("#{sym} in #{@owner} is now polite.") end |
#not_pushy?(sym) ⇒ Boolean
Inverse of #pushy?
207 208 209 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 207 def not_pushy?(sym) !pushy?(sym) end |
#pushy!(sym) ⇒ Object
Mark sym as pushy
163 164 165 166 167 168 169 170 171 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 163 def pushy!(sym) CushionDefaults.conf.we_have_a_pushy! @pushy_defaults.add(sym) @polite_defaults.delete(sym) @owner.send :_cascade_pushy_symbol, sym CushionDefaults.log(":#{sym} in #{@owner} is now pushy.") end |
#pushy?(sym) ⇒ Boolean
Determine whether this or a parent defaults hash has declared sym to be pushy.
186 187 188 189 190 191 192 193 194 195 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 186 def pushy?(sym) if @polite_defaults.include?(sym) # white list has priority false elsif @pushy_defaults.include?(sym) true else pushy_in_parent?(sym) end end |
#pushy_in_parent?(sym) ⇒ Boolean
Determine whether a parent defaults hash has declared sym to be pushy.
198 199 200 201 202 203 204 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 198 def pushy_in_parent?(sym) if super_defaults.respond_to? :pushy? super_defaults.pushy?(sym) else false end end |
#remove_methods_as_needed(key) ⇒ Object
Tell owner to remove methods for a newly-deleted key, as configured.
242 243 244 245 246 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 242 def remove_methods_as_needed(key) @owner.remove_cushion_reader key.to_sym if CushionDefaults.conf.update_readers @owner.remove_bang_reader key.to_sym if CushionDefaults.conf.update_readers @owner.remove_cushion_writer key.to_sym if CushionDefaults.conf.update_writers end |
#thaw_default!(key) ⇒ Set
Thaws the specified default (not its value).
156 157 158 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 156 def thaw_default! key @frozen_defaults.delete? key end |
#where_is_that_default_again(sym) ⇒ Object
Returns the nearest class that has a default set for sym, or nil if no default is set for it.
214 215 216 217 218 219 220 221 222 |
# File 'lib/cushion_defaults/defaults_hash.rb', line 214 def where_is_that_default_again(sym) if has_key? sym @owner elsif super_defaults.respond_to? :where_is_that_default_again super_defaults.where_is_that_default_again sym else nil end end |