Class: Lich::Common::SettingsProxy
- Inherits:
-
Object
- Object
- Lich::Common::SettingsProxy
- Defined in:
- lib/common/settings/settings_proxy.rb
Overview
This module provides a proxy class for settings objects, allowing them to be accessed in a Ruby-compatible way. It handles both scalar and container types, and provides methods for comparison, conversion, and enumeration.
The proxy is designed to work with settings objects that are either Hashes or Arrays. It allows for nested access to settings, while also providing a way to save changes made to the settings.
The proxy also provides a way to handle non-destructive methods, which return a new object instead of modifying the original. This is done by creating a duplicate of the target object before calling the method, and then returning a new proxy for the result if it is a container type.
The proxy also handles method delegation, allowing methods to be called directly on the target object. It uses method_missing to catch calls to methods that are not defined on the proxy itself, and delegates them to the target object.
The proxy also provides a way to handle results of non-destructive methods, which return a new object instead of modifying the original. This is done by creating a duplicate of the target object before calling the method, and then returning a new proxy for the result if it is a container type.
Constant Summary collapse
- NON_DESTRUCTIVE_METHODS =
Non-destructive enumerable methods that should not save changes.
[ :select, :map, :filter, :reject, :collect, :find, :detect, :find_all, :grep, :grep_v, :group_by, :partition, :min, :max, :minmax, :min_by, :max_by, :minmax_by, :sort, :sort_by, :flat_map, :collect_concat, :reduce, :inject, :sum, :count, :cycle, :drop, :drop_while, :take, :take_while, :first, :all?, :any?, :none?, :one?, :find_index, :values_at, :zip, :reverse, :entries, :to_a, :to_h, :include?, :member?, :each_with_index, :each_with_object, :each_entry, :each_slice, :each_cons, :chunk, :slice_before, :slice_after, :slice_when, :chunk_while, :lazy ].freeze
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Allow access to the target for debugging.
-
#target ⇒ Object
readonly
Allow access to the target for debugging.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Accesses a value in the target by key.
-
#[]=(key, value) ⇒ Object
Sets a value in the target by key.
-
#binary_op(operator, other) ⇒ Object
Helper method for binary operators to reduce repetition.
-
#each {|Object| ... } ⇒ self
Iterates over each item in the target.
-
#handle_method_result(result) ⇒ Object
Helper method to handle results of destructive methods.
-
#handle_non_destructive_result(result) ⇒ Object
Helper method to handle results of non-destructive methods.
-
#hash ⇒ Integer
Returns the hash code of the target.
-
#initialize(settings, path, target) ⇒ SettingsProxy
constructor
Initializes a new SettingsProxy instance.
-
#inspect ⇒ String
Returns a string representation of the target for debugging.
-
#instance_of?(klass) ⇒ Boolean
Checks if the target is an instance of the given class.
-
#is_a?(klass) ⇒ Boolean
Checks if the target is an instance of the given class.
-
#kind_of?(klass) ⇒ Boolean
Checks if the target is a kind of the given class.
-
#method ⇒ Object
Define conversion methods using metaprogramming to reduce repetition.
-
#method_missing(method, *args, &block) ⇒ Object
Handles method calls that are not defined on the proxy.
-
#nil? ⇒ Boolean
Checks if the target is nil.
-
#op ⇒ Boolean
Define comparison operators using metaprogramming to reduce repetition.
-
#pretty_print(pp) ⇒ void
Pretty prints the target.
-
#respond_to?(method, include_private = false) ⇒ Boolean
Checks if the target responds to the given method.
-
#respond_to_missing?(method, include_private = false) ⇒ Boolean
Checks if the target responds to the given method.
-
#to_a ⇒ Array?
Converts the target to an array (alias for to_ary).
-
#to_ary ⇒ Array?
Converts the target to an array.
-
#to_h ⇒ Hash?
Converts the target to a hash (alias for to_hash).
-
#to_hash ⇒ Hash?
Converts the target to a hash.
-
#to_s ⇒ String
Returns a string representation of the target.
Constructor Details
#initialize(settings, path, target) ⇒ SettingsProxy
Initializes a new SettingsProxy instance.
31 32 33 34 35 |
# File 'lib/common/settings/settings_proxy.rb', line 31 def initialize(settings, path, target) @settings = settings @path = path.dup @target = target end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
Handles method calls that are not defined on the proxy.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/common/settings/settings_proxy.rb', line 265 def method_missing(method, *args, &block) if @target.respond_to?(method) # For non-destructive methods, operate on a duplicate to avoid modifying original if NON_DESTRUCTIVE_METHODS.include?(method) # Create a duplicate of the target for non-destructive operations target_dup = @target.dup result = target_dup.send(method, *args, &block) # Return the result without saving changes return handle_non_destructive_result(result) else # For destructive methods, operate on the original and save changes result = @target.send(method, *args, &block) @settings.save_proxy_changes(self) return handle_method_result(result) end else super end end |
Instance Attribute Details
#path ⇒ Object (readonly)
Allow access to the target for debugging
40 41 42 |
# File 'lib/common/settings/settings_proxy.rb', line 40 def path @path end |
#target ⇒ Object (readonly)
Allow access to the target for debugging
40 41 42 |
# File 'lib/common/settings/settings_proxy.rb', line 40 def target @target end |
Instance Method Details
#[](key) ⇒ Object
Accesses a value in the target by key.
229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/common/settings/settings_proxy.rb', line 229 def [](key) value = @target[key] if Settings.container?(value) # For container types, return a new proxy with updated path new_path = @path.dup new_path << key SettingsProxy.new(@settings, new_path, value) else # For scalar values, return the value directly value end end |
#[]=(key, value) ⇒ Object
Sets a value in the target by key.
248 249 250 251 252 |
# File 'lib/common/settings/settings_proxy.rb', line 248 def []=(key, value) @target[key] = value @settings.save_proxy_changes(self) # value end |
#binary_op(operator, other) ⇒ Object
Helper method for binary operators to reduce repetition.
58 59 60 61 |
# File 'lib/common/settings/settings_proxy.rb', line 58 def binary_op(operator, other) other_value = other.is_a?(SettingsProxy) ? other.target : other @target.send(operator, other_value) end |
#each {|Object| ... } ⇒ self
Iterates over each item in the target.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/common/settings/settings_proxy.rb', line 192 def each(&_block) return enum_for(:each) unless block_given? if @target.respond_to?(:each) @target.each do |item| if Settings.container?(item) yield SettingsProxy.new(@settings, [], item) else yield item end end end self end |
#handle_method_result(result) ⇒ Object
Helper method to handle results of destructive methods.
307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/common/settings/settings_proxy.rb', line 307 def handle_method_result(result) if result.equal?(@target) # If result is the original target, return self self elsif Settings.container?(result) # For container results, wrap in a new proxy with current path SettingsProxy.new(@settings, @path, result) else # For scalar results, return directly result end end |
#handle_non_destructive_result(result) ⇒ Object
Helper method to handle results of non-destructive methods.
290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/common/settings/settings_proxy.rb', line 290 def handle_non_destructive_result(result) # No need to capture path since we're using empty path @settings.reset_path_and_return( if Settings.container?(result) # For container results, wrap in a new proxy with empty path SettingsProxy.new(@settings, [], result) else # For scalar results, return directly result end ) end |
#hash ⇒ Integer
Returns the hash code of the target.
76 77 78 |
# File 'lib/common/settings/settings_proxy.rb', line 76 def hash @target.hash end |
#inspect ⇒ String
Returns a string representation of the target for debugging.
90 91 92 |
# File 'lib/common/settings/settings_proxy.rb', line 90 def inspect @target.inspect end |
#instance_of?(klass) ⇒ Boolean
Checks if the target is an instance of the given class.
126 127 128 |
# File 'lib/common/settings/settings_proxy.rb', line 126 def instance_of?(klass) @target.instance_of?(klass) end |
#is_a?(klass) ⇒ Boolean
Checks if the target is an instance of the given class.
110 111 112 |
# File 'lib/common/settings/settings_proxy.rb', line 110 def is_a?(klass) @target.is_a?(klass) end |
#kind_of?(klass) ⇒ Boolean
Checks if the target is a kind of the given class.
118 119 120 |
# File 'lib/common/settings/settings_proxy.rb', line 118 def kind_of?(klass) @target.kind_of?(klass) end |
#method ⇒ Object
Define conversion methods using metaprogramming to reduce repetition.
178 179 180 181 182 |
# File 'lib/common/settings/settings_proxy.rb', line 178 [:to_int, :to_i, :to_str, :to_sym, :to_proc].each do |method| define_method(method) do @target.send(method) if @target.respond_to?(method) end end |
#nil? ⇒ Boolean
Checks if the target is nil.
49 50 51 |
# File 'lib/common/settings/settings_proxy.rb', line 49 def nil? @target.nil? end |
#op ⇒ Boolean
Define comparison operators using metaprogramming to reduce repetition. NB: not all operators apply to all objects (e.g. <, >, <=, >= on Arrays).
67 68 69 70 71 |
# File 'lib/common/settings/settings_proxy.rb', line 67 [:==, :!=, :eql?, :equal?, :<=>, :<, :<=, :>, :>=, :|, :&].each do |op| define_method(op) do |other| binary_op(op, other) end end |
#pretty_print(pp) ⇒ void
This method returns an undefined value.
Pretty prints the target.
98 99 100 |
# File 'lib/common/settings/settings_proxy.rb', line 98 def pretty_print(pp) pp.pp(@target) end |
#respond_to?(method, include_private = false) ⇒ Boolean
Checks if the target responds to the given method.
135 136 137 |
# File 'lib/common/settings/settings_proxy.rb', line 135 def respond_to?(method, include_private = false) super || @target.respond_to?(method, include_private) end |
#respond_to_missing?(method, include_private = false) ⇒ Boolean
Checks if the target responds to the given method.
325 326 327 |
# File 'lib/common/settings/settings_proxy.rb', line 325 def respond_to_missing?(method, include_private = false) @target.respond_to?(method, include_private) || super end |
#to_a ⇒ Array?
Converts the target to an array (alias for to_ary).
171 172 173 |
# File 'lib/common/settings/settings_proxy.rb', line 171 def to_a to_ary end |
#to_ary ⇒ Array?
Converts the target to an array.
162 163 164 165 166 |
# File 'lib/common/settings/settings_proxy.rb', line 162 def to_ary return nil unless @target.is_a?(Array) @target.dup end |
#to_h ⇒ Hash?
Converts the target to a hash (alias for to_hash).
155 156 157 |
# File 'lib/common/settings/settings_proxy.rb', line 155 def to_h to_hash end |
#to_hash ⇒ Hash?
Converts the target to a hash.
146 147 148 149 150 |
# File 'lib/common/settings/settings_proxy.rb', line 146 def to_hash return nil unless @target.is_a?(Hash) @target.dup end |
#to_s ⇒ String
Returns a string representation of the target.
83 84 85 |
# File 'lib/common/settings/settings_proxy.rb', line 83 def to_s @target.to_s end |