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
@@ -3,7 +3,7 @@ require 'volt/utils/promise'
|
|
3
3
|
|
4
4
|
# A temp patch for promises until https://github.com/opal/opal/pull/725 is released.
|
5
5
|
class Promise
|
6
|
-
|
6
|
+
class UnrealizedPromiseException < RuntimeError ; end
|
7
7
|
# We made a choice not to support comparitors and << and >> on method_missing
|
8
8
|
# on Promises. This makes it easier to understand what promise proxying does
|
9
9
|
# and how it works. It also prevents confusing situations where you try to
|
@@ -83,12 +83,25 @@ class Promise
|
|
83
83
|
self.then {|v| v.to_json(*args, &block) }
|
84
84
|
end
|
85
85
|
|
86
|
+
# unwrap lets you return a value or raise an exceptoin on a realized promise.
|
87
|
+
# An exception will be raised if the promise is not realized yet.
|
88
|
+
def unwrap
|
89
|
+
if realized?
|
90
|
+
if resolved?
|
91
|
+
value
|
92
|
+
else
|
93
|
+
Object.send(:fail, error)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
raise UnrealizedPromiseException, "#unwrap called on a promise that has yet to be realized."
|
97
|
+
end
|
98
|
+
end
|
86
99
|
|
87
|
-
|
88
|
-
#
|
89
|
-
# the server) and
|
100
|
+
# Waits for the promise to be realized (resolved or rejected), then returns
|
101
|
+
# the resolved value or raises the rejection error. .sync only works on
|
102
|
+
# the server (not in opal), and will raise a warning if on the client.
|
90
103
|
def sync
|
91
|
-
raise ".sync can only be used on the
|
104
|
+
raise ".sync can only be used on the server" if Volt.client?
|
92
105
|
|
93
106
|
result = nil
|
94
107
|
error = nil
|
@@ -103,7 +116,10 @@ class Promise
|
|
103
116
|
err_str = "Exception in Promise at .sync: #{error.inspect}"
|
104
117
|
err_str += error.backtrace.join("\n") if error.respond_to?(:backtrace)
|
105
118
|
Volt.logger.error(err_str)
|
106
|
-
|
119
|
+
|
120
|
+
# The fail method in Promise is already defined, to re-raise the error,
|
121
|
+
# we send fail
|
122
|
+
Object.send(:fail, error)
|
107
123
|
else
|
108
124
|
return result
|
109
125
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Patchs a bug in the Time class, where two instances of time with the same
|
2
|
+
# value do not hash to the same hash as they do in MRI.
|
3
|
+
# https://github.com/opal/opal/issues/963
|
4
|
+
if RUBY_PLATFORM == 'opal'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
class Time
|
8
|
+
def hash
|
9
|
+
"Time:#{to_i}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/volt/utils/timers.rb
CHANGED
@@ -16,16 +16,28 @@ module Volt
|
|
16
16
|
|
17
17
|
# yields the passed in block after interval ms, or immediately if on the
|
18
18
|
# server.
|
19
|
+
#
|
20
|
+
# @return - the timeout id generated by setTimeout
|
19
21
|
def self.client_set_timeout(interval)
|
20
22
|
if Volt.in_browser?
|
21
|
-
|
23
|
+
timer_id = nil
|
24
|
+
`timer_id = setTimeout(function() {`
|
22
25
|
yield
|
23
|
-
`}, interval)
|
26
|
+
`}, interval);`
|
27
|
+
|
28
|
+
# return the timer_id
|
29
|
+
timer_id
|
24
30
|
else
|
25
31
|
yield
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
35
|
+
def self.clear_timeout(timeout_id)
|
36
|
+
if Volt.in_browser?
|
37
|
+
`clearTimeout(timeout_id);`
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
29
41
|
# On the server, we need to manually flush next tick timers.
|
30
42
|
# This is done automatically in the console after each enter.
|
31
43
|
def self.flush_next_tick_timers!
|
data/lib/volt/version.rb
CHANGED
data/lib/volt/volt/app.rb
CHANGED
@@ -23,22 +23,27 @@ require 'volt/models/url'
|
|
23
23
|
require 'volt/page/url_tracker'
|
24
24
|
require 'volt/benchmark/benchmark'
|
25
25
|
require 'volt/page/tasks'
|
26
|
-
require 'volt/
|
26
|
+
require 'volt/volt/repos'
|
27
|
+
require 'volt/volt/templates'
|
27
28
|
|
28
|
-
|
29
|
+
if RUBY_PLATFORM == 'opal'
|
30
|
+
require 'volt/volt/client_setup/browser'
|
31
|
+
else
|
29
32
|
require 'volt/volt/server_setup/app'
|
30
33
|
end
|
31
34
|
|
32
35
|
module Volt
|
33
36
|
class App
|
37
|
+
include Volt::Repos
|
38
|
+
|
34
39
|
if RUBY_PLATFORM != 'opal'
|
35
40
|
# Include server app setup
|
36
41
|
include Volt::ServerSetup::App
|
37
42
|
end
|
38
43
|
|
39
|
-
attr_reader :component_paths, :router, :
|
44
|
+
attr_reader :component_paths, :router, :live_query_pool,
|
40
45
|
:channel_live_queries, :app_path, :database, :message_bus,
|
41
|
-
:middleware
|
46
|
+
:middleware, :browser
|
42
47
|
attr_accessor :sprockets
|
43
48
|
|
44
49
|
def initialize(app_path=nil)
|
@@ -52,7 +57,9 @@ module Volt
|
|
52
57
|
# Setup root path
|
53
58
|
Volt.root = app_path
|
54
59
|
|
55
|
-
|
60
|
+
if RUBY_PLATFORM == 'opal'
|
61
|
+
setup_browser
|
62
|
+
end
|
56
63
|
|
57
64
|
if RUBY_PLATFORM != 'opal'
|
58
65
|
# We need to run the root config first so we can setup the Rack::Session
|
@@ -86,14 +93,39 @@ module Volt
|
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
96
|
+
def templates
|
97
|
+
@templates ||= Templates.new
|
98
|
+
end
|
89
99
|
|
90
|
-
#
|
91
|
-
def
|
92
|
-
|
93
|
-
@
|
100
|
+
# Called on the client side to add routes
|
101
|
+
def add_routes(&block)
|
102
|
+
@router ||= Routes.new
|
103
|
+
@router.define(&block)
|
104
|
+
url.router = @router
|
105
|
+
end
|
106
|
+
|
107
|
+
# Callled on the client to add store compiled templates
|
108
|
+
def add_template(*args)
|
109
|
+
templates.add_template(*args)
|
110
|
+
end
|
111
|
+
|
112
|
+
def tasks
|
113
|
+
@tasks ||= Tasks.new(self)
|
114
|
+
end
|
115
|
+
|
116
|
+
def channel
|
117
|
+
@channel ||= begin
|
118
|
+
if Volt.client?
|
119
|
+
Channel.new
|
120
|
+
else
|
121
|
+
ChannelStub.new
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
94
125
|
|
95
|
-
|
96
|
-
|
126
|
+
# Setup a Page instance.
|
127
|
+
def setup_browser
|
128
|
+
@browser = Browser.new(self)
|
97
129
|
end
|
98
130
|
end
|
99
131
|
end
|
@@ -102,6 +134,6 @@ if Volt.client?
|
|
102
134
|
$volt_app = Volt::App.new
|
103
135
|
|
104
136
|
`$(document).ready(function() {`
|
105
|
-
$volt_app.
|
137
|
+
$volt_app.browser.start
|
106
138
|
`});`
|
107
139
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'volt/utils/ejson'
|
2
|
+
|
3
|
+
module Volt
|
4
|
+
class Browser
|
5
|
+
attr_reader :events
|
6
|
+
|
7
|
+
def initialize(volt_app)
|
8
|
+
@volt_app = volt_app
|
9
|
+
# Run the code to setup the page
|
10
|
+
|
11
|
+
@url_tracker = UrlTracker.new(@volt_app)
|
12
|
+
|
13
|
+
@events = DocumentEvents.new
|
14
|
+
|
15
|
+
# Initialize tasks so we can get the reload message
|
16
|
+
@volt_app.tasks if Volt.env.development?
|
17
|
+
|
18
|
+
if RUBY_PLATFORM == 'opal'
|
19
|
+
if Volt.in_browser?
|
20
|
+
# Setup click handler for links
|
21
|
+
`
|
22
|
+
$(document).on('click', 'a', function(event) {
|
23
|
+
var browser = #{Volt.current_app.browser};
|
24
|
+
return browser.$link_clicked($(this).attr('href'), event);
|
25
|
+
});
|
26
|
+
`
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if Volt.in_browser?
|
31
|
+
@volt_app.channel.on('reconnected') do
|
32
|
+
@volt_app.page._reconnected = true
|
33
|
+
|
34
|
+
`setTimeout(function() {`
|
35
|
+
@volt_app._reconnected = false
|
36
|
+
`}, 2000);`
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def link_clicked(url = '', event = nil)
|
42
|
+
# Skip when href == ''
|
43
|
+
return false if url.blank?
|
44
|
+
|
45
|
+
# Normalize url
|
46
|
+
if @volt_app.url.parse(url)
|
47
|
+
if event
|
48
|
+
# Handled new url
|
49
|
+
`event.stopPropagation();`
|
50
|
+
end
|
51
|
+
|
52
|
+
# Clear the flash
|
53
|
+
@volt_app.flash.clear
|
54
|
+
|
55
|
+
# return false to stop the event propigation
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
|
59
|
+
# Not stopping, process link normally
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
# We provide a binding_name, so we can bind events on the document
|
64
|
+
def binding_name
|
65
|
+
'page'
|
66
|
+
end
|
67
|
+
|
68
|
+
def start
|
69
|
+
# Setup to render template
|
70
|
+
`$('body').html('<!-- $CONTENT --><!-- $/CONTENT -->');`
|
71
|
+
|
72
|
+
load_stored_page
|
73
|
+
|
74
|
+
# Do the initial url params parse
|
75
|
+
@url_tracker.url_updated(true)
|
76
|
+
|
77
|
+
main_controller = Main::MainController.new(@volt_app)
|
78
|
+
|
79
|
+
# Setup main page template
|
80
|
+
TemplateRenderer.new(@volt_app, DomTarget.new, main_controller, 'CONTENT', 'main/main/main/body')
|
81
|
+
|
82
|
+
# Setup title reactive template
|
83
|
+
@title_template = StringTemplateRenderer.new(@volt_app, main_controller, 'main/main/main/title')
|
84
|
+
|
85
|
+
# Watch for changes to the title template
|
86
|
+
proc do
|
87
|
+
title = @title_template.html.gsub(/\n/, ' ')
|
88
|
+
`document.title = title;`
|
89
|
+
end.watch!
|
90
|
+
end
|
91
|
+
|
92
|
+
# When the page is reloaded from the backend, we store the page collection,
|
93
|
+
# so we can reload the page in the exact same state. Speeds up development.
|
94
|
+
def load_stored_page
|
95
|
+
if Volt.client?
|
96
|
+
if `sessionStorage`
|
97
|
+
page_obj_str = nil
|
98
|
+
|
99
|
+
`page_obj_str = sessionStorage.getItem('___page');`
|
100
|
+
`if (page_obj_str) {`
|
101
|
+
`sessionStorage.removeItem('___page');`
|
102
|
+
|
103
|
+
EJSON.parse(page_obj_str).each_pair do |key, value|
|
104
|
+
page.send(:"_#{key}=", value)
|
105
|
+
end
|
106
|
+
`}`
|
107
|
+
end
|
108
|
+
end
|
109
|
+
rescue => e
|
110
|
+
Volt.logger.error("Unable to restore: #{e.inspect}")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# The Volt::Repos module provides access to each root collection (repo).
|
2
|
+
|
3
|
+
module Volt
|
4
|
+
module Repos
|
5
|
+
def url
|
6
|
+
@url ||= URL.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def params
|
10
|
+
@params ||= @url.params
|
11
|
+
end
|
12
|
+
|
13
|
+
def page
|
14
|
+
@page ||= PageRoot.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def store
|
18
|
+
@store ||= StoreRoot.new({}, persistor: Persistors::StoreFactory.new(tasks))
|
19
|
+
end
|
20
|
+
|
21
|
+
def flash
|
22
|
+
@flash ||= begin
|
23
|
+
check_for_client?('flash')
|
24
|
+
FlashRoot.new({}, persistor: Persistors::Flash)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def local_store
|
29
|
+
@local_store ||= begin
|
30
|
+
check_for_client?('local_store')
|
31
|
+
LocalStoreRoot.new({}, persistor: Persistors::LocalStore)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def cookies
|
36
|
+
@cookies ||= begin
|
37
|
+
check_for_client?('cookies')
|
38
|
+
CookiesRoot.new({}, persistor: Persistors::Cookies)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_for_client?(repo_name)
|
43
|
+
unless Volt.client?
|
44
|
+
fail "The #{repo_name} collection can only be accessed from the client side currently"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -13,7 +13,7 @@ module Volt
|
|
13
13
|
def setup_paths
|
14
14
|
# Load component paths
|
15
15
|
@component_paths = ComponentPaths.new(@app_path)
|
16
|
-
@component_paths.require_in_components(
|
16
|
+
@component_paths.require_in_components(self)
|
17
17
|
end
|
18
18
|
|
19
19
|
def load_app_code
|
@@ -25,7 +25,6 @@ module Volt
|
|
25
25
|
@router = Routes.new
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
28
|
def setup_preboot_middleware
|
30
29
|
@middleware = MiddlewareStack.new
|
31
30
|
DefaultMiddlewareStack.preboot_setup(self, @middleware)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# The Templates class holds all loaded templates.
|
2
|
+
module Volt
|
3
|
+
class Templates
|
4
|
+
# On the server, we can delay loading the views until they are actually requeted. This
|
5
|
+
# sets up an instance variable to call to load.
|
6
|
+
attr_writer :template_loader
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@templates = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
templates[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_template(name, template, bindings)
|
17
|
+
# First template gets priority. The backend will load templates in order so
|
18
|
+
# that local templates come in before gems (so they can be overridden).
|
19
|
+
#
|
20
|
+
# TODO: Currently this means we will send templates to the client that will
|
21
|
+
# not get used because they are being overridden. Need to detect that and
|
22
|
+
# not send them.
|
23
|
+
unless @templates[name]
|
24
|
+
@templates[name] = { 'html' => template, 'bindings' => bindings }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Load the templates on first use if a loader was specified
|
29
|
+
def templates
|
30
|
+
if @template_loader
|
31
|
+
# Load the templates
|
32
|
+
@template_loader.call
|
33
|
+
@template_loader = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
@templates
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/volt/volt/users.rb
CHANGED
@@ -85,7 +85,7 @@ module Volt
|
|
85
85
|
def current_user
|
86
86
|
user_id = current_user_id
|
87
87
|
if user_id
|
88
|
-
|
88
|
+
Volt.current_app.store._users.where(id: user_id).first
|
89
89
|
else
|
90
90
|
Promise.new.resolve(nil)
|
91
91
|
end
|
@@ -106,7 +106,7 @@ module Volt
|
|
106
106
|
def login(username, password)
|
107
107
|
UserTasks.login(login: username, password: password).then do |result|
|
108
108
|
# Assign the user_id cookie for the user
|
109
|
-
|
109
|
+
Volt.current_app.cookies._user_id = result
|
110
110
|
|
111
111
|
# Pass nil back
|
112
112
|
nil
|
@@ -114,14 +114,14 @@ module Volt
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def logout
|
117
|
-
|
117
|
+
Volt.current_app.cookies.delete(:user_id)
|
118
118
|
end
|
119
119
|
|
120
120
|
# Fetches the user_id+signature from the correct spot depending on client
|
121
121
|
# or server, does not verify it.
|
122
122
|
def user_id_signature
|
123
123
|
if Volt.client?
|
124
|
-
user_id_signature =
|
124
|
+
user_id_signature = Volt.current_app.cookies._user_id
|
125
125
|
else
|
126
126
|
# Check meta for the user id and validate it
|
127
127
|
meta_data = Thread.current['meta']
|
data/lib/volt.rb
CHANGED
@@ -6,6 +6,7 @@ require 'volt/utils/modes'
|
|
6
6
|
require 'volt/utils/volt_user_error'
|
7
7
|
require 'volt/utils/boolean_patch'
|
8
8
|
require 'volt/utils/set_patch'
|
9
|
+
require 'volt/utils/time_patch'
|
9
10
|
|
10
11
|
require 'volt/config'
|
11
12
|
require 'volt/data_stores/data_store' unless RUBY_PLATFORM == 'opal'
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1 +1 @@
|
|
1
|
-
component 'bootstrap'
|
1
|
+
component 'bootstrap'
|
@@ -27,5 +27,12 @@ if RUBY_PLATFORM != 'opal'
|
|
27
27
|
promise.resolve(Volt::Model.new)
|
28
28
|
expect(controller.loaded?).to eq(true)
|
29
29
|
end
|
30
|
+
|
31
|
+
it 'should provide a u method that disables reactive updates' do
|
32
|
+
expect(Volt::Computation).to receive(:run_without_tracking)
|
33
|
+
|
34
|
+
controller = Volt::ModelController.new(volt_app)
|
35
|
+
controller.u { 5 }
|
36
|
+
end
|
30
37
|
end
|
31
38
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Volt::Models::Helpers::Model do
|
4
|
+
describe "saved_state" do
|
5
|
+
it 'should start not_saved for a buffer' do
|
6
|
+
item = the_page._items.buffer
|
7
|
+
expect(item.saved_state).to eq(:not_saved)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should move to saved when the buffer is saved' do
|
11
|
+
item = the_page._items.buffer
|
12
|
+
item.save!.then do
|
13
|
+
expect(item.saved_state).to eq(:saved)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should start as saved after create' do
|
18
|
+
item = the_page._items.create({name: 'One'})
|
19
|
+
|
20
|
+
expect(item.saved_state).to eq(:saved)
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: because server side model loading is done synchronusly, we can't
|
24
|
+
# test the
|
25
|
+
end
|
26
|
+
end
|
data/spec/models/model_spec.rb
CHANGED
@@ -6,6 +6,9 @@ end
|
|
6
6
|
class Item < Volt::Model
|
7
7
|
end
|
8
8
|
|
9
|
+
class Items < Volt::ArrayModel
|
10
|
+
end
|
11
|
+
|
9
12
|
class TestAssignsMethod < Volt::Model
|
10
13
|
def name=(val)
|
11
14
|
self._name = val
|
@@ -603,4 +606,10 @@ describe Volt::Model do
|
|
603
606
|
expect(array_model.to_json).to eq(array_model.to_a.to_json)
|
604
607
|
end
|
605
608
|
end
|
609
|
+
|
610
|
+
it 'creates sub-arrays with correct classes' do
|
611
|
+
model = Volt::Model.new
|
612
|
+
model._items << {}
|
613
|
+
expect(model._items).to be_instance_of Items
|
614
|
+
end
|
606
615
|
end
|
@@ -8,7 +8,7 @@ describe Volt::Persistors::Params do
|
|
8
8
|
#
|
9
9
|
# expect(a._test!._cool!.persistor.class).to eq(Volt::Persistors::Params)
|
10
10
|
|
11
|
-
a._items
|
11
|
+
a._items << { name: 'Test' }
|
12
12
|
#
|
13
13
|
# expect(a._items.persistor.class).to eq(Volt::Persistors::Params)
|
14
14
|
# expect(a._items[0].persistor.class).to eq(Volt::Persistors::Params)
|
@@ -20,6 +20,7 @@ describe Volt::Persistors::Store do
|
|
20
20
|
persistor_instance = double('volt/persistor instance')
|
21
21
|
expect(persistor_instance).to receive(:loaded)
|
22
22
|
expect(persistor).to receive(:new).and_return(persistor_instance)
|
23
|
+
expect(persistor_instance).to receive(:async?).and_return(false)
|
23
24
|
|
24
25
|
@model = Volt::ArrayModel.new([1, 2, 3], persistor: persistor)
|
25
26
|
|
@@ -24,11 +24,9 @@ describe Volt::ContentBinding do
|
|
24
24
|
}
|
25
25
|
}
|
26
26
|
|
27
|
-
page = double('volt/page')
|
28
|
-
expect(page).to receive(:templates).and_return(templates)
|
29
|
-
|
30
27
|
volt_app = double('volt/app')
|
31
|
-
expect(volt_app).to receive(:
|
28
|
+
expect(volt_app).to receive(:templates).and_return(templates)
|
29
|
+
|
32
30
|
|
33
31
|
|
34
32
|
dom = Volt::AttributeTarget.new(0)
|
@@ -42,11 +42,8 @@ describe Volt::EachBinding do
|
|
42
42
|
}
|
43
43
|
}
|
44
44
|
|
45
|
-
page = double('volt/page')
|
46
|
-
expect(page).to receive(:templates).and_return(templates).at_least(1).times
|
47
|
-
|
48
45
|
volt_app = double('volt/app')
|
49
|
-
expect(volt_app).to receive(:
|
46
|
+
expect(volt_app).to receive(:templates).and_return(templates).at_least(1).times
|
50
47
|
|
51
48
|
Volt::TemplateRenderer.new(volt_app, dom, context, 'main', 'main/main')
|
52
49
|
|
@@ -40,11 +40,8 @@ describe Volt::IfBinding do
|
|
40
40
|
}
|
41
41
|
}
|
42
42
|
|
43
|
-
page = double('volt/page')
|
44
|
-
expect(page).to receive(:templates).and_return(templates).at_least(1).times
|
45
|
-
|
46
43
|
volt_app = double('volt/app')
|
47
|
-
expect(volt_app).to receive(:
|
44
|
+
expect(volt_app).to receive(:templates).and_return(templates).at_least(1).times
|
48
45
|
|
49
46
|
Volt::TemplateRenderer.new(volt_app, dom, context, 'main', 'main/main')
|
50
47
|
|