class Volt::Persistors::ModelStore

Attributes

in_identity_map[RW]
model[R]

Public Class Methods

changed(model_id, data) click to toggle source

Update the models based on the id/identity map. Usually these requests will come from the backend.

# File lib/volt/models/persistors/model_store.rb, line 133
def self.changed(model_id, data)
  Model.no_save do
    model = @@identity_map.lookup(model_id)

    if model
      data.each_pair do |key, value|
        model.set(key, value)# if key != :id
      end
    end
  end
end
new(model, tasks) click to toggle source
Calls superclass method
# File lib/volt/models/persistors/model_store.rb, line 12
def initialize(model, tasks)
  super

  @in_identity_map = false
end

Public Instance Methods

[](val) click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 145
def [](val)
  fail '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
add_to_identity_map() click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 33
def add_to_identity_map
  unless @in_identity_map
    @@identity_map.add(@model.id, @model)

    @in_identity_map = true
  end
end
auto_generate_id() click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 24
def auto_generate_id
  true
end
changed(attribute_name = nil) click to toggle source

Called when the model changes

# File lib/volt/models/persistors/model_store.rb, line 50
def changed(attribute_name = nil)
  path = @model.path

  promise = Promise.new

  ensure_setup

  path_size = path.size
  if save_changes? && path_size > 0 && !@model.nil?
    if path_size > 3 && (parent = @model.parent)
      # If we have a collection, go up one more.
      parent = parent.parent unless parent.is_a?(Volt::Model)
      @model.attributes[:"#{path[-4].singularize}_id"] = parent.id
    end

    if !collection
      puts 'Attempting to save model directly on store.'
      fail 'Attempting to save model directly on store.'
    else
      if RUBY_PLATFORM == 'opal'
        @save_promises ||= []
        @save_promises << promise

        queue_client_save
      else
        errors = save_to_db!(self_attributes)
        if errors.size == 0
          promise.resolve(nil)
        else
          promise.reject(errors)
        end
      end
    end
  end

  promise
end
ensure_setup() click to toggle source

Called the first time a value is assigned into this model

# File lib/volt/models/persistors/model_store.rb, line 29
def ensure_setup
  add_to_identity_map
end
event_added(event, first, first_for_event) click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 127
def event_added(event, first, first_for_event)
  ensure_setup if first_for_event && event == :changed
end
loaded(initial_state = nil) click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 18
def loaded(initial_state = nil)
  initial_state = :loaded if model.path == []

  model.change_state_to(:loaded_state, initial_state)
end
queue_client_save() click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 88
def queue_client_save
  `
  if (!self.saveTimer) {
    self.saveTimer = setImmediate(self.$run_save.bind(self));
  }
  `
end
run_save() click to toggle source

Run save is called on the client side after a queued setImmediate. It does the saving on the front-end. Adding a setImmediate allows multiple changes to be batched together.

# File lib/volt/models/persistors/model_store.rb, line 99
def run_save
  # Clear the save timer
  `
  clearImmediate(self.saveTimer);
  delete self.saveTimer;
  `

  @model.change_state_to(:saved_state, :saving)

  StoreTasks.save(collection, @model.path, self_attributes).then do
    save_promises = @save_promises
    @save_promises = nil
    save_promises.each { |promise|  promise.resolve(nil) }

    @model.change_state_to(:saved_state, :saved)
  end.fail do |errors|
    save_promises = @save_promises
    @save_promises = nil

    # Rewrap in Volt::Errors
    errors = Volt::Errors.new(errors)
    save_promises.each { |promise| promise.reject(errors) }

    # Mark that we failed to save
    @model.change_state_to(:saved_state, :save_failed)
  end
end
save_changes?() click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 41
def save_changes?
  if RUBY_PLATFORM == 'opal'
    !(defined?($loading_models) && $loading_models) && @tasks
  else
    true
  end
end

Private Instance Methods

collection() click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 156
def collection
  @model.path[-2]
end
db() click to toggle source
# File lib/volt/models/persistors/model_store.rb, line 161
def db
  @@db ||= Volt::DataStore.fetch
end
save_to_db!(values) click to toggle source

Do the actual writing of data to the database, only runs on the backend.

# File lib/volt/models/persistors/model_store.rb, line 166
def save_to_db!(values)
  # Check to make sure the model has no validation errors.
  errors = @model.errors
  return errors if errors.present?

  # Try to create
  update_result = db.update(collection, values)

  # An error hash will be returned if the update doesn't work
  return update_result if update_result

  # If we are running in a task, or the console, push update
  if (volt_app = Volt.current_app)
    volt_app.live_query_pool.updated_collection(collection.to_s, Thread.current['in_channel'])
  end
  {}
end
self_attributes() click to toggle source

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

# File lib/volt/models/persistors/model_store.rb, line 152
def self_attributes
  @model.self_attributes
end