class MetalArchives::BaseModel

Abstract model class

Attributes

properties[RW]

Array of declared properties

Public Class Methods

new(hash = {}) click to toggle source

Generic shallow copy constructor

# File lib/metal_archives/models/base_model.rb, line 9
def initialize(hash = {})
  raise Errors::NotImplementedError, 'no :id property in model' unless respond_to? :id?, true

  hash.each do |property, value|
    instance_variable_set("@#{property}", value) if self.class.properties.include? property
  end
end

Protected Class Methods

boolean(name, opts = {}) click to toggle source

Defines a model boolean property. This method is an alias for enum name, :values => [true, false]

name

Name of the property

opts
multiple

Whether or not the property has multiple values (which turns it into an Array of type)

# File lib/metal_archives/models/base_model.rb, line 209
def boolean(name, opts = {})
  enum name, opts.merge(:values => [true, false])
end
cache() click to toggle source

Get class-level object cache

# File lib/metal_archives/models/base_model.rb, line 88
def cache
  @cache ||= MetalArchives::LRUCache.new MetalArchives.config.cache_size
end
enum(name, opts) click to toggle source

Defines a model enum property.

name

Name of the property

opts
values

Required. An array of possible values

multiple

Whether or not the property has multiple values (which turns it into an Array of type)

# File lib/metal_archives/models/base_model.rb, line 163
def enum(name, opts)
  raise ArgumentError, 'opts[:values] is required' unless opts and opts[:values]

  (@properties ||= []) << name

  # property
  define_method(name) do
    load! unless loaded? && instance_variable_defined?("@#{name}")
    instance_variable_get("@#{name}")
  end

  # property?
  define_method("#{name}?") do
    load! unless loaded? && instance_variable_defined?("@#{name}")

    property = instance_variable_get("@#{name}")
    property.respond_to?(:empty?) ? !property.empty? : !!property
  end

  # property=
  define_method("#{name}=") do |value|
    # Check enum type
    if opts[:multiple]
      raise MetalArchives::Errors::TypeError, "invalid enum value #{value}, must be Array for #{name}" unless value.is_a? Array
      value.each do |val|
        raise MetalArchives::Errors::TypeError, "invalid enum value #{val} for #{name}" unless opts[:values].include? val
      end
    else
      raise MetalArchives::Errors::TypeError, "invalid enum value #{value} for #{name}" unless opts[:values].include? value
    end

    instance_variable_set name, value
  end
end
property(name, opts = {}) click to toggle source

Defines a model property.

name

Name of the property

opts
type

Data type of property (a constant)

Default: String

multiple

Whether or not the property has multiple values (which turns it into an Array of type)

# File lib/metal_archives/models/base_model.rb, line 110
def property(name, opts = {})
  (@properties ||= []) << name

  # property
  define_method(name) do
    load! unless loaded? && instance_variable_defined?("@#{name}") || name ==(:id)
    instance_variable_get("@#{name}")
  end

  # property?
  define_method("#{name}?") do
    load! unless loaded? && instance_variable_defined?("@#{name}") || name ==(:id)

    property = instance_variable_get("@#{name}")
    property.respond_to?(:empty?) ? !property.empty? : !!property
  end

  # property=
  define_method("#{name}=") do |value|
    if value.nil?
      instance_variable_set "@#{name}", value
      return
    end

    # Check value type
    type = opts[:type] || String
    if opts[:multiple]
      raise MetalArchives::Errors::TypeError, "invalid type #{value.class}, must be Array for #{name}" unless value.is_a? Array
      value.each do |val|
        raise MetalArchives::Errors::TypeError, "invalid type #{val.class}, must be #{type} for #{name}" unless val.is_a? type
      end
    else
      raise MetalArchives::Errors::TypeError, "invalid type #{value.class}, must be #{type} for #{name}" unless value.is_a? type
    end

    instance_variable_set "@#{name}", value
  end
end

Public Instance Methods

==(obj) click to toggle source

Returns true if two objects have the same type and id

# File lib/metal_archives/models/base_model.rb, line 20
def ==(obj)
  obj.instance_of?(self.class) && id ==(obj.id)
end
cached?() click to toggle source

Whether or not the object is currently cached

# File lib/metal_archives/models/base_model.rb, line 60
def cached?
  loaded? && self.class.cache.include?(id)
end
load!() click to toggle source

Fetch, parse and load the data

Raises
# File lib/metal_archives/models/base_model.rb, line 31
def load!
  raise Errors::InvalidIDError, 'no id present' unless !!id

  # Use constructor to set attributes
  initialize assemble

  # Set empty properties to nil
  self.class.properties.each do |prop|
    instance_variable_set("@#{prop}", nil) unless instance_variable_defined? "@#{prop}"
  end

  @loaded = true
  self.class.cache[id] = self
rescue => e
  # Don't cache invalid requests
  self.class.cache.delete id
  raise e
end
loaded?() click to toggle source

Whether or not the object is currently loaded

# File lib/metal_archives/models/base_model.rb, line 53
def loaded?
  !@loaded.nil?
end

Protected Instance Methods

assemble() click to toggle source

Fetch the data and assemble the model

Override this method

Raises
# File lib/metal_archives/models/base_model.rb, line 75
def assemble
  raise Errors::NotImplementedError, 'method :assemble not implemented'
end