Module: Icss::Meta::RecordType

Includes:
NamedType
Included in:
ErrorSchema, ReceiverModel::ClassMethods
Defined in:
lib/icss/type/record_type.rb,
lib/icss/type/record_field.rb

Overview

RecordType – class methods for a RecordModel

Endows the model class with

  • klass.field – adds a field

  • klass.fields – list of record_fields

  • klass.after_receive(&blk) – blocks to execute after .receive is called

  • klass.after_receivers – list of after_receivers

  • klass.metamodel – overlay module that actually carries the model’s instance methods

  • klass.to_schema –

Instance Method Summary collapse

Methods included from NamedType

#basename, #doc, #doc=, #fullname, #is_core?, make, #metamodel, #namespace, #pathname

Instance Method Details

#after_receive(after_hook_name, &after_hook) ⇒ Object

make a block to run after each time .receive! is invoked



183
184
185
186
# File 'lib/icss/type/record_type.rb', line 183

def after_receive(after_hook_name, &after_hook)
  @after_receivers ||= {}
  @after_receivers[after_hook_name] = after_hook
end

#after_receiversObject

after_receive blocks for self and all ancestors



189
190
191
192
193
# File 'lib/icss/type/record_type.rb', line 189

def after_receivers
  all_f = {} # @after_receivers || {}
  call_ancestor_chain(:after_receivers){|anc_f| all_f.merge!(anc_f) }
  all_f
end

#field(field_name, type, schema = {}) ⇒ Object

Describes a field in a Record object.

Each field has the following attributes:

Parameters:

  • name (Symbol)

    – a string providing the name of the field (required)

  • type (Class, Icss::Meta::Type)

    a schema, or a string or symbol naming a record definition (required)

    avro type     json type   ruby type   kind        example
    ---------     ---------   ----------  --------    ---------
    null          null        NilClass    simple   nil
    boolean       boolean     Boolean     simple   true
    int,long      integer     Integer     simple   1
    float,double  number      Float       simple   1.1
    bytes         string      String      simple   "\u00FF"
    string        string      String      simple   "foo"
    record        object      RecordModel  named       {"a": 1}
    enum          string      Enum        named       "FOO"
    array         array       Array       container  [1]
    map           object      Hash        container  { "a": 1 }
    fixed         string      String      container  "\u00ff"
    union         object      XxxFactory  union
    time          string      Time        simple      "2011-01-02T03:04:05Z"
    
  • schema (Hash) (defaults to: {})

    a customizable set of options

Options Hash (schema):

  • :doc (String)

    – description of field for users (optional)

  • :default (Object)

    – a default value for this field, used when reading instances that lack this field (optional). Permitted values depend on the field’s schema type, according to the table below. Default values for union fields correspond to the first schema in the union. Default values for bytes and fixed fields are JSON strings, where Unicode code points 0-255 are mapped to unsigned 8-bit byte values 0-255.

  • :order (String)

    – specifies how this field impacts sort ordering of this record (optional). Valid values are “ascending” (the default), “descending”, or “ignore”. For more details on how this is used, see the the sort order section below.

  • :required (Boolean)

    – same as :validates => :presence

  • :validates (Hash)

    – sends the validation on to Icss::Type::Validations. Uses syntax parallel to ActiveModel’s:

  • :accessor (Symbol)

    – with :none, no accessor is created. With :protected, :private, or :public, applies corresponding access rule.

    :presence     => true
    :uniqueness   => true
    :numericality => true
    :length       => { :minimum => 0, maximum => 2000 }
    :format       => { :with => /.*/ }
    :inclusion    => { :in => [1,2,3] }
    :exclusion    => { :in => [1,2,3] }
    


96
97
98
99
100
101
102
103
# File 'lib/icss/type/record_type.rb', line 96

def field(field_name, type, schema={})
  field_name = field_name.to_sym
  #
  schema = add_field_schema(field_name, type, schema)
  add_field_accessor(field_name, schema)
  rcvr(field_name, schema)
  add_validator(field_name) if respond_to?(:add_validator)
end

#field_named(fn) ⇒ Object



115
116
117
118
119
# File 'lib/icss/type/record_type.rb', line 115

def field_named(fn)
  fn = fn.to_sym
  ancestors.each{|anc| hsh = anc.instance_variable_get('@field_schemas') or next ; return(hsh[fn]) if hsh[fn] }
  nil
end

#field_namesObject



105
106
107
108
109
# File 'lib/icss/type/record_type.rb', line 105

def field_names
  all_f = []
  call_ancestor_chain(:field_names){|anc_f| all_f = all_f | anc_f }
  all_f
end

#fieldsObject



111
112
113
# File 'lib/icss/type/record_type.rb', line 111

def fields
  field_schemas.values # _at(*field_names)
end

#has_field?(fn) ⇒ Boolean

Returns:



121
122
123
# File 'lib/icss/type/record_type.rb', line 121

def has_field?(fn)
  !! field_schemas.has_key?(fn.to_sym)
end

#rcvr(field_name, schema = {}) ⇒ Object

define a receiver attribute.

Parameters:

  • field_name (Symbol)
    • name of the receiver property

  • type (Class)
    • a

  • [Object] (Hash)

    a customizable set of options

  • [Class] (Hash)

    a customizable set of options



134
135
136
137
138
139
140
141
142
# File 'lib/icss/type/record_type.rb', line 134

def rcvr(field_name, schema={})
  return if schema[:receiver] == :none
  klass = schema[:type]
  define_metamodel_method("receive_#{field_name}") do |val|
    _set_field_val(field_name, klass.receive(val))
  end
  _register_rcvr_for(field_name, "receive_#{field_name}")
  add_after_receivers(field_name)
end

#rcvr_alias(fake_attr, field_name) ⇒ Object



144
145
146
# File 'lib/icss/type/record_type.rb', line 144

def rcvr_alias(fake_attr, field_name)
  _register_rcvr_for(fake_attr, "receive_#{field_name}")
end

#rcvr_remaining(field_name, schema = {}) ⇒ Object

Defines a receiver for attributes sent to receive! that are

  • not defined as receivers

  • field’s name does not start with ‘_’

Examples:

class Foo ; include RecordModel
  field  :bob, String
  rcvr_remaining :other_params
end
foo_obj = Foo.receive(:bob => 'hi, bob", :joe => 'hi, joe')
# => <Foo @bob='hi, bob' @other_params={ :joe => 'hi, joe' }>


172
173
174
175
176
177
178
179
180
# File 'lib/icss/type/record_type.rb', line 172

def rcvr_remaining(field_name, schema={})
  schema[:values] ||= Object
  field(field_name, Hash, schema)
  after_receive(:rcvr_remaining) do |hsh|
    remaining_vals_hsh = hsh.reject{|k,v| (self.class.has_field?(k)) || (k.to_s =~ /^_/) }
    self.send("receive_#{field_name}", remaining_vals_hsh)
  end
  add_after_receivers(field_name)
end

#receive(*args) ⇒ Object

Returns a new instance with the given hash used to set all rcvrs.

All args up to the last one are passed to the initializer. The last arg must be a hash – its attributes are set on the newly-created object

Parameters:

  • hsh (Hash)

    attr-value pairs to set on the newly created object.

  • *args (Array)

    arguments to pass to the constructor

Returns:

Raises:

  • (ArgumentError)


29
30
31
32
33
34
# File 'lib/icss/type/record_type.rb', line 29

def receive *args
  hsh = args.pop
  raise ArgumentError, "#{self} can't receive '#{hsh.inspect}' (it isn't hashlike)" unless hsh.respond_to?(:[]) && hsh.respond_to?(:has_key?)
  obj = self.new(*args)
  obj.receive!(hsh)
end

#to_schemaObject



149
150
151
152
153
154
155
156
157
158
# File 'lib/icss/type/record_type.rb', line 149

def to_schema
  {
    :name      => fullname,
    :namespace => namespace,
    :type      => :record,
    :is_a      => (respond_to?(:is_a) ? is_a : []),
    :doc       => doc,
    :fields    => fields.map(&:to_hash),
   }.compact_blank
end