Class: ServiceOperation::Params::Attribute

Inherits:
Object
  • Object
show all
Defined in:
lib/service_operation/params/attribute.rb

Overview

Represents a single attribute of a value class

Constant Summary collapse

OPTIONS =
[:name, :validator, :coercer, :default, :log, :optional].freeze
EXPANDABLE_VALIDATORS =

Types of validation classes that can be expanded

%w[Array Symbol String].freeze
PARAM_COERCIONS =

Typical coercions from web/string parameters

{
  date: ->(d) { d.is_a?(String) ? Date.parse(d) : d },
  integer: ->(o) { o && o != '' ? o.to_i : nil },
  string: ->(o) { o && o != '' ? o.to_s : nil }
}.freeze
COERCIONS =
{
  'Integer' => PARAM_COERCIONS[:integer],
  'String' => PARAM_COERCIONS[:string],
  'EnumerableOf(Integer)' => ->(o) { Array(o).map(&:to_i) },
  'EnumerableOf(String)' => ->(o) { Array(o).map(&:to_s) },

  json_api_page: lambda do |o|
    h = Hash(o)
    h[:size] = h[:size].to_i if h && h[:size].present?
    h
  end
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Attribute

Returns a new instance of Attribute.



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/service_operation/params/attribute.rb', line 100

def initialize(options = {})
  @name = options[:name].to_sym
  @validator  = options[:validator]
  @coercer    = options[:coercer]
  @default    = options[:default]
  @log        = options.fetch(:log) { true }
  @optional   = options.fetch(:optional) { false }
  @options    = options.reject { |k, _v| OPTIONS.include?(k) }

  freeze
end

Instance Attribute Details

#coercerObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def coercer
  @coercer
end

#defaultObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def default
  @default
end

#logObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def log
  @log
end

#nameObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def name
  @name
end

#optionalObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def optional
  @optional
end

#optionsObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def options
  @options
end

#validatorObject (readonly)

Instance Methods



98
99
100
# File 'lib/service_operation/params/attribute.rb', line 98

def validator
  @validator
end

Class Method Details

.define(*args) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/service_operation/params/attribute.rb', line 45

def define(*args)
  options = extract_options(args)
  name, validator = args
  validator ||= Anything

  raise "#{name.inspect} is a keyword" if KEYWORDS.include?(name)

  if EXPANDABLE_VALIDATORS.include?(validator.class.name)
    validator = expand_validator(validator)
    options[:coerce] = COERCIONS[validator.name] || true if options[:coerce].nil?
  end

  # options[:coerce] = COERCIONS[validator.name] || options[:coerce]
  options[:coercer] = options.delete(:coerce)

  new options.merge(name: name, validator: validator)
end

Instance Method Details

#==(other) ⇒ Object



112
113
114
# File 'lib/service_operation/params/attribute.rb', line 112

def ==(other)
  name == other.name
end

#error(value) ⇒ Object



121
122
123
124
125
126
127
128
129
# File 'lib/service_operation/params/attribute.rb', line 121

def error(value)
  return if validate?(value)

  if required? && value.nil?
    "can't be blank"
  else
    "must be typecast '#{validator.name}'"
  end
end

#from(raw_value, klass = nil) ⇒ Object



116
117
118
119
# File 'lib/service_operation/params/attribute.rb', line 116

def from(raw_value, klass = nil)
  raw_value = (default.respond_to?(:call) ? default.call : default) if raw_value.nil?
  coerce(raw_value, klass)
end

#optional?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'lib/service_operation/params/attribute.rb', line 131

def optional?
  optional == true
end

#required?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/service_operation/params/attribute.rb', line 135

def required?
  !optional
end

#validate?(value) ⇒ Boolean

Returns:

  • (Boolean)


139
140
141
142
143
144
# File 'lib/service_operation/params/attribute.rb', line 139

def validate?(value)
  # special exception to prevent Object === nil from validating
  return false if value.nil? && !optional

  optional || validator === value # rubocop:disable Style/CaseEquality
end