Class: Rester::Service::Resource::Params

Inherits:
Object
  • Object
show all
Defined in:
lib/rester/service/resource/params.rb

Constant Summary collapse

DEFAULT_OPTS =
{ strict: true }.freeze
BASIC_TYPES =
[String, Symbol, Float, Integer, Array, Hash].freeze
DEFAULT_TYPE_MATCHERS =
{
  Integer  => /\A\d+\z/,
  Float    => /\A\d+(\.\d+)?\z/,
  :boolean => /\A(true|false)\z/i
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}, &block) ⇒ Params

Returns a new instance of Params.



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rester/service/resource/params.rb', line 15

def initialize(opts={}, &block)
  @options = DEFAULT_OPTS.merge(opts).freeze
  @_dynamic_fields = []
  @_required_fields = []
  @_defaults = {}
  @_all_fields = []

  # Default "validator" is to just treat the param as a string.
  @_validators = Hash.new([String, {}])

  instance_eval(&block) if block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object (private)



132
133
134
135
136
137
138
139
140
# File 'lib/rester/service/resource/params.rb', line 132

def method_missing(meth, *args)
  if meth.to_s.match(/\A[A-Z][A-Za-z]+\z/)
    name = args.shift
    opts = args.shift || {}
    _add_validator(name, self.class.const_get(meth), opts)
  else
    super
  end
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



13
14
15
# File 'lib/rester/service/resource/params.rb', line 13

def options
  @options
end

Instance Method Details

#Boolean(name, opts = {}) ⇒ Object

Need to have special handling for Boolean since Ruby doesn’t have a Boolean type, instead it has TrueClass and FalseClass…



104
105
106
# File 'lib/rester/service/resource/params.rb', line 104

def Boolean(name, opts={})
  _add_validator(name, :boolean, opts)
end

#freezeObject



35
36
37
38
39
40
41
42
# File 'lib/rester/service/resource/params.rb', line 35

def freeze
  @_validators.freeze
  @_required_fields.freeze
  @_dynamic_fields.freeze
  @_defaults.freeze
  @_all_fields.freeze
  super
end

#required?(key) ⇒ Boolean

Returns:



77
78
79
# File 'lib/rester/service/resource/params.rb', line 77

def required?(key)
  @_required_fields.include?(key.to_sym)
end

#strict?Boolean

Whether or not validation will be done strictly (i.e., only specified params will be allowed).

Returns:



31
32
33
# File 'lib/rester/service/resource/params.rb', line 31

def strict?
  !!options[:strict]
end

#typeObject

The basic data types all have helper methods named after them in Kernel. This allows you to do things like String(1234) to get ‘1234’. It’s the same as doing 1234.to_s.

Since methods already exist globally for these types, we need to override them so we can capture their calls. If this weren’t the case, then we’d be catch them in ‘method_missing`.



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rester/service/resource/params.rb', line 89

BASIC_TYPES.each do |type|
  define_method(type.to_s) { |name, opts={}, &block|
    if type == Hash || (type == Array && opts[:type] == Hash)
      elem_type = (options = @options.merge(opts)).delete(:type)
      opts = elem_type ? { type: elem_type } : {}
      opts.merge!(use: self.class.new(options, &block))
    end

    _add_validator(name, type, opts)
  }
end

#use(params) ⇒ Object



72
73
74
75
# File 'lib/rester/service/resource/params.rb', line 72

def use(params)
  _merge_params(params)
  nil
end

#validate(params) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rester/service/resource/params.rb', line 44

def validate(params)
  param_keys = params.keys.map(&:to_sym)
  default_keys = @_defaults.keys

  unless (missing = @_required_fields - param_keys - default_keys).empty?
    _error!("missing params: #{missing.join(', ')}")
  end

  _validate_strict(param_keys)

  validated_params = Hash[
    params.map { |key, value| [key.to_sym, validate!(key.to_sym, value)] }
  ]

  @_defaults.merge(validated_params)
end

#validate!(key, value) ⇒ Object



61
62
63
64
65
66
67
68
69
70
# File 'lib/rester/service/resource/params.rb', line 61

def validate!(key, value)
  if @_validators.key?(key)
    klass, opts = @_validators[key]
  else
    dynamic_key = @_dynamic_fields.find { |r| r.match(key) }
    klass, opts = @_validators[dynamic_key]
  end

  _validate(key, value, klass, opts)
end