Class: RubstApi::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/rubst_api/model.rb

Defined Under Namespace

Classes: Field

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**attributes) ⇒ Model

Returns a new instance of Model.

Raises:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rubst_api/model.rb', line 52

def initialize(**attributes)
  errors = []
  self.class.fields.each_value do |field|
    value = attributes.key?(field.name) ? attributes[field.name] : field.default
    if value.equal?(UNDEFINED)
      errors << { type: "missing", loc: [field.name], msg: "Field required", input: attributes }
      next
    end
    begin
      instance_variable_set(:"@#{field.name}", Validator.coerce(value, field.type, field.options))
    rescue ValidationError => e
      errors.concat(e.errors.map { |error| error.merge(loc: [field.name] + Array(error[:loc])) })
    end
  end
  raise ValidationError, errors unless errors.empty?
  freeze
end

Class Method Details

.field(name, type = String, default: UNDEFINED, required: nil, **options) ⇒ Object



26
27
28
29
30
# File 'lib/rubst_api/model.rb', line 26

def field(name, type = String, default: UNDEFINED, required: nil, **options)
  required = default.equal?(UNDEFINED) if required.nil?
  fields[name.to_sym] = Field.new(name.to_sym, type, default, required, options.freeze)
  attr_reader name
end

.fieldsObject



24
# File 'lib/rubst_api/model.rb', line 24

def fields = @fields ||= {}

.inherited(child) ⇒ Object



20
21
22
# File 'lib/rubst_api/model.rb', line 20

def inherited(child)
  child.instance_variable_set(:@fields, fields.dup)
end

.json_schema(ref_template: "#/components/schemas/%s") ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/rubst_api/model.rb', line 42

def json_schema(ref_template: "#/components/schemas/%s")
  required = fields.values.select(&:required).map { |field| field.name.to_s }
  {
    type: "object",
    title: name&.split("::")&.last,
    properties: fields.to_h { |name, field| [name, Schema.for(field.type, field.options)] }
  }.tap { |schema| schema[:required] = required unless required.empty? }
end

.validate(value, location: [:body]) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/rubst_api/model.rb', line 32

def validate(value, location: [:body])
  return value if value.is_a?(self)
  unless value.is_a?(Hash)
    raise ValidationError, [{ type: "model_type", loc: location, msg: "Input should be an object", input: value }]
  end
  new(**value.transform_keys(&:to_sym))
rescue ValidationError => e
  raise ValidationError, e.errors.map { |error| error.merge(loc: location + Array(error[:loc])) }
end

Instance Method Details

#==(other) ⇒ Object



81
# File 'lib/rubst_api/model.rb', line 81

def ==(other) = other.instance_of?(self.class) && other.model_dump == model_dump

#model_dump(exclude_none: false, by_alias: false) ⇒ Object Also known as: to_h



70
71
72
73
74
75
76
77
# File 'lib/rubst_api/model.rb', line 70

def model_dump(exclude_none: false, by_alias: false)
  self.class.fields.each_with_object({}) do |(name, field), output|
    value = public_send(name)
    next if exclude_none && value.nil?
    key = by_alias && field.options[:alias] ? field.options[:alias] : name
    output[key] = Serializer.dump(value)
  end
end

#to_jsonObject



80
# File 'lib/rubst_api/model.rb', line 80

def to_json(*) = JSON.generate(model_dump)