Module: Gorillib::Model::ClassMethods

Included in:
Builder::ClassMethods
Defined in:
lib/gorillib/model/base.rb,
lib/gorillib/model/schema_magic.rb,
lib/gorillib/model/serialization.rb

Instance Method Summary collapse

Instance Method Details

#assemble_positionalsObject



57
58
59
60
61
62
# File 'lib/gorillib/model/schema_magic.rb', line 57

def assemble_positionals
  positionals = fields.values.keep_if{|fld| fld.position? }.sort_by!{|fld| fld.position }
  return [] if positionals.empty?
  if (positionals.map(&:position) != (0..positionals.length-1).to_a) then raise ConflictingPositionError, "field positions #{positionals.map(&:position).join(",")} for #{positionals.map(&:name).join(",")} aren't in strict minimal order"  ; end
  positionals.map!(&:name)
end

#attrs_hash_from_args(args) ⇒ Hash

turn model constructor args (*positional_args, {attrs}) into a combined attrs hash. positional_args are mapped to the set of attribute names in order -- by default, the class' field names.

Notes:

  • Positional args always clobber elements of the attribute hash.
  • Nil positional args are treated as present-and-nil (this might change).
  • Raises an error if positional args

Parameters:

  • args (Array[Symbol])

    list of attributes, in order, to map.

Returns:

  • (Hash)

    a combined, reconciled hash of attributes to set



77
78
79
80
81
82
83
84
85
# File 'lib/gorillib/model/schema_magic.rb', line 77

def attrs_hash_from_args(args)
  attrs = args.extract_options!
  if args.present?
    ArgumentError.check_arity!(args, 0..positionals.length){ "extracting args #{args} for #{self}" }
    positionals_to_map = positionals[0..(args.length-1)]
    attrs = attrs.merge(Hash[positionals_to_map.zip(args)])
  end
  attrs
end

#collection(field_name, collection_type, options = {}) ⇒ Object



31
32
33
34
35
# File 'lib/gorillib/model/schema_magic.rb', line 31

def collection(field_name, collection_type, options={})
  options[:item_type] = options[:of] if options.has_key?(:of)
  field(field_name, collection_type, {
      field_type: ::Gorillib::Model::SimpleCollectionField}.merge(options))
end

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

Defines a new field

For each field that is defined, a getter and setter will be added as an instance method to the model. An Field instance will be added to result of the fields class method.

Examples:

field :height, Integer

Parameters:

  • field_name (Symbol)

    The field name. Must start with [A-Za-z_] and subsequently contain only [A-Za-z0-9_]

  • type (Class)

    The field's type (required)

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • doc (String)

    Documentation string for the field (optional)

  • default (Proc, Object)

    Default value, or proc that instance can evaluate to find default value

Returns:

  • Gorillib::Model::Field



21
22
23
24
25
26
27
28
29
# File 'lib/gorillib/model/schema_magic.rb', line 21

def field(field_name, type, options={})
  options = options.symbolize_keys
  field_type = options.delete(:field_type){ ::Gorillib::Model::Field }
  fld = field_type.new(self, field_name, type, options)
  @_own_fields[fld.name] = fld
  _reset_descendant_fields
  fld.send(:inscribe_methods, self)
  fld
end

#field_namesArray<Symbol>

Returns The attribute names.

Returns:



49
50
51
# File 'lib/gorillib/model/schema_magic.rb', line 49

def field_names
  @_field_names ||= fields.keys
end

#fields{Symbol => Gorillib::Model::Field}

Returns:



38
39
40
41
# File 'lib/gorillib/model/schema_magic.rb', line 38

def fields
  return @_fields if defined?(@_fields)
  @_fields = ancestors.reverse.inject({}){|acc, ancestor| acc.merge!(ancestor.try(:_own_fields) || {}) }
end

#from_tuple(*vals) ⇒ Object



31
32
33
# File 'lib/gorillib/model/serialization.rb', line 31

def from_tuple(*vals)
  receive Hash[field_names[0..vals.length-1].zip(vals)]
end

#has_field?(field_name) ⇒ true, false

Returns true if the field is defined on this class.

Returns:

  • (true, false)

    true if the field is defined on this class



44
45
46
# File 'lib/gorillib/model/schema_magic.rb', line 44

def has_field?(field_name)
  fields.has_key?(field_name)
end

#inspectObject

Returns Class name and its attributes.

Examples:

Inspect the model's definition.

Person.inspect #=> Person[first_name, last_name]

Returns:

  • Class name and its attributes



256
257
258
# File 'lib/gorillib/model/base.rb', line 256

def inspect
  "#{self.name || 'anon'}[#{ field_names.join(",") }]"
end

#inspect_compactObject



259
# File 'lib/gorillib/model/base.rb', line 259

def inspect_compact() self.name || inspect ; end

#native?(obj) ⇒ true, false

A native object does not need any transformation; it is accepted directly. By default, an object is native if it is_a? this class

Parameters:

  • obj (Object)

    the object that will be received

Returns:

  • (true, false)

    true if the item does not need conversion



248
249
250
# File 'lib/gorillib/model/base.rb', line 248

def native?(obj)
  obj.is_a?(self)
end

#positionalsObject



53
54
55
# File 'lib/gorillib/model/schema_magic.rb', line 53

def positionals
  @_positionals ||= assemble_positionals
end

#receive(attrs = {}, &block) ⇒ Gorillib::Model

Receive external data, type-converting and creating contained models as necessary

Returns:



232
233
234
235
236
237
238
239
240
241
# File 'lib/gorillib/model/base.rb', line 232

def receive(attrs={}, &block)
  return nil if attrs.nil?
  return attrs if native?(attrs)
  #
  Gorillib::Model::Validate.hashlike!(attrs){ "attributes for #{self.inspect}" }
  klass = attrs.has_key?(:_type) ? Gorillib::Factory(attrs[:_type]) : self
  warn "factory #{klass} is not a type of #{self} as specified in #{attrs}" unless klass <= self
  #
  klass.new(attrs, &block)
end

#typenameObject

A readable handle for this field



224
225
226
# File 'lib/gorillib/model/base.rb', line 224

def typename
  @typename ||= Gorillib::Inflector.underscore(self.name||'anon').gsub(%r{/}, '.')
end