Class: Petra::Configuration::ClassConfigurator

Inherits:
Configurator
  • Object
show all
Defined in:
lib/petra/configuration/class_configurator.rb

Constant Summary collapse

DEFAULTS =
{
  proxy_instances: false,
  mixin_module_proxies: true,
  use_specialized_proxy: true,
  id_method: :object_id,
  lookup_method: ->(id) { ObjectSpace._id2ref(id.to_i) },
  init_method: :new,
  attribute_reader?: false,
  attribute_writer?: ->(name) { /=$/.match(name) },
  dynamic_attribute_reader?: false,
  persistence_method?: false,
  destruction_method?: false
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Configurator

#__persist!, base_config

Constructor Details

#initialize(class_name) ⇒ ClassConfigurator

Returns a new instance of ClassConfigurator.

Parameters:

  • class_name (String)

    The name of the class to be configured. .new() should not be called manually, use #for_class instead which accepts different input types.



29
30
31
32
# File 'lib/petra/configuration/class_configurator.rb', line 29

def initialize(class_name)
  @class_name = class_name
  super()
end

Class Method Details

.for_class(klass) ⇒ Object

Builds a new instance for the given class name. If a configuration for this class already exists, it is loaded and can be retrieved through the corresponding getter methods

Parameters:

  • klass (String, Symbol, Class)

    The class (name) which will be used to initialize the configurator and load a possibly already existing configuration



147
148
149
# File 'lib/petra/configuration/class_configurator.rb', line 147

def self.for_class(klass)
  new(klass.to_s)
end

Instance Method Details

#__inherited_value(key, *args) ⇒ Object

Much like #__value, but it searches for settings with the given name in the current class’ ancestors if itself does not have a custom value set.



214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/petra/configuration/class_configurator.rb', line 214

def __inherited_value(key, *args)
  configurator = self

  # Search for a custom configuration in the current class and its superclasses
  # until we either reach Object (the lowest level ignoring BasicObject) or
  # found a custom setting.
  until (klass = configurator.send(:configured_class)) == Object || configurator.__value?(key)
    configurator = Petra.configuration.class_configurator(klass.superclass)
  end

  # By now, we have either reached the Object level or found a value.
  # In either case, we are save to retrieve it.
  configurator.__value(key, *args)
end

#__value(key, *args, proc_expected: false, base: nil) ⇒ Object

Returns the value for a certain configuration key. If the configuration value is a proc, it will be called with the given *args.

If no custom configuration was set for the given name, the default value is returned instead.

Parameters:

  • proc_expected (Boolean) (defaults to: false)

    If set to true, the value is expected to be either a Proc object or a String/Symbol which is assumed to be a method name. If the value is something else, an Exception is thrown

  • base (Object) (defaults to: nil)

    The base object which is used in case mandatory_proc is set to true. If the fetched value is a String or Symbol, it will be used as method name in a call based on the base object with +args as actual parameters, e.g. base.send(:some_fetched_value, *args)



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/petra/configuration/class_configurator.rb', line 170

def __value(key, *args, proc_expected: false, base: nil)
  v = __configuration.fetch(key.to_sym, DEFAULTS[key.to_sym])

  # As the setting blocks are saved as Proc objects (which are run
  # in their textual scope) and not lambdas (which are run in their caller's scope),
  # Ruby does not allow using the `return` keyword while being inside the
  # block as method the proc was defined in might have already been returned.
  #
  # When configuring petra using blocks, it is advised to use `next`
  # instead of `return` (which will jump back to the correct position),
  # a workaround is to rescue from possible LocalJumpErrors and simply
  # use their exit value.
  begin
    case v
      when Proc
        # see #__send_to_base
        return v.call(*[*args, base][0, v.arity]) if proc_expected
        v.call(*(args[0, v.arity]))
      when String, Symbol
        return __send_to_base(base, method: v, args: args, key: key) if proc_expected
        v
      else
        __fail_for_key key, 'Value has to be either a Proc or a method name (Symbol/String)' if proc_expected
        v
    end
  rescue LocalJumpError => e
    e.exit_value
  end
end

#__value?(key) ⇒ TrueClass, FalseClass

Tests whether this class configuration has a custom setting for the given key.

Returns:

  • (TrueClass, FalseClass)

    true if there is a custom setting



205
206
207
# File 'lib/petra/configuration/class_configurator.rb', line 205

def __value?(key)
  __configuration.key?(key.to_sym)
end