module SchemaModel::ClassMethods

Public Instance Methods

schema(_name, opts = {}) click to toggle source

Dynamically configures accessors, dirty tracking, validation, and serialization methods given definition in opts @param [Object] _name - name of schema @param [Hash] opts - See below

class AwesomeClass
  schema :my_schema,
    id: {
     type: Numeric,             # value will be checked using is_a?
     valid: -> (v) { v > 0 },   # value will be validated by calling this
     schema: [ChildClass]       # single or collection recursive checks
     doc: 'Id, number greater than 1'  # documentation string
    }
end

a = AwesomeClass.new(id: 1)
a.valid? => true
a.errors => {}
# File lib/utils/schema_model.rb, line 31
def schema(_name, opts = {})
  define_method(:definition) { opts }

  opts.each do |k, definition|
    # Reader
    attr_reader k

    # Writer
    define_writer! k, definition
  end
end

Private Instance Methods

define_writer!(k, definition) click to toggle source

Helper for dynamically defining writer method @param [Symbol] k - name of attribute @param [Hash] definition - See docstring for schema above

# File lib/utils/schema_model.rb, line 48
def define_writer!(k, definition)
  define_method("#{k}=") do |value|
    # Recursively convert hash and array of hash to schematized objects
    value = ensure_schema value, definition[:schema]

    # Initial value
    instance_variable_set "@#{k}", value

    # Dirty tracking
    self.changed_attributes ||= Set.new
    self.changed_attributes << k
  end
end