module IMW
class Metadata
# Conceptually, a field is a "slot" for which "records" can have
# values.
#
# An IMW::Metadata::Field is essentially a Hash that has one required
# property: a name.
#
# IMW::Metadata::Field.new('id')
# #=> { 'name' => 'id' }
#
# But you can declare as many other properties as you want (as long
# as you include a +name+):
#
# IMW::Metadata::Field.new 'name' => 'id', 'type' => :integer, 'title' => "ID", 'description' => "Auto-incremented."
# #=> { 'name' => 'id', 'type' => :integer, 'title' > "ID", 'description' => "Auto-incremented." }
#
# Some properties make a field special:
#
# has_many::
# Denotes that this record is in a "has_many" relationship with
# one or more other records. The corresponding value should be
# an array
#
# has_one::
# Denotes that this record is in a "has_one" relationship with
# one or more other records. The corresponding value should be
# an Array in which each key names the joined record and each
# value is an Array of fields describing the joined record..
#
# @see IMW::Metadata::Record for more usage of the
# :has_many and :has_one properties.
class Field < Hash
def initialize obj
super()
if obj.is_a?(Hash) || obj.is_a?(Field)
merge!(obj)
raise IMW::ArgumentError.new("A field must have a name") if obj['name'].blank?
else
self['name'] = obj.to_s.strip
end
end
def hierarchical?
has_key?('has_many') || has_key?('has_one')
end
alias_method :nested?, :hierarchical?
def flat?
! hierarchical?
end
def titleize
self['title'] || self['name'].capitalize # FIXME we can do better than this!
end
def associations
end
end
end
end