Class: Metro::Model::Property

Inherits:
Object
  • Object
show all
Includes:
Units
Defined in:
lib/metro/models/properties/property.rb

Overview

Note:

Property is intented to be subclassed to provide filtering of particular types.

A property is a value filter that allows you to specify filtering options both on the setting and the getting of a value. The property itself does not maintain any of these values but keeps in mind the particular model and options that it is created when applying the filtering.

Constant Summary

Constants included from Units

Units::Bounds

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, options = {}, &block) ⇒ Property

Returns a new instance of Property.

Parameters:

  • model (Model)

    the model associated with this property.

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

    the additional options that may be set with this property. This may be default values or options on how this properby should behave.



23
24
25
26
27
# File 'lib/metro/models/properties/property.rb', line 23

def initialize(model,options={},&block)
  @model = model
  @options = options
  @block = block
end

Instance Attribute Details

#blockObject (readonly)

Returns the value of attribute block.



15
16
17
# File 'lib/metro/models/properties/property.rb', line 15

def block
  @block
end

#modelObject (readonly)

Returns the value of attribute model.



15
16
17
# File 'lib/metro/models/properties/property.rb', line 15

def model
  @model
end

#optionsObject (readonly)

Returns the value of attribute options.



15
16
17
# File 'lib/metro/models/properties/property.rb', line 15

def options
  @options
end

Class Method Details

.define_property(name, options = {}) ⇒ Object

Allow a property to define a sub-property.

A sub-property that is defined can be any type of exiting properties. Which may also define more sub-properties. These sub-properties will be available as properties through the names provided.

The sub-properties can also be prefixed with the parent property name:

If you define a property with the non-default name it will automatically add the prefix to all the sub-properties. This is to prevent any getter/setter method name collisions.

Examples:

DimensionProperty defining two numeric sub-properties for height and width


class DimensionsProperty < Property
  define_property :width
  define_property :height
end

class Frogger < Metro::Model
  property :dimensions

  def after_initialize
    puts "Frog dimensions are #{dimensions}"
    puts "(#{dimensions.width},#{dimensions.height}) == (#{width},#{height})"
  end
end

FontProperty defines sub-properties which include the parent propery prefix


class FontProperty < Property
  define_property :size, prefix: true
  define_property :name, type: :text, prefix: true
end

class MyLabel < Metro::Model
  property :font

  def after_initialize
    puts "Font is: #{font} - #{font_name}:#{font_size}"
  end
end

DimensionProperty defining two numeric sub-properties for height and width


class DimensionsProperty < Property
  define_property :width
  define_property :height
end

class Frogger < Metro::Model
  property :dims, type: :dimensions

  def after_initialize
    puts "Frog dimensions are #{dims}"
    puts "(#{dims.width},#{dims.height}) == (#{dims_width},#{dims_height})"
  end
end


134
135
136
# File 'lib/metro/models/properties/property.rb', line 134

def self.define_property(name,options = {})
  defined_properties.push PropertyDefinition.new name, options
end

.defined_propertiesObject

Returns an array of all the defined properties.

Returns:

  • an array of all the defined properties.



141
142
143
# File 'lib/metro/models/properties/property.rb', line 141

def self.defined_properties
  @defined_properties ||= []
end

.get(*types, &block) ⇒ Object

Define a filter block for getting a value of that type.



30
31
32
33
34
35
# File 'lib/metro/models/properties/property.rb', line 30

def self.get(*types,&block)
  types = [ NilClass ] if types.empty?
  types.each do |type|
    gets[type.to_s] = block
  end
end

.get_or_set(type = NilClass, &block) ⇒ Object

Define a filter block that applies to both the setting and getting of a property.



70
71
72
73
# File 'lib/metro/models/properties/property.rb', line 70

def self.get_or_set(type=NilClass,&block)
  gets[type.to_s] = block
  sets[type.to_s] = block
end

.getsObject

All get filter blocks defined



38
39
40
# File 'lib/metro/models/properties/property.rb', line 38

def self.gets
  @gets ||= hash_with_default_to_nil
end

.hash_with_default_to_nilObject

Generate a hash that will default all missing keys to the NilClass key and the NilClass key will return a cource of action that will raise an exception. This means by default that if it is not overridden an error is generated.



179
180
181
182
183
# File 'lib/metro/models/properties/property.rb', line 179

def self.hash_with_default_to_nil
  hash = HashWithIndifferentAccess.new { |hash,key| hash["NilClass"] }
  hash["NilClass"] = lambda { |value| raise "#{self} is not able to translate the #{value} (#{value.class})" }
  hash
end

.inherited(subclass) ⇒ Object

Capture all the subclassed properties and add them to the availble list of properties.



149
150
151
152
# File 'lib/metro/models/properties/property.rb', line 149

def self.inherited(subclass)
  property_name = subclass.to_s.gsub(/Property$/,'').split("::").last.underscore
  properties_hash[property_name] = subclass.to_s
end

.propertiesObject



154
155
156
# File 'lib/metro/models/properties/property.rb', line 154

def self.properties
  @properties ||= []
end

.properties_hashObject

Generate a properties hash. This properties will default to the numeric key when the property type cannot be found.



170
171
172
# File 'lib/metro/models/properties/property.rb', line 170

def self.properties_hash
  @properties_hash ||= HashWithIndifferentAccess.new { |hash,key| hash[:numeric] }
end

.property(name) ⇒ Object

Returns a Property Class that matches the specified name.

Returns:

  • a Property Class that matches the specified name.



161
162
163
164
# File 'lib/metro/models/properties/property.rb', line 161

def self.property(name)
  property_classname = properties_hash[name]
  property_classname.constantize
end

.set(*types, &block) ⇒ Object

Define a filter block for setting a value of the type.



50
51
52
53
54
55
# File 'lib/metro/models/properties/property.rb', line 50

def self.set(*types,&block)
  types = [ NilClass ] if types.empty?
  types.each do |type|
    sets[type.to_s] = block
  end
end

.setsObject

All set filter blocks defined



58
59
60
# File 'lib/metro/models/properties/property.rb', line 58

def self.sets
  @sets ||= hash_with_default_to_nil
end

Instance Method Details

#get(value) ⇒ Object

Perform a get of the value, running it through the get filter block that matches the type.



44
45
46
47
# File 'lib/metro/models/properties/property.rb', line 44

def get(value)
  get_block = self.class.gets[value.class.to_s]
  instance_exec(value,&get_block)
end

#set(value) ⇒ Object

Perform a set of the value, running it through the set filter block that matches the type.



64
65
66
67
# File 'lib/metro/models/properties/property.rb', line 64

def set(value)
  set_block = self.class.sets[value.class.to_s]
  instance_exec(value,&set_block)
end