Class: Mementus::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/mementus/model.rb

Overview

Proof of concept for a toy ORM that combines some aspects of the ActiveRecord API with an in-memory query model based on the Axiom relational algebra API.

Constant Summary collapse

@@local_storage =
nil
@@model_registry =
{}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.collectionObject



84
85
86
87
88
89
90
91
92
# File 'lib/mementus/model.rb', line 84

def self.collection
  @@local_storage ||= Axiom::Adapter::Memory.new

  if @@local_storage.has_key?(name_to_sym)
    @@local_storage[name_to_sym]
  else
    Axiom::Relation.new(self.new.schema_tuple)
  end
end

.inherited(concrete_model) ⇒ Object



12
13
14
15
# File 'lib/mementus/model.rb', line 12

def self.inherited(concrete_model)
  concrete_model.send(:include, Virtus.model)
  concrete_model.send(:extend, Relation::ClassMethods)
end

.name_to_symObject



20
21
22
23
# File 'lib/mementus/model.rb', line 20

def self.name_to_sym  
  name_without_namespace = name.split("::").last
  name_without_namespace.gsub(/([^\^])([A-Z])/,'\1_\2').downcase.to_sym
end

.scope(name, conditions) ⇒ Object

TODO: fix incomplete scope chaining



95
96
97
98
99
100
101
102
103
# File 'lib/mementus/model.rb', line 95

def self.scope(name, conditions)
  if conditions.is_a? Hash
    scope_method = lambda { self.where(conditions) }
  elsif conditions.is_a? Proc
    scope_method = conditions
  end

  define_singleton_method(name, &scope_method)
end

Instance Method Details

#cache_keyObject

Unique cache identifier for this instance



27
28
29
# File 'lib/mementus/model.rb', line 27

def cache_key
  "#{self.class.name_to_sym.to_s}-#{object_id.to_s}"
end

#createObject

Create only writes to memory. It’s required in order to index the object’s attributes in the query model.



56
57
58
59
60
# File 'lib/mementus/model.rb', line 56

def create
  ensure_registered(self)
  local_storage[self.class.name_to_sym].insert([values_tuple])
  self.class.cache_put(self.cache_key, self)
end

#ensure_registered(model) ⇒ Object



62
63
64
# File 'lib/mementus/model.rb', line 62

def ensure_registered(model)
  register(model) unless registered?(model)
end

#local_storageObject



80
81
82
# File 'lib/mementus/model.rb', line 80

def local_storage
  @@local_storage ||= Axiom::Adapter::Memory.new
end

#model_registryObject



76
77
78
# File 'lib/mementus/model.rb', line 76

def model_registry
  @@model_registry
end

#register(model) ⇒ Object



70
71
72
73
74
# File 'lib/mementus/model.rb', line 70

def register(model)
  model_id = model.class.name_to_sym
  model_registry[model_id] = true
  local_storage[model_id] = Axiom::Relation.new(model.schema_tuple)
end

#registered?(model) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/mementus/model.rb', line 66

def registered?(model)
  model_registry.has_key? model.class.name_to_sym
end

#schema_tupleObject

TODO: this mapping could be based on declared indexes, rather than dumping the entire attribute schema here.



34
35
36
37
38
39
40
# File 'lib/mementus/model.rb', line 34

def schema_tuple
  tuple = [[:__cache_key, String]]
  attribute_set.each do |attribute_type|
    tuple << [attribute_type.name.to_sym, attribute_type.primitive]
  end
  tuple
end

#values_tupleObject

TODO: this mapping could be based on declared indexes, rather than dumping the entire attribute data set here.



45
46
47
48
49
50
51
# File 'lib/mementus/model.rb', line 45

def values_tuple
  tuple = [cache_key]
  attributes.each do |_, attribute_value|
    tuple << attribute_value
  end
  tuple
end