volt 0.8.27.beta2 → 0.8.27.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +3 -0
- data/CHANGELOG.md +7 -2
- data/CONTRIBUTING.md +133 -0
- data/Gemfile +0 -1
- data/Rakefile +11 -3
- data/Readme.md +4 -4
- data/VERSION +1 -1
- data/app/volt/models/user.rb +6 -3
- data/lib/volt/cli/console.rb +21 -12
- data/lib/volt/cli/runner.rb +1 -1
- data/lib/volt/cli.rb +5 -4
- data/lib/volt/config.rb +9 -11
- data/lib/volt/controllers/model_controller.rb +16 -0
- data/lib/volt/data_stores/data_store.rb +1 -1
- data/lib/volt/extra_core/array.rb +1 -6
- data/lib/volt/extra_core/blank.rb +1 -3
- data/lib/volt/extra_core/class.rb +1 -1
- data/lib/volt/extra_core/extra_core.rb +0 -1
- data/lib/volt/extra_core/logger.rb +78 -1
- data/lib/volt/extra_core/object.rb +4 -4
- data/lib/volt/models/array_model.rb +2 -3
- data/lib/volt/models/buffer.rb +1 -2
- data/lib/volt/models/field_helpers.rb +4 -5
- data/lib/volt/models/model.rb +27 -1
- data/lib/volt/models/model_hash_behaviour.rb +3 -4
- data/lib/volt/models/persistors/array_store.rb +6 -7
- data/lib/volt/models/persistors/cookies.rb +2 -2
- data/lib/volt/models/persistors/model_store.rb +5 -6
- data/lib/volt/models/validations.rb +5 -7
- data/lib/volt/models/validators/email_validator.rb +8 -29
- data/lib/volt/models/validators/format_validator.rb +116 -0
- data/lib/volt/models/validators/numericality_validator.rb +2 -2
- data/lib/volt/models/validators/phone_number_validator.rb +8 -29
- data/lib/volt/models/validators/unique_validator.rb +2 -2
- data/lib/volt/page/bindings/content_binding.rb +1 -1
- data/lib/volt/page/bindings/each_binding.rb +1 -1
- data/lib/volt/page/bindings/template_binding/view_lookup_for_path.rb +92 -0
- data/lib/volt/page/bindings/template_binding.rb +10 -85
- data/lib/volt/page/channel.rb +0 -1
- data/lib/volt/page/page.rb +5 -7
- data/lib/volt/page/sub_context.rb +1 -1
- data/lib/volt/page/targets/base_section.rb +2 -2
- data/lib/volt/page/targets/helpers/comment_searchers.rb +2 -2
- data/lib/volt/reactive/reactive_accessors.rb +1 -1
- data/lib/volt/reactive/reactive_array.rb +6 -6
- data/lib/volt/router/routes.rb +4 -4
- data/lib/volt/server/rack/asset_files.rb +1 -2
- data/lib/volt/server/rack/component_code.rb +0 -2
- data/lib/volt/server/rack/component_paths.rb +2 -2
- data/lib/volt/server/rack/quiet_common_logger.rb +2 -2
- data/lib/volt/spec/capybara.rb +1 -1
- data/lib/volt/spec/sauce_labs.rb +6 -6
- data/lib/volt/spec/setup.rb +8 -7
- data/lib/volt/tasks/dispatcher.rb +12 -10
- data/lib/volt/tasks/task_handler.rb +1 -1
- data/lib/volt/utils/generic_pool.rb +2 -2
- data/lib/volt/volt/users.rb +7 -9
- data/lib/volt.rb +2 -4
- data/spec/apps/file_loading/app/missing_deps/config/dependencies.rb +1 -1
- data/spec/apps/kitchen_sink/Gemfile +2 -2
- data/spec/apps/kitchen_sink/app/main/config/dependencies.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +0 -1
- data/spec/apps/kitchen_sink/app/main/models/user.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -1
- data/spec/apps/kitchen_sink/config/app.rb +1 -1
- data/spec/extra_core/array_spec.rb +4 -2
- data/spec/extra_core/blank_spec.rb +11 -0
- data/spec/extra_core/class_spec.rb +2 -2
- data/spec/extra_core/logger_spec.rb +50 -0
- data/spec/extra_core/string_transformations_spec.rb +0 -1
- data/spec/integration/cookies_spec.rb +1 -2
- data/spec/integration/flash_spec.rb +2 -3
- data/spec/integration/list_spec.rb +1 -1
- data/spec/integration/templates_spec.rb +0 -1
- data/spec/integration/url_spec.rb +1 -2
- data/spec/integration/user_spec.rb +3 -3
- data/spec/models/field_helpers_spec.rb +2 -2
- data/spec/models/model_spec.rb +21 -2
- data/spec/models/user_spec.rb +69 -0
- data/spec/models/validations_spec.rb +69 -78
- data/spec/models/validators/email_validator_spec.rb +3 -3
- data/spec/models/validators/format_validator_spec.rb +144 -0
- data/spec/models/validators/length_validator_spec.rb +82 -0
- data/spec/models/validators/phone_number_validator_spec.rb +3 -3
- data/spec/page/bindings/template_binding/view_lookup_for_path_spec.rb +149 -0
- data/spec/page/bindings/template_binding_spec.rb +0 -151
- data/spec/reactive/computation_spec.rb +46 -0
- data/spec/reactive/dependency_spec.rb +0 -1
- data/spec/reactive/reactive_array_spec.rb +0 -1
- data/spec/router/routes_spec.rb +0 -4
- data/spec/server/html_parser/view_parser_spec.rb +0 -4
- data/spec/server/rack/asset_files_spec.rb +1 -1
- data/spec/server/rack/quite_common_logger_spec.rb +55 -0
- data/spec/spec_helper.rb +2 -5
- data/spec/tasks/dispatcher_spec.rb +16 -5
- data/spec/tasks/live_query_spec.rb +0 -1
- data/spec/tasks/query_tasks.rb +0 -1
- data/spec/tasks/query_tracker_spec.rb +0 -3
- data/spec/templates/targets/binding_document/component_node_spec.rb +0 -1
- data/spec/utils/generic_counting_pool_spec.rb +0 -1
- data/spec/utils/generic_pool_spec.rb +0 -1
- data/templates/component/assets/images/.empty_directory +0 -0
- data/templates/project/README.md.tt +3 -2
- data/templates/project/app/main/assets/images/.empty_directory +0 -0
- data/templates/project/config/base/index.html +6 -7
- data/volt.gemspec +3 -5
- metadata +27 -9
- data/lib/volt/extra_core/numeric.rb +0 -9
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
require 'volt/page/bindings/base_binding'
|
|
2
2
|
require 'volt/page/template_renderer'
|
|
3
3
|
require 'volt/page/bindings/template_binding/grouped_controllers'
|
|
4
|
+
require 'volt/page/bindings/template_binding/view_lookup_for_path'
|
|
4
5
|
|
|
5
6
|
module Volt
|
|
6
7
|
class TemplateBinding < BaseBinding
|
|
7
8
|
def initialize(page, target, context, binding_name, binding_in_path, getter)
|
|
8
9
|
super(page, target, context, binding_name)
|
|
9
10
|
|
|
10
|
-
#
|
|
11
|
-
|
|
11
|
+
# Setup the view lookup helper
|
|
12
|
+
@view_lookup = Volt::ViewLookupForPath.new(page, binding_in_path)
|
|
12
13
|
|
|
13
14
|
@current_template = nil
|
|
14
15
|
|
|
@@ -22,86 +23,6 @@ module Volt
|
|
|
22
23
|
end.watch!
|
|
23
24
|
end
|
|
24
25
|
|
|
25
|
-
def setup_path(binding_in_path)
|
|
26
|
-
path_parts = binding_in_path.split('/')
|
|
27
|
-
@collection_name = path_parts[0]
|
|
28
|
-
@controller_name = path_parts[1]
|
|
29
|
-
@page_name = path_parts[2]
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Returns true if there is a template at the path
|
|
33
|
-
def check_for_template?(path)
|
|
34
|
-
@page.templates[path]
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Takes in a lookup path and returns the full path for the matching
|
|
38
|
-
# template. Also returns the controller and action name if applicable.
|
|
39
|
-
#
|
|
40
|
-
# Looking up a path is fairly simple. There are 4 parts needed to find
|
|
41
|
-
# the html to be rendered. File paths look like this:
|
|
42
|
-
# app/{component}/views/{controller_name}/{view}.html
|
|
43
|
-
# Within the html file may be one or more sections.
|
|
44
|
-
# 1. component (app/{comp})
|
|
45
|
-
# 2. controller
|
|
46
|
-
# 3. view
|
|
47
|
-
# 4. sections
|
|
48
|
-
#
|
|
49
|
-
# When searching for a file, the lookup starts at the section, and moves up.
|
|
50
|
-
# when moving up, default values are provided for the section, then view/section, etc..
|
|
51
|
-
# until a file is either found or the component level is reached.
|
|
52
|
-
#
|
|
53
|
-
# The defaults are as follows:
|
|
54
|
-
# 1. component - main
|
|
55
|
-
# 2. controller - main
|
|
56
|
-
# 3. view - index
|
|
57
|
-
# 4. section - body
|
|
58
|
-
def path_for_template(lookup_path, force_section = nil)
|
|
59
|
-
parts = lookup_path.split('/')
|
|
60
|
-
parts_size = parts.size
|
|
61
|
-
|
|
62
|
-
default_parts = %w(main main index body)
|
|
63
|
-
|
|
64
|
-
# When forcing a sub template, we can default the sub template section
|
|
65
|
-
default_parts[-1] = force_section if force_section
|
|
66
|
-
|
|
67
|
-
(5 - parts_size).times do |path_position|
|
|
68
|
-
# If they passed in a force_section, we can skip the first
|
|
69
|
-
next if force_section && path_position == 0
|
|
70
|
-
|
|
71
|
-
full_path = [@collection_name, @controller_name, @page_name, nil]
|
|
72
|
-
|
|
73
|
-
start_at = full_path.size - parts_size - path_position
|
|
74
|
-
|
|
75
|
-
full_path.size.times do |index|
|
|
76
|
-
if index >= start_at
|
|
77
|
-
if (part = parts[index - start_at])
|
|
78
|
-
full_path[index] = part
|
|
79
|
-
else
|
|
80
|
-
full_path[index] = default_parts[index]
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
path = full_path.join('/')
|
|
86
|
-
if check_for_template?(path)
|
|
87
|
-
controller = nil
|
|
88
|
-
|
|
89
|
-
if path_position >= 1
|
|
90
|
-
init_method = full_path[2]
|
|
91
|
-
else
|
|
92
|
-
init_method = full_path[3]
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# Lookup the controller
|
|
96
|
-
controller = [full_path[0], full_path[1] + '_controller', init_method]
|
|
97
|
-
|
|
98
|
-
return path, controller
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
[nil, nil]
|
|
103
|
-
end
|
|
104
|
-
|
|
105
26
|
def update(path, section_or_arguments = nil, options = {})
|
|
106
27
|
Computation.run_without_tracking do
|
|
107
28
|
# Remove existing template and call _removed
|
|
@@ -136,7 +57,7 @@ module Volt
|
|
|
136
57
|
clear_grouped_controller
|
|
137
58
|
end
|
|
138
59
|
|
|
139
|
-
full_path, controller_path = path_for_template(path, section)
|
|
60
|
+
full_path, controller_path = @view_lookup.path_for_template(path, section)
|
|
140
61
|
render_template(full_path, controller_path)
|
|
141
62
|
|
|
142
63
|
queue_clear_grouped_controller
|
|
@@ -208,7 +129,9 @@ module Volt
|
|
|
208
129
|
if @controller
|
|
209
130
|
# Set the current section on the controller if it wants so it can manipulate
|
|
210
131
|
# the dom if needed
|
|
211
|
-
|
|
132
|
+
# Only assign sections for action's, so we don't get AttributeSections bound
|
|
133
|
+
# also.
|
|
134
|
+
if @action && @controller.respond_to?(:section=)
|
|
212
135
|
@controller.section = @current_template.dom_section
|
|
213
136
|
end
|
|
214
137
|
|
|
@@ -217,6 +140,8 @@ module Volt
|
|
|
217
140
|
end
|
|
218
141
|
|
|
219
142
|
def remove
|
|
143
|
+
controller_send(:"before_#{@action}_remove") if @controller && @action
|
|
144
|
+
|
|
220
145
|
clear_grouped_controller
|
|
221
146
|
|
|
222
147
|
if @current_template
|
|
@@ -228,7 +153,7 @@ module Volt
|
|
|
228
153
|
super
|
|
229
154
|
|
|
230
155
|
if @controller
|
|
231
|
-
controller_send(:"#{@action}
|
|
156
|
+
controller_send(:"after_#{@action}_remove") if @action
|
|
232
157
|
|
|
233
158
|
@controller = nil
|
|
234
159
|
end
|
data/lib/volt/page/channel.rb
CHANGED
data/lib/volt/page/page.rb
CHANGED
|
@@ -140,13 +140,11 @@ module Volt
|
|
|
140
140
|
attr_reader :events
|
|
141
141
|
|
|
142
142
|
def add_model(model_name)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
raise unless model_name == :User
|
|
149
|
-
end
|
|
143
|
+
model_name = model_name.camelize.to_sym
|
|
144
|
+
@model_classes[model_name] = Object.const_get(model_name)
|
|
145
|
+
rescue NameError => e
|
|
146
|
+
# Handle if the model is user (Volt's provided user model is scoped under Volt::)
|
|
147
|
+
raise unless model_name == :User
|
|
150
148
|
end
|
|
151
149
|
|
|
152
150
|
def add_template(name, template, bindings)
|
|
@@ -8,7 +8,7 @@ module Volt
|
|
|
8
8
|
class SubContext
|
|
9
9
|
attr_reader :locals
|
|
10
10
|
|
|
11
|
-
def initialize(locals=nil, context = nil, return_nils = false)
|
|
11
|
+
def initialize(locals = nil, context = nil, return_nils = false)
|
|
12
12
|
@locals = locals.stringify_keys if locals
|
|
13
13
|
@context = context
|
|
14
14
|
@return_nils = return_nils
|
|
@@ -21,7 +21,7 @@ module Volt
|
|
|
21
21
|
if self.is_a?(DomSection)
|
|
22
22
|
dom_template = (@@template_cache[template_name] ||= DomTemplate.new(page, template_name))
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
set_template(dom_template)
|
|
25
25
|
else
|
|
26
26
|
template = page.templates[template_name]
|
|
27
27
|
|
|
@@ -33,7 +33,7 @@ module Volt
|
|
|
33
33
|
bindings = {}
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
set_content_and_rezero_bindings(html, bindings)
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -8,14 +8,14 @@ module Volt
|
|
|
8
8
|
|
|
9
9
|
def find_by_comment(text, in_node = `document`)
|
|
10
10
|
if NO_XPATH
|
|
11
|
-
|
|
11
|
+
find_by_comment_without_xml(text, in_node)
|
|
12
12
|
else
|
|
13
13
|
node = nil
|
|
14
14
|
|
|
15
15
|
`
|
|
16
16
|
node = document.evaluate("//comment()[. = ' " + text + " ']", in_node, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null).iterateNext();
|
|
17
17
|
`
|
|
18
|
-
|
|
18
|
+
node
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -25,7 +25,7 @@ module Volt
|
|
|
25
25
|
def reactive_writer(*names)
|
|
26
26
|
names.each do |name|
|
|
27
27
|
var_name = :"@#{name}"
|
|
28
|
-
define_method(
|
|
28
|
+
define_method("#{name}=") do |new_value|
|
|
29
29
|
instance_variable_set(var_name, new_value)
|
|
30
30
|
|
|
31
31
|
self.class.__reactive_dependency_get(name).changed!
|
|
@@ -39,9 +39,9 @@ module Volt
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
count
|
|
43
43
|
else
|
|
44
|
-
|
|
44
|
+
size
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -67,9 +67,9 @@ module Volt
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
false
|
|
71
71
|
else
|
|
72
|
-
|
|
72
|
+
@array.any?
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -83,9 +83,9 @@ module Volt
|
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
true
|
|
87
87
|
else
|
|
88
|
-
|
|
88
|
+
@array.all?
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
data/lib/volt/router/routes.rb
CHANGED
|
@@ -119,16 +119,16 @@ module Volt
|
|
|
119
119
|
if node[part]
|
|
120
120
|
# We found a match, replace the bindings and return
|
|
121
121
|
# TODO: Handvle nested
|
|
122
|
-
|
|
122
|
+
setup_bindings_in_params(original_parts, node[part])
|
|
123
123
|
else
|
|
124
|
-
|
|
124
|
+
false
|
|
125
125
|
end
|
|
126
126
|
elsif (new_node = node[part])
|
|
127
127
|
# Direct match for section, continue
|
|
128
|
-
|
|
128
|
+
match_path(original_parts, parts, new_node)
|
|
129
129
|
elsif (new_node = node['*'])
|
|
130
130
|
# Match on binding section
|
|
131
|
-
|
|
131
|
+
match_path(original_parts, parts, new_node)
|
|
132
132
|
end
|
|
133
133
|
end
|
|
134
134
|
|
|
@@ -35,11 +35,10 @@ module Volt
|
|
|
35
35
|
component_path = @component_paths.component_paths(name)
|
|
36
36
|
|
|
37
37
|
unless component_path
|
|
38
|
-
|
|
38
|
+
fail "Unable to find component '#{name}', make sure the gem is included in your Gemfile"
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
component_path.each do |path|
|
|
42
|
-
|
|
43
42
|
# Load the dependencies
|
|
44
43
|
load_dependencies(path)
|
|
45
44
|
|
|
@@ -84,8 +84,8 @@ module Volt
|
|
|
84
84
|
def load_views_and_routes
|
|
85
85
|
component_names = []
|
|
86
86
|
app_folders do |app_folder|
|
|
87
|
-
Dir["#{app_folder}/*"].map {|cp| cp[/[^\/]+$/] }.each do |component_name|
|
|
88
|
-
component_names << component_name
|
|
87
|
+
Dir["#{app_folder}/*"].map { |cp| cp[/[^\/]+$/] }.each do |component_name|
|
|
88
|
+
component_names << component_name if File.directory?(component_name)
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'rack'
|
|
1
2
|
class QuietCommonLogger < Rack::CommonLogger
|
|
2
3
|
include Rack
|
|
3
4
|
|
|
@@ -16,7 +17,6 @@ class QuietCommonLogger < Rack::CommonLogger
|
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
body = BodyProxy.new(body) do
|
|
19
|
-
|
|
20
20
|
# Don't log on ignored extensions
|
|
21
21
|
unless @@ignore_extensions.include?(ext)
|
|
22
22
|
log(env, status, header, began_at)
|
|
@@ -31,4 +31,4 @@ class QuietCommonLogger < Rack::CommonLogger
|
|
|
31
31
|
|
|
32
32
|
[status, header, body]
|
|
33
33
|
end
|
|
34
|
-
end
|
|
34
|
+
end
|
data/lib/volt/spec/capybara.rb
CHANGED
data/lib/volt/spec/sauce_labs.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module Volt
|
|
2
2
|
class << self
|
|
3
3
|
def setup_sauce_labs
|
|
4
|
-
require
|
|
5
|
-
require
|
|
4
|
+
require 'sauce'
|
|
5
|
+
require 'sauce/capybara'
|
|
6
6
|
|
|
7
7
|
Sauce.config do |c|
|
|
8
8
|
if ENV['OS']
|
|
@@ -15,9 +15,9 @@ module Volt
|
|
|
15
15
|
c[:browsers] = [
|
|
16
16
|
# ["Windows 7", "Chrome", "30"],
|
|
17
17
|
# ["Windows 8", "Firefox", "28"],
|
|
18
|
-
[
|
|
19
|
-
[
|
|
20
|
-
[
|
|
18
|
+
['Windows 8.1', 'Internet Explorer', '11'],
|
|
19
|
+
['Windows 8.0', 'Internet Explorer', '10'],
|
|
20
|
+
['Windows 7.0', 'Internet Explorer', '9'],
|
|
21
21
|
# ["OSX 10.9", "iPhone", "8.1"],
|
|
22
22
|
# ["OSX 10.8", "Safari", "6"],
|
|
23
23
|
# ["Linux", "Chrome", "26"]
|
|
@@ -30,4 +30,4 @@ module Volt
|
|
|
30
30
|
Capybara.javascript_driver = :sauce
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
|
-
end
|
|
33
|
+
end
|
data/lib/volt/spec/setup.rb
CHANGED
|
@@ -2,16 +2,17 @@ module Volt
|
|
|
2
2
|
class << self
|
|
3
3
|
def spec_setup(app_path = '.')
|
|
4
4
|
require 'volt'
|
|
5
|
-
unless RUBY_PLATFORM == 'opal'
|
|
6
|
-
require 'volt/spec/capybara'
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
ENV['SERVER'] = 'true'
|
|
7
|
+
ENV['VOLT_ENV'] = 'test'
|
|
8
|
+
|
|
9
|
+
require 'volt/boot'
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# Require in app
|
|
12
|
+
Volt.boot(app_path)
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
unless RUBY_PLATFORM == 'opal'
|
|
15
|
+
require 'volt/spec/capybara'
|
|
15
16
|
|
|
16
17
|
setup_capybara(app_path)
|
|
17
18
|
end
|
|
@@ -2,7 +2,6 @@ module Volt
|
|
|
2
2
|
# The task dispatcher is responsible for taking incoming messages
|
|
3
3
|
# from the socket channel and dispatching them to the proper handler.
|
|
4
4
|
class Dispatcher
|
|
5
|
-
|
|
6
5
|
# Dispatch takes an incoming Task from the client and runs it on the
|
|
7
6
|
# server, returning the result to the client.
|
|
8
7
|
# Tasks returning a promise will wait to return.
|
|
@@ -15,6 +14,8 @@ module Volt
|
|
|
15
14
|
|
|
16
15
|
promise = Promise.new
|
|
17
16
|
|
|
17
|
+
start_time = Time.now.to_f
|
|
18
|
+
|
|
18
19
|
# Check that we are calling on a TaskHandler class and a method provide at
|
|
19
20
|
# TaskHandler or above in the ancestor chain.
|
|
20
21
|
if safe_method?(klass, method_name)
|
|
@@ -35,15 +36,15 @@ module Volt
|
|
|
35
36
|
# Unsafe method
|
|
36
37
|
promise.reject(RuntimeError.new("unsafe method: #{method_name}"))
|
|
37
38
|
end
|
|
38
|
-
|
|
39
|
-
if callback_id
|
|
40
39
|
# Run the promise and pass the return value/error back to the client
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
promise.then do |result|
|
|
41
|
+
channel.send_message('response', callback_id, result, nil)
|
|
42
|
+
|
|
43
|
+
run_time = ((Time.now.to_f - start_time) * 1000).round(3)
|
|
44
|
+
Volt.logger.log_dispatch(class_name, method_name, run_time, args)
|
|
45
|
+
end.fail do |error|
|
|
46
|
+
Volt.logger.error(error)
|
|
47
|
+
channel.send_message('response', callback_id, nil, error)
|
|
47
48
|
end
|
|
48
49
|
end
|
|
49
50
|
|
|
@@ -64,7 +65,8 @@ module Volt
|
|
|
64
65
|
end
|
|
65
66
|
end
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
false
|
|
68
69
|
end
|
|
69
70
|
end
|
|
70
71
|
end
|
|
72
|
+
|
|
@@ -36,7 +36,7 @@ module Volt
|
|
|
36
36
|
def self.method_missing(name, *args, &block)
|
|
37
37
|
# TODO: optimize: this could run the inside first to see if it
|
|
38
38
|
# returns a promise, so we don't have to wrap it.
|
|
39
|
-
|
|
39
|
+
Promise.new.then do
|
|
40
40
|
new(nil, nil).send(name, *args, &block)
|
|
41
41
|
end.resolve(nil)
|
|
42
42
|
end
|
data/lib/volt/volt/users.rb
CHANGED
|
@@ -5,23 +5,23 @@ module Volt
|
|
|
5
5
|
user_id_signature = self.user_id_signature
|
|
6
6
|
|
|
7
7
|
if user_id_signature.nil?
|
|
8
|
-
|
|
8
|
+
nil
|
|
9
9
|
else
|
|
10
10
|
index = user_id_signature.index(':')
|
|
11
11
|
user_id = user_id_signature[0...index]
|
|
12
12
|
|
|
13
13
|
if RUBY_PLATFORM != 'opal'
|
|
14
|
-
hash = user_id_signature[(index+1)..-1]
|
|
14
|
+
hash = user_id_signature[(index + 1)..-1]
|
|
15
15
|
|
|
16
16
|
# Make sure the user hash matches
|
|
17
17
|
if BCrypt::Password.new(hash) != "#{Volt.config.app_secret}::#{user_id}"
|
|
18
18
|
# user id has been tampered with, reject
|
|
19
|
-
|
|
19
|
+
fail 'user id or hash has been tampered with'
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
user_id
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -34,16 +34,15 @@ module Volt
|
|
|
34
34
|
def user
|
|
35
35
|
user_id = self.user_id
|
|
36
36
|
if user_id
|
|
37
|
-
|
|
37
|
+
$page.store._users.find_one(_id: user_id)
|
|
38
38
|
else
|
|
39
|
-
|
|
39
|
+
nil
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
# Login the user, return a promise for success
|
|
44
44
|
def login(username, password)
|
|
45
45
|
UserTasks.login(username, password).then do |result|
|
|
46
|
-
|
|
47
46
|
# Assign the user_id cookie for the user
|
|
48
47
|
$page.cookies._user_id = result
|
|
49
48
|
|
|
@@ -56,7 +55,6 @@ module Volt
|
|
|
56
55
|
$page.cookies.delete(:user_id)
|
|
57
56
|
end
|
|
58
57
|
|
|
59
|
-
|
|
60
58
|
# Fetches the user_id+signature from the correct spot depending on client
|
|
61
59
|
# or server, does not verify it.
|
|
62
60
|
def user_id_signature
|
|
@@ -75,4 +73,4 @@ module Volt
|
|
|
75
73
|
user_id_signature
|
|
76
74
|
end
|
|
77
75
|
end
|
|
78
|
-
end
|
|
76
|
+
end
|
data/lib/volt.rb
CHANGED
|
@@ -3,8 +3,7 @@ require 'volt/extra_core/extra_core'
|
|
|
3
3
|
require 'volt/reactive/computation'
|
|
4
4
|
require 'volt/reactive/dependency'
|
|
5
5
|
require 'volt/config'
|
|
6
|
-
|
|
7
|
-
else
|
|
6
|
+
unless RUBY_PLATFORM == 'opal'
|
|
8
7
|
require 'volt/data_stores/data_store'
|
|
9
8
|
end
|
|
10
9
|
require 'volt/volt/users'
|
|
@@ -40,7 +39,7 @@ module Volt
|
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
def logger
|
|
43
|
-
@logger ||=
|
|
42
|
+
@logger ||= Volt::VoltLogger.new
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
attr_writer :logger
|
|
@@ -50,4 +49,3 @@ module Volt
|
|
|
50
49
|
end
|
|
51
50
|
end
|
|
52
51
|
end
|
|
53
|
-
|
|
@@ -1 +1 @@
|
|
|
1
|
-
component 'a-gem-that-isnt-in-the-gemfile'
|
|
1
|
+
component 'a-gem-that-isnt-in-the-gemfile'
|
|
@@ -10,8 +10,8 @@ gem 'volt-bootstrap'
|
|
|
10
10
|
# Simple theme for bootstrap, remove to theme yourself.
|
|
11
11
|
gem 'volt-bootstrap-jumbotron-theme'
|
|
12
12
|
|
|
13
|
-
gem 'volt-fields'
|
|
14
|
-
gem 'volt-user-templates'
|
|
13
|
+
gem 'volt-fields'
|
|
14
|
+
gem 'volt-user-templates'
|
|
15
15
|
|
|
16
16
|
# Server for MRI
|
|
17
17
|
platform :mri do
|
|
@@ -11,6 +11,5 @@ get '/todos', _controller: 'todos'
|
|
|
11
11
|
get '/signup', _controller: 'user-templates', _action: 'signup'
|
|
12
12
|
get '/login', _controller: 'user-templates', _action: 'login'
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
# The main route, this should be last. It will match any params not previously matched.
|
|
16
15
|
get '/', {}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
class User < Volt::User
|
|
2
|
-
end
|
|
2
|
+
end
|
|
@@ -2,7 +2,9 @@ require 'spec_helper'
|
|
|
2
2
|
require 'volt/extra_core/array'
|
|
3
3
|
|
|
4
4
|
describe Array do
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
describe '#sum' do
|
|
6
|
+
it 'calculates sum of array of integers' do
|
|
7
|
+
expect([1, 2, 3].sum).to eq(6)
|
|
8
|
+
end
|
|
7
9
|
end
|
|
8
10
|
end
|
|
@@ -11,7 +11,7 @@ end
|
|
|
11
11
|
class TestSubClassAttributes2 < TestClassAttributes
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
describe
|
|
14
|
+
describe 'extra_core class addons' do
|
|
15
15
|
it 'should provide class_attributes that can be inherited' do
|
|
16
16
|
expect(TestClassAttributes.some_data).to eq(nil)
|
|
17
17
|
|
|
@@ -30,4 +30,4 @@ describe "extra_core class addons" do
|
|
|
30
30
|
expect(TestSubClassAttributes.some_data).to eq(10)
|
|
31
31
|
expect(TestSubClassAttributes2.some_data).to eq(15)
|
|
32
32
|
end
|
|
33
|
-
end
|
|
33
|
+
end
|