require 'volt/models/persistors/store' require 'volt/models/persistors/store_state' module Persistors class ModelStore < Store include StoreState ID_CHARS = [('a'..'f'), ('0'..'9')].map {|v| v.to_a }.flatten attr_reader :model attr_accessor :in_identity_map def initialize(model, tasks) super @in_identity_map = false end def add_to_collection @in_collection = true ensure_setup changed end def remove_from_collection @in_collection = false end # Called the first time a value is assigned into this model def ensure_setup if @model.attributes @model.attributes[:_id] ||= generate_id add_to_identity_map end end def add_to_identity_map unless @in_identity_map @@identity_map.add(@model._id, @model) @in_identity_map = true end end # Create a random unique id that can be used as the mongo id as well def generate_id id = [] 24.times { id << ID_CHARS.sample } return id.join end # Called when the model changes def changed(attribute_name=nil) path = @model.path promise = Promise.new ensure_setup path_size = path.size if !(defined?($loading_models) && $loading_models) && @tasks && path_size > 0 && !@model.nil? if path_size > 3 && (parent = @model.parent) && source = parent.parent @model.attributes[:"#{path[-4].singularize}_id"] = source._id end if !collection puts "Attempting to save model directly on store." raise "Attempting to save model directly on store." else StoreTasks.save(collection, self_attributes).then do |errors| if errors.size == 0 promise.resolve(nil) else promise.reject(errors) end end end end return promise end def event_added(event, first, first_for_event) if first_for_event && event == :changed ensure_setup end end # Update the models based on the id/identity map. Usually these requests # will come from the backend. def self.changed(model_id, data) model = @@identity_map.lookup(model_id) if model data.each_pair do |key, value| if key != :_id model.send(:"#{key}=", value) end end end end def [](val) raise "Models do not support hash style lookup. Hashes inserted into other models are converted to models, see https://github.com/voltrb/volt#automatic-model-conversion" end private # Return the attributes that are only for this store, not any sub-associations. def self_attributes # Don't store any sub-stores, those will do their own saving. @model.attributes.reject {|k,v| v.is_a?(Model) || v.is_a?(ArrayModel) } end def collection @model.path[-2] end end end