class Squares::Base

Attributes

id[RW]

Public Class Methods

new(*args) click to toggle source
# File lib/squares/base.rb, line 5
def initialize *args
  build_instance *args
  trigger :after_initialize
end

Private Class Methods

[](id) click to toggle source
# File lib/squares/base.rb, line 163
def [] id
  if item = store[id]
    deserialize(item).tap do |item|
      item.instance_eval 'trigger :after_find'
    end
  end
end
Also aliased as: find
[]=(*args) click to toggle source
# File lib/squares/base.rb, line 172
      def []= *args
        id, instance = *args
        if instance.class == self
          instance.id = id
        elsif instance.respond_to?(:to_h)
          instance = self.new(id, instance)
        else
          raise ArgumentError.new(<<-ERR)
          You must provide an instance of #{self.name} or at least
          something which responds to #to_h"
          ERR
        end
        instance.tap do |i|
          i.instance_eval 'trigger :before_create'
          i.save
          i.instance_eval 'trigger :after_create'
        end
      end
Also aliased as: create
add_hook(hook_id, args, block) click to toggle source

/hooks

# File lib/squares/base.rb, line 335
def add_hook hook_id, args, block
  @_hooks ||= {}
  @_hooks[hook_id] ||= []
  @_hooks[hook_id] << block
end
after_create(*args, &block) click to toggle source
# File lib/squares/base.rb, line 307
def after_create *args, &block
  add_hook :after_create, args, block
end
after_find(*args, &block) click to toggle source
# File lib/squares/base.rb, line 315
def after_find *args, &block
  add_hook :after_find, args, block
end
after_initialize(*args, &block) click to toggle source
# File lib/squares/base.rb, line 311
def after_initialize *args, &block
  add_hook :after_initialize, args, block
end
after_save(*args, &block) click to toggle source
# File lib/squares/base.rb, line 323
def after_save *args, &block
  add_hook :after_save, args, block
end
before_create(*args, &block) click to toggle source
# File lib/squares/base.rb, line 303
def before_create *args, &block
  add_hook :before_create, args, block
end
before_destroy(*args, &block) click to toggle source
# File lib/squares/base.rb, line 327
def before_destroy *args, &block
  add_hook :before_destroy, args, block
end
before_save(*args, &block) click to toggle source
# File lib/squares/base.rb, line 319
def before_save *args, &block
  add_hook :before_save, args, block
end
create(*args)
Alias for: []=
defaults() click to toggle source
# File lib/squares/base.rb, line 275
def defaults
  @_defaults ||= {}
end
delete(id) click to toggle source
# File lib/squares/base.rb, line 218
def delete id
  store.delete id
end
deserialize(item) click to toggle source
# File lib/squares/base.rb, line 350
def deserialize item
  serializers.reverse.inject(item) do |memo, serializer|
    serializer.restore item
  end
end
each(&block) click to toggle source
# File lib/squares/base.rb, line 222
def each &block
  values.each &block
end
find(id)
Alias for: []
has_key?(key) click to toggle source
# File lib/squares/base.rb, line 192
def has_key? key
  store.has_key? key
end
Also aliased as: key?, member?, includes?
hooks() click to toggle source

hooks

# File lib/squares/base.rb, line 299
def hooks
  @_hooks
end
includes?(key)
Alias for: has_key?
inherited(subclass) click to toggle source
# File lib/squares/base.rb, line 345
def inherited(subclass)
  @_models ||= []
  @_models << subclass
end
key?(key)
Alias for: has_key?
keys() click to toggle source
# File lib/squares/base.rb, line 199
def keys
  store.keys
end
member?(key)
Alias for: has_key?
models() click to toggle source
# File lib/squares/base.rb, line 294
def models
  (@_models || []).uniq.sort { |a,b| a.to_s <=> b.to_s }
end
normalize_property(property) click to toggle source
# File lib/squares/base.rb, line 211
def normalize_property property
  unless properties.include?(property)
    property = "#{property}?".to_sym if properties.include?("#{property}?".to_sym)
  end
  properties.include?(property) && property
end
properties(*props) click to toggle source
# File lib/squares/base.rb, line 268
def properties *props
  props.each do |prop|
    property prop, {}
  end
  @_properties
end
property(prop, opts={}) click to toggle source
# File lib/squares/base.rb, line 253
def property prop, opts={}
  @_properties ||= []
  @_properties << prop
  uniquify_properties
  define_method prop do
    get_property prop
  end
  define_method "#{prop.to_s.gsub(/\?$/, '')}=" do |v|
    set_property prop, v
  end
  if opts.has_key?(:default)
    defaults[prop] = opts[:default]
  end
end
serializers() click to toggle source
# File lib/squares/base.rb, line 159
def serializers
  [Marshal]
end
store() click to toggle source
# File lib/squares/base.rb, line 290
def store
  @store ||= {}
end
store=(storage) click to toggle source
# File lib/squares/base.rb, line 286
def store= storage
  @store = storage
end
underscore_name() click to toggle source
# File lib/squares/base.rb, line 279
def underscore_name
  self.name.
    gsub(/::/, '/').
    gsub(/([^\/])([A-Z])/, '\1_\2').
    downcase
end
uniquify_properties() click to toggle source
# File lib/squares/base.rb, line 341
def uniquify_properties
  @_properties = @_properties.uniq.compact
end
valid_property?(property) click to toggle source
# File lib/squares/base.rb, line 207
def valid_property? property
  !!normalize_property(property)
end
values() click to toggle source
# File lib/squares/base.rb, line 203
def values
  store.values.map{ |i| deserialize i }
end
where(*args, &block) click to toggle source
# File lib/squares/base.rb, line 226
def where(*args, &block)
  result_set = []
  if block
    result_set = values.select(&block)
    return result_set if result_set.empty?
  end

  args.each do |arg|
    if arg.kind_of?(Hash)
      result_set = (!result_set.empty? ? result_set : values).reject do |i|
        failed_matches = 0
        arg.each do |k,v|
          raise ArgumentError.new("\"#{k}\" is not a valid property of #{self}") unless valid_property?(k)
          failed_matches += 1 unless i[k] == v
        end
        failed_matches > 0
      end
    elsif arg.kind_of?(Symbol)
      raise ArgumentError.new("\"#{arg}\" is not a valid property of #{self}") unless valid_property?(arg)
      result_set = (result_set.empty? ? values : result_set).select do |i|
        i[arg]
      end
    end
  end
  result_set
end

Public Instance Methods

==(other) click to toggle source
# File lib/squares/base.rb, line 27
def == other
  @id == other.id && properties_equal(other)
end
[](key) click to toggle source
# File lib/squares/base.rb, line 31
def [](key)
  get_property key
end
[]=(key, value) click to toggle source
# File lib/squares/base.rb, line 35
def []=(key, value)
  set_property key, value
end
changed?() click to toggle source
# File lib/squares/base.rb, line 47
def changed?
  @_changed
end
defaults() click to toggle source
# File lib/squares/base.rb, line 72
def defaults
  self.class.defaults
end
delete() click to toggle source
# File lib/squares/base.rb, line 18
def delete
  self.class.delete self.id
end
destroy() click to toggle source
# File lib/squares/base.rb, line 22
def destroy
  trigger :before_destroy
  delete
end
properties() click to toggle source
# File lib/squares/base.rb, line 51
def properties
  self.class.properties
end
save() click to toggle source
# File lib/squares/base.rb, line 10
def save
  trigger :before_save
  @_changed = false
  store[@id] = serialize
  trigger :after_save
  nil
end
serialize() click to toggle source
# File lib/squares/base.rb, line 76
def serialize
  serializers.inject(self.dup) do |memo, serializer|
    serializer.dump memo
  end
end
to_h(key_name = :id) click to toggle source
# File lib/squares/base.rb, line 59
def to_h(key_name = :id)
  { :type => self.class.name, key_name => id }.tap do |h|
    properties.each do |property|
      h[property] = self[property]
    end
  end
end
Also aliased as: to_hash
to_hash(key_name = :id)
Alias for: to_h
to_json(key_name = :id) click to toggle source
# File lib/squares/base.rb, line 55
def to_json(key_name = :id)
  to_hash(key_name).to_json
end
update_attributes(new_properties)
Alias for: update_properties
update_properties(new_properties) click to toggle source
# File lib/squares/base.rb, line 39
def update_properties new_properties
  new_properties.each do |key, value|
    self[key] = value if valid_property?(key)
  end
  save
end
Also aliased as: update_attributes
valid_property?(property) click to toggle source
# File lib/squares/base.rb, line 68
def valid_property? property
  self.class.valid_property? property
end

Private Instance Methods

build_instance(*args) click to toggle source
# File lib/squares/base.rb, line 106
def build_instance *args
  @id, values = *args
  values_hash = values.to_h
  properties_sorted_by_defaults.each do |property|
    value = values_hash.has_key?(property) ? values_hash[property] : default_for(property)
    set_property property, value
  end
end
default_for(property) click to toggle source
# File lib/squares/base.rb, line 123
def default_for property
  defaults[property].respond_to?(:call) ?
    defaults[property].call(self) :
    defaults[property]
end
get_property(property) click to toggle source
# File lib/squares/base.rb, line 129
def get_property property
  instance_variable_get "@#{instance_var_string_for property}"
end
instance_var_string_for(property) click to toggle source
# File lib/squares/base.rb, line 142
def instance_var_string_for property
  property = self.class.normalize_property property
  if property.to_s.match(/\?$/)
    "#{property.to_s.gsub(/\?$/,'')}__question__".to_sym
  else
    property
  end
end
properties_equal(other) click to toggle source
# File lib/squares/base.rb, line 100
def properties_equal other
  ! properties.detect do |property|
    self.send(property) != other.send(property)
  end
end
properties_sorted_by_defaults() click to toggle source
# File lib/squares/base.rb, line 115
def properties_sorted_by_defaults
  (properties || []).sort do |a,b|
    a_val = defaults[a].respond_to?(:call) ? 1 : 0
    b_val = defaults[b].respond_to?(:call) ? 1 : 0
    a_val <=> b_val
  end
end
serializers() click to toggle source
# File lib/squares/base.rb, line 84
def serializers
  self.class.serializers
end
set_property(property, value) click to toggle source
# File lib/squares/base.rb, line 133
def set_property property, value
  unless valid_property?(property)
    raise ArgumentError.new("\"#{property}\" is not a valid property of #{self.class}")
  end
  instance_variable_set("@#{instance_var_string_for property}", value).tap do |value|
    @_changed = true
  end
end
store() click to toggle source
# File lib/squares/base.rb, line 151
def store
  self.class.store
end
trigger(hook_name) click to toggle source
# File lib/squares/base.rb, line 88
def trigger hook_name
  return if @hook_callback_in_progress
  hooks = self.class.hooks
  if hooks && hooks[hook_name]
    hooks[hook_name].each do |hook|
      @hook_callback_in_progress = true
      self.instance_eval &hook
      @hook_callback_in_progress = false
    end
  end
end