volt 0.9.4.pre3 → 0.9.4.pre5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/CODE_OF_CONDUCT.md +15 -0
- data/README.md +2 -0
- data/app/volt/models/user.rb +6 -4
- data/lib/volt/boot.rb +0 -2
- data/lib/volt/cli/bundle.rb +29 -0
- data/lib/volt/cli/console.rb +2 -2
- data/lib/volt/cli/generate.rb +2 -0
- data/lib/volt/cli/new_gem.rb +23 -0
- data/lib/volt/cli.rb +15 -2
- data/lib/volt/controllers/collection_helpers.rb +34 -3
- data/lib/volt/controllers/http_controller.rb +1 -1
- data/lib/volt/controllers/model_controller.rb +9 -33
- data/lib/volt/helpers/time.rb +43 -0
- data/lib/volt/models/array_model.rb +96 -90
- data/lib/volt/models/buffer.rb +42 -7
- data/lib/volt/models/helpers/array_model.rb +15 -0
- data/lib/volt/models/helpers/base.rb +113 -0
- data/lib/volt/models/helpers/change_helpers.rb +91 -0
- data/lib/volt/models/helpers/dirty.rb +93 -0
- data/lib/volt/models/helpers/listener_tracker.rb +19 -0
- data/lib/volt/models/helpers/model.rb +15 -0
- data/lib/volt/models/model.rb +17 -12
- data/lib/volt/models/permissions.rb +1 -1
- data/lib/volt/models/persistors/array_store.rb +4 -0
- data/lib/volt/models/persistors/base.rb +10 -0
- data/lib/volt/models/persistors/cookies.rb +2 -0
- data/lib/volt/models/persistors/local_store.rb +3 -0
- data/lib/volt/models/persistors/model_store.rb +7 -0
- data/lib/volt/models/persistors/params.rb +4 -1
- data/lib/volt/models/persistors/query/query_listener.rb +1 -1
- data/lib/volt/models/url.rb +12 -7
- data/lib/volt/models/validators/unique_validator.rb +1 -1
- data/lib/volt/page/bindings/base_binding.rb +2 -2
- data/lib/volt/page/bindings/event_binding.rb +2 -2
- data/lib/volt/page/bindings/view_binding/controller_handler.rb +20 -0
- data/lib/volt/page/bindings/view_binding/view_lookup_for_path.rb +6 -4
- data/lib/volt/page/bindings/view_binding.rb +7 -7
- data/lib/volt/page/path_string_renderer.rb +2 -4
- data/lib/volt/page/targets/base_section.rb +3 -3
- data/lib/volt/page/targets/dom_template.rb +2 -2
- data/lib/volt/page/tasks.rb +6 -6
- data/lib/volt/page/template_renderer.rb +1 -1
- data/lib/volt/page/url_tracker.rb +4 -4
- data/lib/volt/reactive/reactive_array.rb +31 -20
- data/lib/volt/server/component_templates.rb +5 -5
- data/lib/volt/server/forking_server.rb +2 -2
- data/lib/volt/server/message_bus/peer_to_peer/server_tracker.rb +3 -3
- data/lib/volt/server/message_bus/peer_to_peer.rb +7 -7
- data/lib/volt/server/rack/asset_files.rb +28 -8
- data/lib/volt/server/rack/component_paths.rb +4 -4
- data/lib/volt/server/rack/opal_files.rb +0 -1
- data/lib/volt/server/socket_connection_handler.rb +5 -2
- data/lib/volt/server.rb +0 -1
- data/lib/volt/spec/setup.rb +4 -5
- data/lib/volt/tasks/task.rb +2 -3
- data/lib/volt/utils/promise_extensions.rb +22 -6
- data/lib/volt/utils/time_patch.rb +12 -0
- data/lib/volt/utils/timers.rb +14 -2
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +44 -12
- data/lib/volt/volt/client_setup/browser.rb +113 -0
- data/lib/volt/volt/repos.rb +48 -0
- data/lib/volt/volt/server_setup/app.rb +1 -2
- data/lib/volt/volt/templates.rb +39 -0
- data/lib/volt/volt/users.rb +4 -4
- data/lib/volt.rb +1 -0
- data/spec/apps/file_loading/app/disable_auto/assets/css/test1.css.scss +0 -0
- data/spec/apps/file_loading/app/disable_auto/assets/css/test2.css.scss +0 -0
- data/spec/apps/file_loading/app/disable_auto/assets/js/test1.js +0 -0
- data/spec/apps/file_loading/app/disable_auto/assets/js/test2.js +0 -0
- data/spec/apps/file_loading/app/disable_auto/config/dependencies.rb +3 -0
- data/spec/apps/file_loading/app/main/assets/css/test3.css +0 -0
- data/spec/apps/file_loading/app/shared/config/dependencies.rb +1 -1
- data/spec/controllers/model_controller_spec.rb +7 -0
- data/spec/models/{model_helpers/model_helpers_spec.rb → helpers/base_spec.rb} +1 -1
- data/spec/models/helpers/model_spec.rb +26 -0
- data/spec/models/model_spec.rb +9 -0
- data/spec/models/persistors/params_spec.rb +1 -1
- data/spec/models/persistors/store_spec.rb +1 -0
- data/spec/page/bindings/content_binding_spec.rb +2 -4
- data/spec/page/bindings/each_binding_spec.rb +1 -4
- data/spec/page/bindings/if_binding_spec.rb +1 -4
- data/spec/page/bindings/template_binding/view_lookup_for_path_spec.rb +17 -27
- data/spec/page/path_string_renderer_spec.rb +15 -4
- data/spec/server/rack/asset_files_spec.rb +88 -8
- data/spec/tasks/user_tasks_spec.rb +1 -1
- data/spec/utils/promise_extensions_spec.rb +22 -0
- data/spec/volt/repos_spec.rb +11 -0
- data/templates/newgem/CODE_OF_CONDUCT.md.tt +13 -0
- data/templates/project/app/main/config/routes.rb +4 -1
- metadata +34 -10
- data/lib/volt/models/model_helpers/dirty.rb +0 -88
- data/lib/volt/models/model_helpers/listener_tracker.rb +0 -15
- data/lib/volt/models/model_helpers/model_change_helpers.rb +0 -87
- data/lib/volt/models/model_helpers/model_helpers.rb +0 -110
- data/lib/volt/models/state_helpers.rb +0 -11
- data/lib/volt/page/page.rb +0 -190
data/lib/volt/models/buffer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'volt/reactive/reactive_accessors'
|
2
|
+
|
1
3
|
module Volt
|
2
4
|
module Buffer
|
3
5
|
# Save saves the contents of a buffer to the save_to location. If the buffer is new, it will create a new
|
@@ -14,7 +16,8 @@ module Volt
|
|
14
16
|
result = nil
|
15
17
|
|
16
18
|
if errors.size == 0
|
17
|
-
save_to
|
19
|
+
# cache save_to in a local
|
20
|
+
save_to = self.save_to
|
18
21
|
if save_to
|
19
22
|
if save_to.is_a?(ArrayModel)
|
20
23
|
# Add to the collection
|
@@ -33,7 +36,7 @@ module Volt
|
|
33
36
|
new_model.change_state_to(:loaded_state, :loaded)
|
34
37
|
|
35
38
|
# Set the buffer's id to track the main model's id
|
36
|
-
|
39
|
+
self.save_to = new_model
|
37
40
|
end
|
38
41
|
|
39
42
|
# Copy attributes back from save_to model
|
@@ -76,11 +79,7 @@ module Volt
|
|
76
79
|
end
|
77
80
|
|
78
81
|
def buffer?
|
79
|
-
options[:buffer]
|
80
|
-
end
|
81
|
-
|
82
|
-
def save_to
|
83
|
-
options[:save_to]
|
82
|
+
options[:buffer] || false
|
84
83
|
end
|
85
84
|
|
86
85
|
# Returns a buffered version of the model
|
@@ -100,5 +99,41 @@ module Volt
|
|
100
99
|
|
101
100
|
model
|
102
101
|
end
|
102
|
+
|
103
|
+
def self.included(base)
|
104
|
+
base.include ReactiveAccessors
|
105
|
+
base.reactive_accessor :__save_to
|
106
|
+
end
|
107
|
+
|
108
|
+
def save_to
|
109
|
+
val = __save_to
|
110
|
+
|
111
|
+
unless val
|
112
|
+
# Lazy load the save_to
|
113
|
+
self.save_to = options[:save_to]
|
114
|
+
return __save_to
|
115
|
+
end
|
116
|
+
|
117
|
+
val
|
118
|
+
end
|
119
|
+
|
120
|
+
def save_to=(val)
|
121
|
+
self.__save_to = val
|
122
|
+
end
|
123
|
+
|
124
|
+
def saved_state
|
125
|
+
if buffer?
|
126
|
+
# cache save_to in local
|
127
|
+
lsave_to = self.save_to
|
128
|
+
|
129
|
+
lsave_to.try(:saved_state) || :not_saved
|
130
|
+
else
|
131
|
+
super
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def saved?
|
136
|
+
saved_state == :saved
|
137
|
+
end
|
103
138
|
end
|
104
139
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Volt
|
2
|
+
module Models
|
3
|
+
module Helpers
|
4
|
+
# A place for things shared between an ArrayModel and a Model
|
5
|
+
module Base
|
6
|
+
def deep_unwrap(value)
|
7
|
+
if value.is_a?(Model)
|
8
|
+
value.to_h
|
9
|
+
elsif value.is_a?(ArrayModel)
|
10
|
+
value.to_a
|
11
|
+
else
|
12
|
+
value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Pass to the persisotr
|
17
|
+
def event_added(event, first, first_for_event)
|
18
|
+
@persistor.event_added(event, first, first_for_event) if @persistor
|
19
|
+
end
|
20
|
+
|
21
|
+
# Pass to the persistor
|
22
|
+
def event_removed(event, last, last_for_event)
|
23
|
+
@persistor.event_removed(event, last, last_for_event) if @persistor
|
24
|
+
end
|
25
|
+
|
26
|
+
ID_CHARS = [('a'..'f'), ('0'..'9')].map(&:to_a).flatten
|
27
|
+
|
28
|
+
# Create a random unique id that can be used as the mongo id as well
|
29
|
+
def generate_id
|
30
|
+
id = []
|
31
|
+
24.times { id << ID_CHARS.sample }
|
32
|
+
|
33
|
+
id.join
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# Return the attributes that are only for this model and any hash sub models
|
38
|
+
# but not any sub-associations.
|
39
|
+
def self_attributes
|
40
|
+
# Don't store any sub-models, those will do their own saving.
|
41
|
+
attributes.reject { |k, v| v.is_a?(ArrayModel) }.map do |k,v|
|
42
|
+
if v.is_a?(Model)
|
43
|
+
v = v.self_attributes
|
44
|
+
end
|
45
|
+
|
46
|
+
[k,v]
|
47
|
+
end.to_h
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# Takes the persistor if there is one and
|
52
|
+
def setup_persistor(persistor)
|
53
|
+
# Use page as the default persistor
|
54
|
+
persistor ||= Persistors::Page
|
55
|
+
if persistor.respond_to?(:new)
|
56
|
+
@persistor = persistor.new(self)
|
57
|
+
else
|
58
|
+
# an already initialized persistor was passed in
|
59
|
+
@persistor = persistor
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def store
|
64
|
+
Volt.current_app.store
|
65
|
+
end
|
66
|
+
|
67
|
+
# returns the root model for the collection the model is currently on. So
|
68
|
+
# if the model is persisted somewhere on store, it will return ```store```
|
69
|
+
def root
|
70
|
+
persistor.try(:root_model)
|
71
|
+
end
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
# Gets the class for a model at the specified path.
|
75
|
+
def class_at_path(path)
|
76
|
+
if path
|
77
|
+
begin
|
78
|
+
# remove the _ and then singularize/pluralize
|
79
|
+
if path.last == :[]
|
80
|
+
index = -2
|
81
|
+
else
|
82
|
+
index = -1
|
83
|
+
end
|
84
|
+
|
85
|
+
# process_class_name is defined by Model/ArrayModel as
|
86
|
+
# singularize/pluralize
|
87
|
+
klass_name = process_class_name(klass_name = path[index]).camelize
|
88
|
+
|
89
|
+
# Lookup the class
|
90
|
+
klass = Object.const_get(klass_name)
|
91
|
+
|
92
|
+
# Use it if it is a model
|
93
|
+
klass = self unless klass < self
|
94
|
+
rescue NameError => e
|
95
|
+
# Ignore exception, just means the model isn't defined
|
96
|
+
klass = self
|
97
|
+
end
|
98
|
+
else
|
99
|
+
klass = self
|
100
|
+
end
|
101
|
+
|
102
|
+
klass
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.included(base)
|
107
|
+
base.send :extend, ClassMethods
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# ModelChangeHelpers handle validating and persisting the data in a model
|
2
|
+
# when it is changed. #run_changed will be called from the model.
|
3
|
+
module Volt
|
4
|
+
module Models
|
5
|
+
module Helpers
|
6
|
+
module ChangeHelpers
|
7
|
+
def self.included(base)
|
8
|
+
base.setup_action_helpers_in_class(:before_save, :before_validate)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Called when something in the model changes. Saves
|
12
|
+
# the model if there is a persistor, and changes the
|
13
|
+
# model to not be new.
|
14
|
+
#
|
15
|
+
# @return [Promise|nil] a promise for when the save is
|
16
|
+
# complete
|
17
|
+
def run_changed(attribute_name = nil)
|
18
|
+
# no_validate mode should only be used internally. no_validate mode is a
|
19
|
+
# performance optimization that prevents validation from running after each
|
20
|
+
# change when assigning multile attributes.
|
21
|
+
unless Volt.in_mode?(:no_validate)
|
22
|
+
# Run the validations for all fields
|
23
|
+
result = nil
|
24
|
+
return validate!.then do
|
25
|
+
# Buffers are allowed to be in an invalid state
|
26
|
+
unless buffer?
|
27
|
+
# First check that all local validations pass
|
28
|
+
if error_in_changed_attributes?
|
29
|
+
# Some errors are present, revert changes
|
30
|
+
revert_changes!
|
31
|
+
|
32
|
+
# After we revert, we need to validate again to get the error messages back
|
33
|
+
# TODO: Could probably cache the previous errors.
|
34
|
+
result = validate!.then do
|
35
|
+
# Reject the promise with the errors
|
36
|
+
Promise.new.reject(errs)
|
37
|
+
end
|
38
|
+
else
|
39
|
+
result = persist_changes(attribute_name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return result inside of the validate! promise
|
44
|
+
result.then { self }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Didn't run validations
|
49
|
+
self.then
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
private
|
54
|
+
# Should only be called from run_changed. Saves the changes back to the persistor
|
55
|
+
# and clears the tracked changes.
|
56
|
+
def persist_changes(attribute_name)
|
57
|
+
# No errors, tell the persistor to handle the change (usually save)
|
58
|
+
result = nil
|
59
|
+
|
60
|
+
# Don't save right now if we're in a nosave block
|
61
|
+
unless Volt.in_mode?(:no_save)
|
62
|
+
# Call the before_save callback
|
63
|
+
# skip validations when running before_save, this prevents n+1, and allows
|
64
|
+
# the before_save to put the model into an invalid state, which you want
|
65
|
+
# sometimes.
|
66
|
+
Volt::Model.no_validate do
|
67
|
+
run_callbacks(:before_save)
|
68
|
+
end
|
69
|
+
|
70
|
+
# the changed method on a persistor should return a promise that will
|
71
|
+
# be resolved when the save is complete, or fail with a hash of errors.
|
72
|
+
if @persistor
|
73
|
+
result = @persistor.changed(attribute_name)
|
74
|
+
else
|
75
|
+
result = Promise.new.resolve(nil)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Saved, no longer new
|
79
|
+
@new = false
|
80
|
+
|
81
|
+
# Clear the change tracking
|
82
|
+
clear_tracked_changes!
|
83
|
+
end
|
84
|
+
|
85
|
+
result
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Volt
|
2
|
+
module Models
|
3
|
+
module Helpers
|
4
|
+
# The dirty module provides helper methods for working with and tracking
|
5
|
+
# previous values on model attributes.
|
6
|
+
module Dirty
|
7
|
+
# Return the list of attributes that have changed since the last 'save' event.
|
8
|
+
def changed_attributes
|
9
|
+
@changed_attributes ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Return true if key has changed
|
13
|
+
def changed?(key = nil)
|
14
|
+
if key
|
15
|
+
# return the changed values for the keys
|
16
|
+
changed_attributes.key?(key)
|
17
|
+
else
|
18
|
+
changed_attributes.present?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Grab all previous versions of for key
|
23
|
+
def changes(key)
|
24
|
+
changed_attributes[key]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Grab the previous value for the key
|
28
|
+
def was(key)
|
29
|
+
val = changed_attributes[key]
|
30
|
+
|
31
|
+
# Doing val && val[0] doesn't work in opal
|
32
|
+
# https://github.com/opal/opal/issues/664
|
33
|
+
if val
|
34
|
+
val[0]
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Clear changed attributes
|
41
|
+
def clear_tracked_changes!
|
42
|
+
@changed_attributes = {}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Reverts the model attributes back to the pre-change values.
|
46
|
+
def revert_changes!
|
47
|
+
# Reassign the first value since we started tracking
|
48
|
+
if @changed_attributes
|
49
|
+
@changed_attributes.each_pair do |key, value|
|
50
|
+
@attributes[key] = value.first
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
clear_tracked_changes!
|
55
|
+
end
|
56
|
+
|
57
|
+
def attribute_will_change!(attribute_name, old_value)
|
58
|
+
# Don't track nil models
|
59
|
+
old_value = nil if old_value.nil?
|
60
|
+
|
61
|
+
(changed_attributes[attribute_name] ||= []) << old_value
|
62
|
+
end
|
63
|
+
|
64
|
+
# Handle change and was method calls
|
65
|
+
# Example: name_was or name_changes
|
66
|
+
def method_missing(method_name, *args, &block)
|
67
|
+
# Quick check to see if changes or was are being called, this check
|
68
|
+
# keeps us from needing to parse out the parts if we're not going
|
69
|
+
# to use them.
|
70
|
+
if method_name =~ /[_](changes|was)$/
|
71
|
+
# Break apart the method call
|
72
|
+
# TODO: no destructuring because of https://github.com/opal/opal/issues/663
|
73
|
+
*parts = method_name.to_s.split('_')
|
74
|
+
action = parts.pop
|
75
|
+
key = parts.join('_').to_sym
|
76
|
+
|
77
|
+
# Handle changes or was calls.
|
78
|
+
case action
|
79
|
+
when 'changes'
|
80
|
+
return changes(key)
|
81
|
+
when 'was'
|
82
|
+
return was(key)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Otherwise, run super
|
87
|
+
super
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Volt
|
2
|
+
module Models
|
3
|
+
module Helpers
|
4
|
+
# Included in model's so they can inform the ArrayModel when new listeners are added or removed.
|
5
|
+
module ListenerTracker
|
6
|
+
# Called when data from this model begins being watched
|
7
|
+
def listener_added
|
8
|
+
@listener_count ||= 0
|
9
|
+
@listener_count += 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def listener_removed
|
13
|
+
@listener_count ||= 0
|
14
|
+
@listener_count -= 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/volt/models/model.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
require 'volt/models/model_wrapper'
|
2
2
|
require 'volt/models/array_model'
|
3
|
-
require 'volt/models/
|
3
|
+
require 'volt/models/helpers/base'
|
4
4
|
require 'volt/models/model_hash_behaviour'
|
5
5
|
require 'volt/models/validations/validations'
|
6
6
|
require 'volt/utils/modes'
|
7
7
|
require 'volt/models/state_manager'
|
8
|
-
require 'volt/models/
|
8
|
+
require 'volt/models/helpers/model'
|
9
9
|
require 'volt/models/buffer'
|
10
10
|
require 'volt/models/field_helpers'
|
11
11
|
require 'volt/reactive/reactive_hash'
|
12
12
|
require 'volt/models/validators/user_validation'
|
13
|
-
require 'volt/models/
|
14
|
-
require 'volt/models/
|
15
|
-
require 'volt/models/
|
13
|
+
require 'volt/models/helpers/dirty'
|
14
|
+
require 'volt/models/helpers/listener_tracker'
|
15
|
+
require 'volt/models/helpers/change_helpers'
|
16
16
|
require 'volt/models/permissions'
|
17
17
|
require 'volt/models/associations'
|
18
18
|
require 'volt/reactive/class_eventable'
|
@@ -33,22 +33,23 @@ module Volt
|
|
33
33
|
class Model
|
34
34
|
include LifecycleCallbacks
|
35
35
|
include ModelWrapper
|
36
|
-
include
|
36
|
+
include Models::Helpers::Base
|
37
37
|
include ModelHashBehaviour
|
38
38
|
include StateManager
|
39
|
-
include
|
39
|
+
include Models::Helpers::Model
|
40
40
|
include Validations
|
41
|
+
# Buffer needs to go after StateHelpers so it can call saved_state as super
|
41
42
|
include Buffer
|
42
43
|
include FieldHelpers
|
43
44
|
include UserValidatorHelpers
|
44
|
-
include Dirty
|
45
|
+
include Models::Helpers::Dirty
|
45
46
|
include ClassEventable
|
46
47
|
include Modes
|
47
|
-
include ListenerTracker
|
48
|
+
include Models::Helpers::ListenerTracker
|
48
49
|
include Permissions
|
49
50
|
include Associations
|
50
51
|
include ReactiveAccessors
|
51
|
-
include
|
52
|
+
include Models::Helpers::ChangeHelpers
|
52
53
|
|
53
54
|
attr_reader :attributes, :parent, :path, :persistor, :options
|
54
55
|
|
@@ -305,7 +306,7 @@ module Volt
|
|
305
306
|
options = options.dup
|
306
307
|
options[:query] = []
|
307
308
|
|
308
|
-
ArrayModel.new(attributes, options)
|
309
|
+
Volt::ArrayModel.class_at_path(options[:path]).new(attributes, options)
|
309
310
|
end
|
310
311
|
|
311
312
|
def inspect
|
@@ -336,7 +337,7 @@ module Volt
|
|
336
337
|
result = parent.delete(self)
|
337
338
|
|
338
339
|
# Wrap result in a promise if it isn't one
|
339
|
-
return result
|
340
|
+
return result#.then
|
340
341
|
else
|
341
342
|
fail 'Model does not have a parent and cannot be deleted.'
|
342
343
|
end
|
@@ -416,5 +417,9 @@ module Volt
|
|
416
417
|
end
|
417
418
|
end
|
418
419
|
|
420
|
+
def self.process_class_name(name)
|
421
|
+
name.singularize
|
422
|
+
end
|
423
|
+
|
419
424
|
end
|
420
425
|
end
|
@@ -10,6 +10,10 @@ module Volt
|
|
10
10
|
@model.change_state_to(:loaded_state, initial_state || :loaded)
|
11
11
|
end
|
12
12
|
|
13
|
+
# Method that is called when data on the model changes.
|
14
|
+
# @returns [true|Promise] - should return a Promise or true. On async
|
15
|
+
# persistors, the promise from set and save! will wait on the
|
16
|
+
# Promise.
|
13
17
|
def changed(attribute_name)
|
14
18
|
end
|
15
19
|
|
@@ -36,6 +40,12 @@ module Volt
|
|
36
40
|
false
|
37
41
|
end
|
38
42
|
|
43
|
+
# return true if this persistor is asynchronus and needs to return
|
44
|
+
# Promises.
|
45
|
+
def async?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
39
49
|
# Find the root for this model
|
40
50
|
def root_model
|
41
51
|
node = @model
|
@@ -12,6 +12,7 @@ module Volt
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def loaded(initial_state = nil)
|
15
|
+
super
|
15
16
|
# When the main model is first loaded, we pull in the data from the
|
16
17
|
# store if it exists
|
17
18
|
if @model.path == []
|
@@ -31,6 +32,8 @@ module Volt
|
|
31
32
|
# Callled when an item is changed (or removed)
|
32
33
|
def changed(attribute_name)
|
33
34
|
root_model.persistor.save_all
|
35
|
+
|
36
|
+
true
|
34
37
|
end
|
35
38
|
|
36
39
|
# Called on the root
|
@@ -103,14 +103,21 @@ module Volt
|
|
103
103
|
delete self.saveTimer;
|
104
104
|
`
|
105
105
|
|
106
|
+
@model.change_state_to(:saved_state, :saving)
|
107
|
+
|
106
108
|
StoreTasks.save(collection, @model.path, self_attributes).then do
|
107
109
|
save_promises = @save_promises
|
108
110
|
@save_promises = nil
|
109
111
|
save_promises.each { |promise| promise.resolve(nil) }
|
112
|
+
|
113
|
+
@model.change_state_to(:saved_state, :saved)
|
110
114
|
end.fail do |errors|
|
111
115
|
save_promises = @save_promises
|
112
116
|
@save_promises = nil
|
113
117
|
save_promises.each { |promise| promise.reject(errors) }
|
118
|
+
|
119
|
+
# Mark that we failed to save
|
120
|
+
@model.change_state_to(:saved_state, :save_failed)
|
114
121
|
end
|
115
122
|
end
|
116
123
|
|
@@ -13,11 +13,14 @@ module Volt
|
|
13
13
|
window.paramsUpdateTimer = setTimeout(this.$run_update.bind(this), 0);
|
14
14
|
}
|
15
15
|
`
|
16
|
+
|
16
17
|
end
|
18
|
+
|
19
|
+
true
|
17
20
|
end
|
18
21
|
|
19
22
|
def run_update
|
20
|
-
|
23
|
+
Volt.current_app.url.update! if Volt.client?
|
21
24
|
end
|
22
25
|
end
|
23
26
|
end
|
@@ -49,7 +49,7 @@ module Volt
|
|
49
49
|
# If we get back that the user signature is wrong, log the user out.
|
50
50
|
if err.to_s.start_with?('user id or hash is incorrectly signed')
|
51
51
|
# Delete the invalid cookie
|
52
|
-
|
52
|
+
Volt.current_app.cookies.delete(:user_id)
|
53
53
|
end
|
54
54
|
|
55
55
|
fail err
|
data/lib/volt/models/url.rb
CHANGED
@@ -123,15 +123,20 @@ module Volt
|
|
123
123
|
frag = fragment
|
124
124
|
if frag.present?
|
125
125
|
# Scroll to anchor via http://www.w3.org/html/wg/drafts/html/master/browsers.html#scroll-to-fragid
|
126
|
+
# Sometimes the fragment will cause a jquery parsing error, so we
|
127
|
+
# catch any exceptions.
|
126
128
|
`
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
129
|
+
try {
|
130
|
+
var anchor = $('#' + frag);
|
131
|
+
if (anchor.length == 0) {
|
132
|
+
anchor = $('*[name="' + frag + '"]:first');
|
133
|
+
}
|
134
|
+
if (anchor && anchor.length > 0) {
|
135
|
+
console.log('scroll to: ', anchor.offset().top);
|
136
|
+
$(document.body).scrollTop(anchor.offset().top);
|
137
|
+
}
|
134
138
|
}
|
139
|
+
catch(e) {}
|
135
140
|
`
|
136
141
|
else
|
137
142
|
# Scroll to the top by default
|
@@ -12,7 +12,7 @@ module Volt
|
|
12
12
|
|
13
13
|
# Check if the value is taken
|
14
14
|
# TODO: need a way to handle scope for unique
|
15
|
-
return
|
15
|
+
return Volt.current_app.store.get(model.path[-2]).where(query).first.then do |item|
|
16
16
|
if item
|
17
17
|
message = (args.is_a?(Hash) && args[:message]) || 'is already taken'
|
18
18
|
|