Module: DbMod::Statements::Configuration::Defaults

Defined in:
lib/db_mod/statements/configuration/defaults.rb

Overview

Provides functionality backing the MethodConfiguration#defaults setting. Allows certain statement or prepared method parameters to be omitted, supplying default values where necessary:

def_statement(:a, 'SELECT id FROM a WHERE x > $y') { defaults y: 10 }
def_prepared(:b, %(
  INSERT INTO b
    (p, q, r)
  VALUES
    ($1, $2, $3)
  RETURNING p, q, r
)) { defaults(5, 6).single(:row) }

def_prepared(:c, 'SELECT a FROM b WHERE d = $e AND f > $g') do
  # procs may be used
  defaults g: ->(args) { args[:e] * 10 }
end

# ...

a    # y => 10
a 11 # y => 11

# defaults filled in from the right
b 1, 2 # => { 'p' => '1', 'q' => '2', 'r' => '6' }

# proc defaults executed when method is called
c e: 2 # === c e: 2, g: 20

Class Method Summary collapse

Class Method Details

.extend(definition, params, defaults) ⇒ Proc

Extend a method definition by wrapping it with a proc that will try to fill in any omitted arguments with given defaults.

Parameters:

  • definition (Proc)

    base method definition, with parameter validation already attached

  • params (Hash<Symbol,value>, Array<value>)
  • defaults (Hash<Symbol,value,Array<value>] default values, in the same form as they would be provided to the original method definition except that some values may be omitted. Defaults may either be constant values, or a lambda proc may be given, which will be passed the entirety of the argument list and should return a single value to be used when none is given)

    efaults [Hash<Symbol,value,Array<value>] default values, in the same form as they would be provided to the original method definition except that some values may be omitted. Defaults may either be constant values, or a lambda proc may be given, which will be passed the entirety of the argument list and should return a single value to be used when none is given

Returns:

  • (Proc)

    new method definition, or the same one if no default values have been appended



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/db_mod/statements/configuration/defaults.rb', line 49

def self.extend(definition, params, defaults)
  return definition if defaults.nil?

  if [[], 0].include? params
    fail ArgumentError, 'defaults not allowed for no-args methods'
  end

  if params.is_a? Array
    extend_named_args_method(definition, defaults)
  else
    extend_fixed_args_method(definition, params, defaults)
  end
end

.extend_fixed_args_method(definition, arity, defaults) ⇒ Proc (private)

Extend a method with numbered parameters, providing default argument values for one or more parameters. Defaults will be applied, in the same left-to-right order, but at the right-hand side of the parameter list, as with normal method default arguments.

Parameters:

  • definition (Proc)

    base method definition, with parameter validation already attached

  • arity (Fixnum)

    number of arguments expected by the base method definition

  • defaults (Array)

    default parameter values

Returns:

  • (Proc)

    wrapped method definition



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/db_mod/statements/configuration/defaults.rb', line 145

def self.extend_fixed_args_method(definition, arity, defaults)
  fail ArgumentError, 'too many defaults' if defaults.size > arity

  unless defaults.is_a? Array
    fail ArgumentError, 'array expected for defaults'
  end

  arity = (arity - defaults.size)..arity
  fail ArgumentError, 'too many defaults' if arity.min < 0

  lambda do |*args|
    Defaults.use_fixed_defaults(self, args, defaults, arity)
    instance_exec(*args, &definition)
  end
end

.extend_named_args_method(definition, defaults) ⇒ Proc (private)

Extend a method with named parameters, providing default argument values for one or more parameters.

Parameters:

  • definition (Proc)

    base method definition, with parameter validation already attached

  • defaults (Hash<Symbol,value>)

    see extend

Returns:

  • (Proc)

    wrapped method definition



73
74
75
76
77
78
79
80
81
82
# File 'lib/db_mod/statements/configuration/defaults.rb', line 73

def self.extend_named_args_method(definition, defaults)
  unless defaults.is_a? Hash
    fail ArgumentError, 'hash expected for defaults'
  end

  lambda do |*args|
    Defaults.use_named_defaults(self, args, defaults)
    instance_exec(*args, &definition)
  end
end

.use_fixed_defaults(scope, args, defaults, arity) ⇒ Object (private)

Fill in any missing parameter arguments using default values where available.

Parameters:

  • scope (Object)

    scope to be used for executing default values that are lambda procedures. Should be the instance object where the method has been defined.

  • args (Array)

    method arguments before processing and validation

  • defaults (Array)

    default parameter values

  • arity (Range<Fixnum>)

    number of arguments expected by the base method definition

Raises:

  • (ArgumentError)

    if there are not enough or too many args

See Also:



175
176
177
178
179
180
181
182
183
# File 'lib/db_mod/statements/configuration/defaults.rb', line 175

def self.use_fixed_defaults(scope, args, defaults, arity)
  unless arity.include? args.count
    fail ArgumentError, "#{args.count} given, (#{arity}) expected"
  end

  defaults[args.size - arity.min...defaults.size].each do |arg|
    args << value!(arg, scope, args)
  end
end

.use_named_defaults(scope, args, defaults) ⇒ Object (private)

Fill in any missing parameter arguments using default values where available.

Parameters:

  • scope (Object)

    scope to be used for executing default values that are lambda procedures. Should be the instance object where the method has been defined.

  • args ([Hash<Symbol,value>])

    method arguments before processing and validation

  • defaults (Hash<Symbol,value>)

    default parameter values

See Also:



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/db_mod/statements/configuration/defaults.rb', line 96

def self.use_named_defaults(scope, args, defaults)
  # Special case when no args given.
  args << {} if args.empty?

  # If the args are weird, expect normal parameter validation
  # to pick it up.
  return args unless args.last.is_a? Hash

  defaults.each do |arg, value|
    next if args.last.key? arg

    args.last[arg] = value! value, scope, args.last
  end
end

.value!(value, scope, args) ⇒ Object (private)

Execute the default ‘value’ if it is a Proc, or just return it.

Parameters:

  • value (Proc, Object)

    default value as specified by MethodConfiguration#defaults

  • scope (Object)

    scope to be used for executing default values that are lambda procedures. Should be the instance object where the method has been defined.

  • args (Hash, Array)

    fixed or named argument list, to be passed to the ‘value’ if it is a proc

Returns:

  • (Object)

    value to be passed to the parametered database query



124
125
126
127
128
129
130
# File 'lib/db_mod/statements/configuration/defaults.rb', line 124

def self.value!(value, scope, args)
  if value.is_a? Proc
    scope.instance_exec(args, &value)
  else
    value
  end
end