1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 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 199 200 201
|
# frozen_string_literal: true
require 'contracts'
require 'aruba/basic_configuration/option'
require 'aruba/in_config_wrapper'
# Aruba
module Aruba
# Basic configuration for Aruba
#
# @private
class BasicConfiguration
include Contracts
class << self
def known_options
@known_options ||= {}
end
# Define an option reader
#
# @param [Symbol] name
# The name of the reader
#
# @option [Class, Module] type
# The type contract for the option
#
# @option [Object] default
# The default value
def option_reader(name, type:, default: nil)
raise ArgumentError, 'Either use block or default value' if block_given? && default
add_option(name, block_given? ? yield(InConfigWrapper.new(known_options)) : default)
Contract None => type
define_method(name) { find_option(name).value }
end
# Define an option reader and writer
#
# @param [Symbol] name
# The name of the reader
#
# @option [Class, Module] type
# The type contract for the option
#
# @option [Object] default
# The default value
#
def option_accessor(name, type:, default: nil)
raise ArgumentError, 'Either use block or default value' if block_given? && default
# Add writer
add_option(name, block_given? ? yield(InConfigWrapper.new(known_options)) : default)
Contract type => type
define_method(:"#{name}=") { |v| find_option(name).value = v }
# Add reader
option_reader name, type: type
end
private
def add_option(name, value = nil)
return if known_options.key?(name)
known_options[name] = Option.new(name: name, value: value)
self
end
end
protected
attr_accessor :local_options
attr_writer :hooks
public
# Create configuration
def initialize
initialize_configuration
end
# @yield [Configuration]
#
# Yields self
def configure
yield self if block_given?
end
# Reset configuration
def reset
initialize_configuration
end
# Make deep dup copy of configuration
def make_copy
obj = dup
obj.local_options = Marshal.load(Marshal.dump(local_options))
obj.hooks = @hooks
obj
end
# Define before-hook
#
# @param [Symbol, String] name
# The name of the hook
#
# @yield
# The code block which should be run. This is a configure time only option
def before(name, &block)
name = format('%s_%s', 'before_', name.to_s).to_sym
raise ArgumentError, 'A block is required' unless block
@hooks.append(name, block)
self
end
# Run before-hook
#
# @param [Symbol, String] name
# The name of the hook
#
# @param [Proc] context
# The context a hook should run in
#
# @param [Array] args
# Arguments for the run of hook
def run_before_hook(name, context, *args)
name = format('%s_%s', 'before_', name.to_s).to_sym
@hooks.execute(name, context, *args)
end
# Define after-hook
#
# @param [Symbol, String] name
# The name of the hook
#
# @yield
# The code block which should be run. This is a configure time only option
def after(name, &block)
name = format('%s_%s', 'after_', name.to_s).to_sym
raise ArgumentError, 'A block is required' unless block
@hooks.append(name, block)
self
end
# Run after-hook
#
# @param [Symbol, String] name
# The name of the hook
#
# @param [Proc] context
# The context a hook should run in
#
# @param [Array] args
# Arguments for the run of hook
def run_after_hook(name, context, *args)
name = format('%s_%s', 'after_', name.to_s).to_sym
@hooks.execute(name, context, *args)
end
# Check if <name> is option
#
# @param [String, Symbol] name
# The name of the option
def option?(name)
local_options.any? { |_, v| v.name == name.to_sym }
end
def ==(other)
local_options.values.map(&:value) == other.local_options.values.map(&:value)
end
# Set if name is option
def set_if_option(name, *args)
public_send(:"#{name}=", *args) if option? name
end
private
def initialize_configuration
@local_options = Marshal.load(Marshal.dump(self.class.known_options))
@hooks = Hooks.new
end
def find_option(name)
raise NotImplementedError, %(Unknown option "#{name}") unless option? name
local_options[name]
end
end
end
|