Module: Collapsium::ViralCapabilities
- Extended by:
- Support::HashMethods, Support::Methods
- Includes:
- Support::HashMethods, Support::Methods
- Included in:
- RecursiveDup, RecursiveMerge, RecursiveSort, UberHash
- Defined in:
- lib/collapsium/viral_capabilities.rb
Overview
Tries to make extended Hash capabilities viral, i.e. provides the same features to nested Hash structures as the Hash that includes this module.
Virality is ensured by changing the return value of various methods; if it is derived from Hash, it is attempted to convert it to the including class.
The module uses HashMethods to decide which methods to make viral in this manner.
There are two ways for using this module: a) in a ‘Class`, either include, prepend or extend it. b) in a `Module`, extend this module. The resulting module can be included,
prepended or extended in a `Class` again.
Constant Summary
Constants included from Support::HashMethods
Support::HashMethods::KEYED_READ_METHODS, Support::HashMethods::KEYED_WRITE_METHODS, Support::HashMethods::READ_METHODS, Support::HashMethods::WRITE_METHODS
Class Method Summary collapse
-
.enhance(base) ⇒ Object
Enhance the base by wrapping all READ_METHODS and WRITE_METHODS in a wrapper that uses enhance_hash_value to, well, enhance Hash results.
-
.enhance_hash_value(outer_hash, value) ⇒ Object
Given an outer Hash and a value, enhance Hash values so that they have the same capabilities as the outer Hash.
- .extended(base) ⇒ Object
- .included(base) ⇒ Object
-
.prepended(base) ⇒ Object
When prepended, included or extended, enhance the base.
Instance Method Summary collapse
- #extended(base) ⇒ Object
- #included(base) ⇒ Object
-
#prepended(base) ⇒ Object
When prepended, included or extended, enhance the base.
Methods included from Support::Methods
loop_detected?, repeated, resolve_helpers, wrap_method
Class Method Details
.enhance(base) ⇒ Object
Enhance the base by wrapping all READ_METHODS and WRITE_METHODS in a wrapper that uses enhance_hash_value to, well, enhance Hash results.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/collapsium/viral_capabilities.rb', line 68 def enhance(base) # rubocop:disable Style/ClassVars @@write_block ||= proc do |wrapped_method, *args, &block| arg_copy = args.map do |arg| enhance_hash_value(wrapped_method.receiver, arg) end result = wrapped_method.call(*arg_copy, &block) next enhance_hash_value(wrapped_method.receiver, result) end @@read_block ||= proc do |wrapped_method, *args, &block| result = wrapped_method.call(*args, &block) next enhance_hash_value(wrapped_method.receiver, result) end # rubocop:enable Style/ClassVars READ_METHODS.each do |method_name| wrap_method(base, method_name, raise_on_missing: false, &@@read_block) end WRITE_METHODS.each do |method_name| wrap_method(base, method_name, raise_on_missing: false, &@@write_block) end end |
.enhance_hash_value(outer_hash, value) ⇒ Object
Given an outer Hash and a value, enhance Hash values so that they have the same capabilities as the outer Hash. Non-Hash values are returned unchanged.
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 |
# File 'lib/collapsium/viral_capabilities.rb', line 96 def enhance_hash_value(outer_hash, value) # If the value is not a Hash, we don't do anything. if not value.is_a? Hash return value end # If the value is a different type of Hash from ourself, we want to # create an instance of our own type with the same values. # XXX: DO NOT replace the loop with :merge! or :merge - those are # potentially wrapped write functions, leading to an infinite # recursion. if value.class != outer_hash.class new_value = outer_hash.class.new value.each do |key, inner_val| if not inner_val.is_a? Hash new_value[key] = inner_val next end if inner_val.class == outer_hash.class new_value[key] = inner_val next end new_inner_value = outer_hash.class.new new_inner_value.merge!(inner_val) new_value[key] = new_inner_value end value = new_value end # Next, we want to extend all the modules in self. That might be a # no-op due to the above block, but not necessarily so. value_mods = (class << value; self end).included_modules own_mods = (class << outer_hash; self end).included_modules (own_mods - value_mods).each do |mod| value.extend(mod) end # If we have a default_proc and the value doesn't, we want to use our # own. This *can* override a perfectly fine default_proc with our own, # which might suck. value.default_proc ||= outer_hash.default_proc # Finally, the class can define its own virality function. if outer_hash.respond_to?(:virality) value = outer_hash.(value) end return value end |
.extended(base) ⇒ Object
61 62 63 |
# File 'lib/collapsium/viral_capabilities.rb', line 61 def extended(base) enhance(base) end |
.included(base) ⇒ Object
57 58 59 |
# File 'lib/collapsium/viral_capabilities.rb', line 57 def included(base) enhance(base) end |
.prepended(base) ⇒ Object
When prepended, included or extended, enhance the base.
53 54 55 |
# File 'lib/collapsium/viral_capabilities.rb', line 53 def prepended(base) enhance(base) end |
Instance Method Details
#extended(base) ⇒ Object
43 44 45 |
# File 'lib/collapsium/viral_capabilities.rb', line 43 def extended(base) ViralCapabilities.enhance(base) end |
#included(base) ⇒ Object
39 40 41 |
# File 'lib/collapsium/viral_capabilities.rb', line 39 def included(base) ViralCapabilities.enhance(base) end |
#prepended(base) ⇒ Object
When prepended, included or extended, enhance the base.
35 36 37 |
# File 'lib/collapsium/viral_capabilities.rb', line 35 def prepended(base) ViralCapabilities.enhance(base) end |