Module: CushionDefaults::ClassMethods
- Defined in:
- lib/cushion_defaults/class_methods.rb
Overview
A series of class methods to be plopped into any class that includes CushionDefaults.
Instance Attribute Summary collapse
-
#defaults ⇒ Object
Reader for the @defaults@ @DefaultsHash@.
-
#descendents ⇒ Object
readonly
Reader for the @defaults@ @DefaultsHash@.
Mass Default Setting Methods collapse
-
#defaults_from_yaml(file_name = nil) ⇒ Object
Load in the defaults for this class from a YAML file.
-
#initialize_defaults_hash ⇒ Object
private
Either set up or wipe @defaults.
Reader/Writer collapse
-
#bang_reader(*syms) ⇒ Object
Identical to #cushion_reader with one important exception: after determining the default value, @bang_reader@ goes on to crystallize this default value for the instance.
-
#cushion(*syms) ⇒ Object
Sets up both #cushion_readers and #cushion_writers for @syms@.
-
#cushion_defaults ⇒ Object
Defines #cushion_readers and #cushion_writers for all of this class’ @defaults@.
-
#cushion_reader(*syms) ⇒ Object
Sets up a cushion_reader for each :sym in @syms@.
-
#cushion_readers_for_defaults ⇒ Object
Defines #cushion_readers for all of this class’ @defaults@.
-
#cushion_writer(*syms) ⇒ Object
Sets up a cushion_writer for each :sym in @syms@.
- #remove_bang(sym) ⇒ Object deprecated Deprecated.
-
#remove_cushion_bang(sym) ⇒ Object
Undefines any bang method for sym in this class (if present).
-
#remove_cushion_reader(sym) ⇒ Object
Undefines the cushion_reader for sym in this class (if present).
-
#remove_cushion_writer(sym) ⇒ Object
Undefines any writer for sym in this class (if present).
- #remove_reader(sym) ⇒ Object deprecated Deprecated.
- #remove_writer(sym) ⇒ Object deprecated Deprecated.
Freeze/Thaw Defaults collapse
-
#deep_freeze_default(*syms) ⇒ Object
In addition to preventing the @default@ from being set to a new value (see #freeze_default), also freezes the value to which @default@ is currently set.
-
#deep_freeze_defaults ⇒ Object
Calls #deep_freeze_default for all defaults.
-
#freeze_default(*syms) ⇒ Object
Prevents a default from being set to a new value.
-
#freeze_defaults ⇒ Object
Calls #freeze_default for all defaults.
-
#thaw_default(*syms) ⇒ Object
Thaws a frozen default, allowing it to be set to a new value.
-
#thaw_defaults ⇒ Object
Calls #thaw_default for all defaults.
Pushy/Polite Defaults collapse
-
#make_polite(*syms) ⇒ Object
Declare each sym to be polite.
-
#make_pushy(*syms) ⇒ Object
Declare each sym to be pushy.
Instance Method Summary collapse
-
#inherited(inheritor) ⇒ Object
private
Ensure that if class @Klass@ includes @CushionDefaults@, then any class that subclasses @Klass@ will include it as well.
-
#set_default(key, val) ⇒ Object
Equivalent to @@defaults = val@.
Instance Attribute Details
#defaults ⇒ Object
Reader for the @defaults@ @DefaultsHash@.
8 9 10 |
# File 'lib/cushion_defaults/class_methods.rb', line 8 def defaults @defaults end |
#descendents ⇒ Object (readonly)
Reader for the @defaults@ @DefaultsHash@.
8 9 10 |
# File 'lib/cushion_defaults/class_methods.rb', line 8 def descendents @descendents end |
Instance Method Details
#bang_reader(*syms) ⇒ Object
Identical to #cushion_reader with one important exception: after determining the default value, @bang_reader@ goes on to crystallize this default value for the instance.
This is especially useful with proc cushions, as the below examples make clear.
Note that this method is equivalent to calling @instance.crystallize_default(:sym)@.
Note also, finally, that bang_readers can exist and function even if no #cushion_writers are defined.
227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/cushion_defaults/class_methods.rb', line 227 def bang_reader(*syms) syms.each do |sym| sym = sym.to_sym bang_sym = "#{sym}!".to_sym if self_or_parent_instance_method?(bang_sym) CushionDefaults.log("#{self} or a parent class already has a bang method #{bang_sym}", :warn) end define_method(bang_sym) do crystallize_default(sym) end CushionDefaults.log("bang_reader #{bang_sym} established for #{self}") end end |
#cushion(*syms) ⇒ Object
Sets up both #cushion_readers and #cushion_writers for @syms@. Will set up #bang_readers if Configuration#bang_things_up is true.
380 381 382 383 384 |
# File 'lib/cushion_defaults/class_methods.rb', line 380 def cushion(*syms) cushion_reader(*syms) cushion_writer(*syms) end |
#cushion_defaults ⇒ Object
Defines #cushion_readers and #cushion_writers for all of this class’ @defaults@.
Only defines @cushion_readers@ and @cushion_writers@ for this class defaults. All other getters are assumed to have been defined further up the class tree.
Thus, if class @A@ defines the default @var1@, and class @B@ defines the default @var2@, calling this method within class @B@ will only generate a getter for @var2@.
See also:
-
#cushion
-
#cushion_readers_for_defaults
408 409 410 411 |
# File 'lib/cushion_defaults/class_methods.rb', line 408 def cushion_defaults cushion *defaults.keys CushionDefaults.log("cushions established for #{self}'s defaults': #{defaults.keys.join(', ')}", :info) end |
#cushion_reader(*syms) ⇒ Object
Sets up a cushion_reader for each :sym in @syms@.
Each reader method checks if its instance variable (:sym) is defined. If it is, it returns that. If not, it returns the default value.
The only exception to this rule is when we have pushy defaults. If a default is pushy, we return it regardless of what this object’s instance variable may or may not be.
Note that if the default responds to :call (a proc, e.g.), then the default is instead called with the instance variable and the symbolic representation of the default requested. This allows for proc cushions.
Will set up #bang_readers if Configuration#bang_things_up is true.
The readers are named according to the same format as @attr_reader@.
106 107 108 109 110 |
# File 'lib/cushion_defaults/class_methods.rb', line 106 def cushion_reader(*syms) # send it with force==true syms.each { |sym| _update_cushion_reader(sym.to_sym, true) } bang_reader *syms if CushionDefaults.conf.bang_things_up end |
#cushion_readers_for_defaults ⇒ Object
Defines #cushion_readers for all of this class’ @defaults@.
Only defines @cushion_readers@ for defaults specified for this class. All other readers are assumed to have been defined further up the class tree.
Thus, if class @A@ defines the default @var1@, and class @B@ defines the default @var2@, calling this method within class @B@ will only generate a reader for @var2@.
393 394 395 |
# File 'lib/cushion_defaults/class_methods.rb', line 393 def cushion_readers_for_defaults cushion_reader *defaults.keys end |
#cushion_writer(*syms) ⇒ Object
Sets up a cushion_writer for each :sym in @syms@.
Each writer method carries out one of several checks.
First, it sees if the default is nil or an empty string, and if we care whether this is the case. If CushionDefaults::Configuration#ignore_attempts_to_set_nil is true, we will not set the instance variable to nil; and correspondingly, if CushionDefaults::Configuration#blank_str_is_nil is true, we will not set the instance variable to ”. This failure will be logged at the debug level unless CushionDefaults::Configuration#whiny_ignores, in which case it will be logged at warn.
Assuming the above checks pass, we next check whether the key we’re interested in is pushy. If it is, it warns us that the new value will have no effect since it will be overridden by a pushy default.
Finally, assuming it was not flagged as nilish, the variable is set to the new value.
The writers are named according to the same format as @attr_writer@.
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/cushion_defaults/class_methods.rb', line 261 def cushion_writer(*syms) syms.each do |sym| method_name = "#{sym}=".to_sym if self_or_parent_instance_method?(method_name) CushionDefaults.log("#{self} or a parent class already has what looks like a setter method for #{sym}", :warn) end instance_variable_sym = "@#{sym}".to_sym defaults_cache = @defaults define_method(method_name) do |y| if CushionDefaults.nilish? y if CushionDefaults.conf.whiny_ignores CushionDefaults.log("You are attempting to set a nilish value for #{sym}. This will not be recorded, and any value set will be deleted.", :warn) end else if CushionDefaults.conf.we_have_a_pushy? && defaults_cache.pushy?(sym) CushionDefaults.log("You are setting a value for #{sym}, but this is a pushy default and this value will not be returned by any cushion_readers.", :warn) end instance_variable_set(instance_variable_sym, y) end end CushionDefaults.log("cushion_writer #{sym}= established for #{self}") end end |
#deep_freeze_default(*syms) ⇒ Object
In addition to preventing the @default@ from being set to a new value (see #freeze_default), also freezes the value to which @default@ is currently set.
Does not throw an error when you attempt to freeze an already-frozen default, but it does log at warning level.
Equivalent to calling: @freeze_default :sym; defaults.freeze@
451 452 453 454 455 456 457 |
# File 'lib/cushion_defaults/class_methods.rb', line 451 def deep_freeze_default(*syms) syms.each do |sym| sym = sym.to_sym freeze_default sym defaults[sym].freeze end end |
#deep_freeze_defaults ⇒ Object
Calls #deep_freeze_default for all defaults.
462 463 464 |
# File 'lib/cushion_defaults/class_methods.rb', line 462 def deep_freeze_defaults deep_freeze_default *defaults.keys end |
#defaults_from_yaml(file_name = nil) ⇒ Object
Load in the defaults for this class from a YAML file. If @file_name@ is specified, this YAML file is loaded. Otherwise, CushionDefaults::Configuration#yaml_file_for is evaluated for the current class. By default, the yaml file for @Klass@ is expected to be at @config/cushion_defaults/klass.yaml@.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/cushion_defaults/class_methods.rb', line 44 def defaults_from_yaml(file_name = nil) if file_name yaml_path = "#{CushionDefaults.conf.yaml_source_full_path}#{file_name}.yaml" else yaml_path = CushionDefaults.conf.yaml_file_for(self) end yaml = YAML::load(File.open(yaml_path)) rescue {} if yaml.empty? CushionDefaults.log("No YAML configuration for class #{self} found at #{yaml_path}", CushionDefaults.conf.whiny_yaml ? :warn : :debug) end initialize_defaults_hash log_str = "New defaults added for #{self}:#{' [none]' if yaml.empty?}" # If automatic readers and writers are enabled, this will set them up as a consequence. yaml.each do |key, val| log_str << "\n\t\t#{key}: #{val}" @defaults[key.to_sym] = val end CushionDefaults.log(log_str, :info) end |
#freeze_default(*syms) ⇒ Object
A frozen default can still be overridden lower in the class hierarchy.
Prevents a default from being set to a new value. Freezing a default is permanent in the life of the program.
Note that while a frozen default is guaranteed to maintain its identity, its attributes can still be modified (e.g., by bang! methods). To prevent any modification to a default value, call #deep_freeze_default.
Does not throw an error when you attempt to freeze an already-frozen default, but it does log at warning level.
426 427 428 429 430 431 432 433 434 |
# File 'lib/cushion_defaults/class_methods.rb', line 426 def freeze_default(*syms) syms.each do |sym| sym = sym.to_sym unless defaults.freeze_default! sym # It returns nil if the key was already present in the Set CushionDefaults.log("Cannot freeze #{sym}: it was already frozen for #{self}", :warn) end end end |
#freeze_defaults ⇒ Object
Calls #freeze_default for all defaults.
439 440 441 |
# File 'lib/cushion_defaults/class_methods.rb', line 439 def freeze_defaults freeze_default *defaults.keys end |
#inherited(inheritor) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Ensure that if class @Klass@ includes @CushionDefaults@, then any class that subclasses @Klass@ will include it as well.
Called automatically whenever any class that includes @CushionDefaults@ is inherited.
557 558 559 560 561 |
# File 'lib/cushion_defaults/class_methods.rb', line 557 def inherited(inheritor) inheritor.send :include, CushionDefaults @descendents << inheritor super inheritor end |
#initialize_defaults_hash ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Either set up or wipe @defaults. Should not usually be called directly.
69 70 71 72 73 74 75 76 |
# File 'lib/cushion_defaults/class_methods.rb', line 69 def initialize_defaults_hash if @defaults # We need to maintain the identity of the hash, as child classes may have stored a reference to it @defaults.clear else @defaults = DefaultsHash.new(self) end end |
#make_polite(*syms) ⇒ Object
Declare each sym to be polite. A polite default operates as normal. This is useful to override an ancestor class’ pushy declaration.
This will automatically create #cushion_reader‘s for all variables made polite.
510 511 512 513 514 515 |
# File 'lib/cushion_defaults/class_methods.rb', line 510 def make_polite(*syms) syms.each do |sym| @defaults.not_pushy!(sym) _update_cushion_reader(sym, true) end end |
#make_pushy(*syms) ⇒ Object
Declare each sym to be pushy. Pushy defaults will be returned by #cushion_readers regardless of what the instance variables are set to.
This will automatically create #cushion_reader‘s for all variables made pushy.
499 500 501 502 503 504 |
# File 'lib/cushion_defaults/class_methods.rb', line 499 def make_pushy(*syms) syms.each do |sym| @defaults.pushy!(sym) _update_cushion_reader(sym, true) end end |
#remove_bang(sym) ⇒ Object
This method will delete any method of the form @sym!@, not just bang readers.
Undefines any bang method for sym in this class (if present). Does not affect ancestor classes.
315 316 317 318 319 320 321 322 |
# File 'lib/cushion_defaults/class_methods.rb', line 315 def remove_bang(sym) sym = "#{sym}!".to_sym if self_has_method?(sym) undef_method(sym) @have_bang_readers.delete(sym) CushionDefaults.log("bang reader #{sym} removed from #{self}", :info) end end |
#remove_cushion_bang(sym) ⇒ Object
This method will delete any method of the form @sym!@, not just bang readers.
Undefines any bang method for sym in this class (if present). Does not affect ancestor classes.
327 328 329 330 331 332 333 |
# File 'lib/cushion_defaults/class_methods.rb', line 327 def remove_cushion_bang(sym) sym = "#{sym}!".to_sym if @have_bang_readers.delete?(sym) && self_has_method?(sym) undef_method(sym) CushionDefaults.log("bang reader #{sym} removed from #{self}", :info) end end |
#remove_cushion_reader(sym) ⇒ Object
Undefines the cushion_reader for sym in this class (if present). Does not affect ancestor classes.
303 304 305 306 307 308 309 |
# File 'lib/cushion_defaults/class_methods.rb', line 303 def remove_cushion_reader(sym) sym = sym.to_sym if @have_cushion_readers.delete?(sym) && self_has_method?(sym) undef_method(sym) CushionDefaults.log("cushion_reader #{sym} removed from #{self}", :info) end end |
#remove_cushion_writer(sym) ⇒ Object
This method will delete any method of the format ‘sym=’, not just cushion_writers.
Undefines any writer for sym in this class (if present). Does not affect ancestor classes.
351 352 353 354 355 356 357 |
# File 'lib/cushion_defaults/class_methods.rb', line 351 def remove_cushion_writer(sym) write_sym = "#{sym}=".to_sym if @have_cushion_writers.delete?(write_sym) && self_has_method?(write_sym) undef_method(write_sym) CushionDefaults.log("cushion_writer #{sym}= removed from #{self}", :info) end end |
#remove_reader(sym) ⇒ Object
This method will delete any method of the form @sym@, not just cushion_readers.
Undefines the reader for sym in this class (if present). Does not affect ancestor classes.
292 293 294 295 296 297 298 299 |
# File 'lib/cushion_defaults/class_methods.rb', line 292 def remove_reader(sym) sym = sym.to_sym if self_has_method?(sym) undef_method(sym) @have_cushion_readers.delete(sym) CushionDefaults.log("cushion_reader #{sym} removed from #{self}", :info) end end |
#remove_writer(sym) ⇒ Object
This method will delete any method of the format ‘sym=’, not just cushion_writers.
Undefines any writer for sym in this class (if present). Does not affect ancestor classes.
339 340 341 342 343 344 345 346 |
# File 'lib/cushion_defaults/class_methods.rb', line 339 def remove_writer(sym) write_sym = "#{sym}=".to_sym if self_has_method?(write_sym) undef_method(write_sym) @have_cushion_writers.delete(write_sym) CushionDefaults.log("cushion_writer #{sym}= removed from #{self}", :info) end end |
#set_default(key, val) ⇒ Object
Equivalent to @@defaults = val@
32 33 34 |
# File 'lib/cushion_defaults/class_methods.rb', line 32 def set_default(key, val) @defaults[key.to_sym] = val end |
#thaw_default(*syms) ⇒ Object
Thaws a frozen default, allowing it to be set to a new value.
Note that if the value of the @default@ is itself frozen (using #deep_freeze_default or @Object#freeze@), thaw_default allows you to set @default@ to a new value but does not and cannot allow you to modify the value to which @default@ points until and unless @default@ is set to a new value.
Does not throw an error when you attempt to thaw a non-frozen default, but it does log at warning level.
475 476 477 478 479 480 481 482 483 484 |
# File 'lib/cushion_defaults/class_methods.rb', line 475 def thaw_default(*syms) syms.each do |sym| sym = sym.to_sym unless defaults.thaw_default! sym # It returns nil if the key was not present in the Set CushionDefaults.log("Cannot thaw #{sym}: it was already thawed for #{self}", :warn) end CushionDefaults.log("After thawing, currently frozen defaults are #{defaults.frozen_defaults.to_a.join(', ')}") end end |
#thaw_defaults ⇒ Object
Calls #thaw_default for all defaults.
489 490 491 |
# File 'lib/cushion_defaults/class_methods.rb', line 489 def thaw_defaults thaw_default *defaults.keys end |