Class: Opto::Type

Inherits:
Object
  • Object
show all
Defined in:
lib/opto/type.rb

Overview

Defines a type handler. Used as a base from which to inherit in the type handlers.

Constant Summary collapse

GLOBAL_OPTIONS =
{
  required: true
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Type


92
93
94
# File 'lib/opto/type.rb', line 92

def initialize(options = {})
  @options = Type::GLOBAL_OPTIONS.merge(self.class.const_defined?(:OPTIONS) ? self.class.const_get(:OPTIONS) : {}).merge(options.symbolize_keys)
end

Instance Attribute Details

#optionsObject

Returns the value of attribute options


16
17
18
# File 'lib/opto/type.rb', line 16

def options
  @options
end

Class Method Details

.for(type_name) ⇒ Object

Find a type handler for :type_name, for example: Opto::Type.for(:string)

Raises:

  • (NameError)

33
34
35
36
# File 'lib/opto/type.rb', line 33

def for(type_name)
  raise NameError, "No handler for type #{type_name}" unless types[type_name]
  types[type_name]
end

.inherited(where) ⇒ Object


19
20
21
# File 'lib/opto/type.rb', line 19

def inherited(where)
  types[where.type] = where
end

.sanitizer(name, &block) ⇒ Object

Define a sanitizer. Can be used to for example convert strings to integers or to remove whitespace, etc.

Examples:

class Foo < Opto::Type
  sanitizer :add_suffix |value|
    value.to_s + "-1"
  end
end

Raises:

  • (TypeError)

69
70
71
72
# File 'lib/opto/type.rb', line 69

def sanitizer(name, &block)
  raise TypeError, "Block required" unless block_given?
  sanitizers << define_method("sanitize_#{name}", &block)
end

.sanitizersObject


56
57
58
# File 'lib/opto/type.rb', line 56

def sanitizers
  @sanitizers ||= []
end

.true_when(&block) ⇒ Object

Raises:

  • (TypeError)

74
75
76
77
# File 'lib/opto/type.rb', line 74

def true_when(&block)
  raise TypeError, "Block required" unless block_given?
  define_method(:truthy?, &block)
end

.typeObject


27
28
29
# File 'lib/opto/type.rb', line 27

def type
  name.to_s.split('::').last.snakecase.to_sym
end

.typesObject


23
24
25
# File 'lib/opto/type.rb', line 23

def types
  @types ||= {}
end

.validator(name, &block) ⇒ Object

Define a validator:

Examples:

class Foo < Opto::Type
  validator :is_foo do |value|
    unless value == 'foo'
      "Foo is not foo."
     end
  end
end

Raises:

  • (TypeError)

51
52
53
54
# File 'lib/opto/type.rb', line 51

def validator(name, &block)
  raise TypeError, "Block required" unless block_given?
  validators << define_method("validate_#{name}", &block)
end

.validatorsObject


38
39
40
# File 'lib/opto/type.rb', line 38

def validators
  @validators ||= []
end

Instance Method Details

#errorsObject


116
117
118
# File 'lib/opto/type.rb', line 116

def errors
  @errors ||= {}
end

#required?Boolean


100
101
102
# File 'lib/opto/type.rb', line 100

def required?
  !!options[:required]
end

#sanitize(value) ⇒ Object


104
105
106
107
108
109
110
111
112
113
114
# File 'lib/opto/type.rb', line 104

def sanitize(value)
  new_value = value
  self.class.sanitizers.each do |sanitizer|
    begin
      new_value = self.send(sanitizer, new_value)
    rescue StandardError => ex
      raise ex, "Sanitizer #{sanitizer} : #{ex.message}"
    end
  end
  new_value
end

#typeObject


96
97
98
# File 'lib/opto/type.rb', line 96

def type
  self.class.type
end

#valid?(value) ⇒ Boolean


120
121
122
123
# File 'lib/opto/type.rb', line 120

def valid?(value)
  validate(value)
  errors.empty?
end

#validate(value) ⇒ Object


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/opto/type.rb', line 125

def validate(value)
  errors.clear
  if value.nil?
    errors[:presence] = "Required value missing" if required?
  else
    (Type.validators + self.class.validators).each do |validator|
      begin
        result = self.send(validator, value)
      rescue StandardError => ex
        raise ex, "Validator #{validator} : #{ex.message}"
      end
      unless result.kind_of?(NilClass) || result.kind_of?(TrueClass)
        errors[validator] = result
      end
    end
  end
end