Module: Recurly::Schema::SchemaValidator

Included in:
Request, Resource
Defined in:
lib/recurly/schema/schema_validator.rb

Overview

This module is responsible for validating that the raw data passed in to attributes matches the schema belonging to this class. It should be mixed in to the Request class.

Instance Method Summary collapse

Instance Method Details

#get_did_you_mean(schema, misspelled_attr) ⇒ Object

Gets the closest term to the misspelled attribute


61
62
63
64
65
66
67
68
69
# File 'lib/recurly/schema/schema_validator.rb', line 61

def get_did_you_mean(schema, misspelled_attr)
  closest = schema.attributes.keys.sort_by do |v|
    levenshtein_distance(v, misspelled_attr)
  end.first

  if closest && levenshtein_distance(closest, misspelled_attr) <= 4
    closest
  end
end

#validate!Object

Validates the attributes and throws an error if something is wrong.

Examples:

Recurly::Requests::PlanCreate.new(code: 'plan123').validate!
#=> {:code=>"plan123"}
Recurly::Requests::PlanCreate.new(code: 3.14).validate!
#=> ArgumentError: Attribute 'code' on the resource Recurly::Requests::PlanCreate is type Float but should be a String.
Recurly::Requests::PlanCreate.new(kode: 'plan123').validate!
#=> ArgumentError: Attribute 'kode' does not exist on request Recurly::Requests::PlanCreate. Did you mean 'code'?

Raises:

  • (ArgumentError)

    if the attribute data does not match the schema.


20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/recurly/schema/schema_validator.rb', line 20

def validate!
  attributes.each do |attr_name, val|
    schema_attr = schema.get_attribute(attr_name)
    if schema_attr.nil?
      err_msg = "Attribute '#{attr_name}' does not exist on request #{self.class.name}."
      if did_you_mean = get_did_you_mean(schema, attr_name)
        err_msg << " Did you mean '#{did_you_mean}'?"
      end
      raise ArgumentError, err_msg
    else
      validate_attribute!(attr_name, schema_attr, val)
    end
  end
end

#validate_attribute!(name, schema_attr, val) ⇒ Object

Validates an individual attribute


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/recurly/schema/schema_validator.rb', line 36

def validate_attribute!(name, schema_attr, val)
  unless val.nil? || schema_attr.is_valid?(val)
    # If it's safely castable, the json deserializer or server
    # will take care of it for us
    unless safely_castable?(val.class, schema_attr.type)
      expected = case schema_attr
        when Schema::ArrayAttribute
          "Array of #{schema_attr.type}s"
        else
          schema_attr.type
        end

      raise ArgumentError, "Attribute '#{name}' on the resource #{self.class.name} is type #{val.class} but should be a #{expected}"
    end
  end

  # This is the convention for a recurly object
  if schema_attr.is_a?(Schema::ResourceAttribute) && val.is_a?(Hash)
    # Using send because the initializer may be private
    instance = schema_attr.recurly_class.send(:new, val)
    instance.validate!
  end
end