Class: Store

Inherits:
Model show all
Defined in:
lib/volt/models/store.rb

Constant Summary collapse

ID_CHARS =
[('a'..'z'), ('A'..'Z'), ('0'..'9')].map {|v| v.to_a }.flatten
@@identity_map =
{}

Instance Attribute Summary collapse

Attributes inherited from Model

#attributes, #parent, #path

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Model

#!, #<<, #==, #assign_attribute, #delete, #expand!, #false?, #inspect, #nil?, #read_attribute, #return_undefined_method, #trigger_by_attribute!, #true?

Methods included from ObjectTracking

#__setup_tracking

Methods included from ModelWrapper

#wrap_value, #wrap_values

Methods included from ReactiveTags

included, #reactive_method_tag

Constructor Details

#initialize(tasks = nil, *args) ⇒ Store

Returns a new instance of Store.



10
11
12
13
14
15
16
17
18
19
# File 'lib/volt/models/store.rb', line 10

def initialize(tasks=nil, *args)
  @tasks = tasks
  @state = :not_loaded

  super(*args)
  
  track_in_identity_map if attributes && attributes[:_id]
  
  value_updated
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/volt/models/store.rb', line 62

def method_missing(method_name, *args, &block)
  if method_name[-1] == ']'
    # Load the model
    self.load!
  end

  result = super
  
  if method_name[0] == '_' && method_name[-1] == '='
    # Trigger value updated after an assignment
    self.value_updated
  end
  
  return result
end

Instance Attribute Details

#stateObject (readonly)

Returns the value of attribute state.



8
9
10
# File 'lib/volt/models/store.rb', line 8

def state
  @state
end

Class Method Details

.update(model_id, data) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/volt/models/store.rb', line 43

def self.update(model_id, data)
  model = @@identity_map[model_id]
  
  if model
    data.each_pair do |key, value|
      if key != '_id'
        model.send(:"#{key}=", value)
      end
    end
  end
end

Instance Method Details

#change_channel_connection(add_or_remove) ⇒ Object



36
37
38
39
40
41
# File 'lib/volt/models/store.rb', line 36

def change_channel_connection(add_or_remove)
  if attributes && path.size > 1
    channel_name = "#{path[-2]}##{attributes[:_id]}"
    $page.tasks.call('ChannelTasks', "#{add_or_remove}_listener", channel_name)
  end    
end

#collection(path = nil) ⇒ Object



112
113
114
115
116
117
118
119
# File 'lib/volt/models/store.rb', line 112

def collection(path=nil)
  path ||= self.path
  
  collection_name = path.last
  collection_name = path[-2] if collection_name == :[]
  
  return collection_name
end

#ensure_idObject

When called, will setup an id if there is not one



83
84
85
86
87
88
89
# File 'lib/volt/models/store.rb', line 83

def ensure_id
  # No id yet, lets create one
  if attributes && !attributes[:_id]
    self.attributes[:_id] = generate_id
    track_in_identity_map
  end
end

#event_added(event, scope_provider, first) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/volt/models/store.rb', line 21

def event_added(event, scope_provider, first)
  if first && event == :changed
    # Start listening
    ensure_id
    change_channel_connection("add")
  end
end

#event_removed(event, no_more_events) ⇒ Object



29
30
31
32
33
34
# File 'lib/volt/models/store.rb', line 29

def event_removed(event, no_more_events)
  if no_more_events && event == :changed
    # Stop listening
    change_channel_connection("remove")
  end
end

#generate_idObject



55
56
57
58
59
60
# File 'lib/volt/models/store.rb', line 55

def generate_id
  id = []
  12.times { id << ID_CHARS.sample }
  
  return id.join
end

#load!Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/volt/models/store.rb', line 136

def load!
  if @state == :not_loaded
    @state = :loading
  
    if @tasks && path.last.plural?
      # Check to see the parents scope so we can only lookup associated
      # models.
      scope = {}
    
      # Scope to the parent
      if path.size > 2 && (attrs = parent.attributes) && attrs[:_id].true?
        scope[:"#{path[-3].singularize}_id"] = parent._id
      end
      
      load_child_models(scope)
    end
  end
  
  return self
end

#load_child_models(scope) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
# File 'lib/volt/models/store.rb', line 157

def load_child_models(scope)
  # puts "FIND: #{collection(path).inspect} at #{scope.inspect}"
  @tasks.call('StoreTasks', 'find', collection(path), scope) do |results|
    # TODO: Globals evil, replace
    $loading_models = true
    results.each do |result|
      self << Store.new(@tasks, result, self, path + [:[]], @class_paths)
    end
    $loading_models = false
  end
end

#new_array_model(*args) ⇒ Object



173
174
175
# File 'lib/volt/models/store.rb', line 173

def new_array_model(*args)
  StoreArray.new(@tasks, *args)
end

#new_model(attributes = {}, parent = nil, path = nil, class_paths = nil) ⇒ Object



169
170
171
# File 'lib/volt/models/store.rb', line 169

def new_model(attributes={}, parent=nil, path=nil, class_paths=nil)
  return Store.new(@tasks, attributes, parent, path, class_paths)
end

#read_new_model(method_name) ⇒ Object

On stores, we store the model so we don’t have to look it up every time we do a read.



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/volt/models/store.rb', line 123

def read_new_model(method_name)
  model = new_model(nil, self, path + [method_name])
  
  self.attributes ||= {}
  attributes[method_name] = model
  
  if model.state == :not_loaded
    model.load!
  end
  
  return model
end

#self_attributesObject

Return the attributes that are only for this store, not any sub-associations.



107
108
109
110
# File 'lib/volt/models/store.rb', line 107

def self_attributes
  # Don't store any sub-stores, those will do their own saving.
  attrs = attributes.reject {|k,v| v.is_a?(Model) || v.is_a?(ArrayModel) }    
end

#track_in_identity_mapObject



78
79
80
# File 'lib/volt/models/store.rb', line 78

def track_in_identity_map
  @@identity_map[attributes[:_id]] = self
end

#value_updatedObject



91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/volt/models/store.rb', line 91

def value_updated
  path_size = path.size
  if !(defined?($loading_models) && $loading_models) && @tasks && path_size > 0 && !nil?
    
    ensure_id
    
    if path_size > 3 && parent && source = parent.parent
      self.attributes[:"#{path[-4].singularize}_id"] = source._id
    end
    
    # puts "Save: #{collection} - #{attrs.inspect}"
    @tasks.call('StoreTasks', 'save', collection, self_attributes)
  end
end