volt 0.8.14 → 0.8.15
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/.gitignore +1 -1
- data/Readme.md +8 -2
- data/VERSION +1 -1
- data/app/volt/controllers/notices_controller.rb +1 -1
- data/app/volt/models/user.rb +2 -2
- data/app/volt/tasks/live_query/live_query_pool.rb +1 -1
- data/app/volt/tasks/query_tasks.rb +1 -1
- data/app/volt/tasks/store_tasks.rb +1 -1
- data/app/volt/tasks/user_tasks.rb +2 -2
- data/lib/volt/boot.rb +2 -2
- data/lib/volt/cli/asset_compile.rb +31 -27
- data/lib/volt/cli.rb +64 -65
- data/lib/volt/config.rb +25 -23
- data/lib/volt/console.rb +17 -16
- data/lib/volt/controllers/model_controller.rb +82 -80
- data/lib/volt/data_stores/data_store.rb +2 -2
- data/lib/volt/data_stores/mongo_driver.rb +2 -2
- data/lib/volt/extra_core/inflections.rb +2 -2
- data/lib/volt/extra_core/inflector/inflections.rb +185 -183
- data/lib/volt/extra_core/inflector/methods.rb +50 -48
- data/lib/volt/extra_core/string.rb +2 -2
- data/lib/volt/models/array_model.rb +93 -92
- data/lib/volt/models/cursor.rb +3 -2
- data/lib/volt/models/model.rb +248 -251
- data/lib/volt/models/model_hash_behaviour.rb +44 -44
- data/lib/volt/models/model_helpers.rb +38 -36
- data/lib/volt/models/model_state.rb +16 -17
- data/lib/volt/models/model_wrapper.rb +25 -24
- data/lib/volt/models/persistors/array_store.rb +145 -143
- data/lib/volt/models/persistors/base.rb +18 -16
- data/lib/volt/models/persistors/flash.rb +24 -22
- data/lib/volt/models/persistors/local_store.rb +46 -44
- data/lib/volt/models/persistors/model_identity_map.rb +10 -8
- data/lib/volt/models/persistors/model_store.rb +76 -76
- data/lib/volt/models/persistors/params.rb +19 -17
- data/lib/volt/models/persistors/query/query_listener.rb +65 -63
- data/lib/volt/models/persistors/query/query_listener_pool.rb +12 -10
- data/lib/volt/models/persistors/store.rb +28 -28
- data/lib/volt/models/persistors/store_factory.rb +12 -10
- data/lib/volt/models/persistors/store_state.rb +33 -31
- data/lib/volt/models/url.rb +96 -104
- data/lib/volt/models/validations.rb +56 -54
- data/lib/volt/models/validators/length_validator.rb +24 -22
- data/lib/volt/models/validators/presence_validator.rb +14 -12
- data/lib/volt/page/bindings/attribute_binding.rb +106 -106
- data/lib/volt/page/bindings/base_binding.rb +23 -21
- data/lib/volt/page/bindings/component_binding.rb +3 -1
- data/lib/volt/page/bindings/content_binding.rb +34 -34
- data/lib/volt/page/bindings/each_binding.rb +113 -113
- data/lib/volt/page/bindings/event_binding.rb +38 -34
- data/lib/volt/page/bindings/if_binding.rb +56 -54
- data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +24 -22
- data/lib/volt/page/bindings/template_binding.rb +182 -185
- data/lib/volt/page/channel.rb +79 -77
- data/lib/volt/page/channel_stub.rb +29 -27
- data/lib/volt/page/document.rb +6 -5
- data/lib/volt/page/document_events.rb +54 -52
- data/lib/volt/page/page.rb +139 -138
- data/lib/volt/page/string_template_renderer.rb +36 -36
- data/lib/volt/page/sub_context.rb +26 -25
- data/lib/volt/page/targets/attribute_section.rb +27 -25
- data/lib/volt/page/targets/attribute_target.rb +7 -6
- data/lib/volt/page/targets/base_section.rb +27 -26
- data/lib/volt/page/targets/binding_document/base_node.rb +3 -1
- data/lib/volt/page/targets/binding_document/component_node.rb +85 -82
- data/lib/volt/page/targets/binding_document/html_node.rb +11 -9
- data/lib/volt/page/targets/dom_section.rb +78 -77
- data/lib/volt/page/targets/dom_target.rb +8 -6
- data/lib/volt/page/targets/dom_template.rb +90 -88
- data/lib/volt/page/targets/helpers/comment_searchers.rb +51 -49
- data/lib/volt/page/tasks.rb +59 -57
- data/lib/volt/page/template_renderer.rb +17 -14
- data/lib/volt/page/url_tracker.rb +26 -24
- data/lib/volt/reactive/computation.rb +87 -88
- data/lib/volt/reactive/dependency.rb +30 -28
- data/lib/volt/reactive/eventable.rb +64 -62
- data/lib/volt/reactive/hash_dependency.rb +25 -23
- data/lib/volt/reactive/reactive_accessors.rb +34 -32
- data/lib/volt/reactive/reactive_array.rb +162 -162
- data/lib/volt/reactive/reactive_hash.rb +37 -35
- data/lib/volt/router/routes.rb +99 -101
- data/lib/volt/server/component_handler.rb +20 -21
- data/lib/volt/server/component_templates.rb +72 -70
- data/lib/volt/server/html_parser/attribute_scope.rb +109 -99
- data/lib/volt/server/html_parser/each_scope.rb +17 -16
- data/lib/volt/server/html_parser/if_view_scope.rb +51 -49
- data/lib/volt/server/html_parser/sandlebars_parser.rb +184 -177
- data/lib/volt/server/html_parser/textarea_scope.rb +24 -22
- data/lib/volt/server/html_parser/view_handler.rb +66 -65
- data/lib/volt/server/html_parser/view_parser.rb +23 -21
- data/lib/volt/server/html_parser/view_scope.rb +142 -141
- data/lib/volt/server/rack/asset_files.rb +81 -79
- data/lib/volt/server/rack/component_code.rb +17 -15
- data/lib/volt/server/rack/component_html_renderer.rb +14 -12
- data/lib/volt/server/rack/component_paths.rb +72 -71
- data/lib/volt/server/rack/index_files.rb +36 -39
- data/lib/volt/server/rack/opal_files.rb +43 -41
- data/lib/volt/server/rack/source_map_server.rb +23 -21
- data/lib/volt/server/socket_connection_handler.rb +46 -45
- data/lib/volt/server/socket_connection_handler_stub.rb +21 -19
- data/lib/volt/server.rb +60 -58
- data/lib/volt/spec/setup.rb +3 -3
- data/lib/volt/tasks/dispatcher.rb +24 -23
- data/lib/volt/tasks/task_handler.rb +35 -33
- data/lib/volt/utils/ejson.rb +8 -6
- data/lib/volt/utils/generic_counting_pool.rb +33 -31
- data/lib/volt/utils/generic_pool.rb +73 -70
- data/lib/volt/utils/local_storage.rb +42 -38
- data/lib/volt/volt/environment.rb +1 -1
- data/lib/volt.rb +44 -42
- data/spec/apps/kitchen_sink/app/main/assets/css/todos.css +28 -0
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +2 -2
- data/spec/apps/kitchen_sink/app/main/controllers/todos_controller.rb +17 -0
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -0
- data/spec/apps/kitchen_sink/app/main/views/todos/index.html +24 -0
- data/spec/apps/kitchen_sink/config.ru +1 -1
- data/spec/controllers/reactive_accessors_spec.rb +5 -5
- data/spec/extra_core/inflector_spec.rb +2 -2
- data/spec/integration/list_spec.rb +68 -0
- data/spec/models/model_spec.rb +57 -57
- data/spec/models/persistors/params_spec.rb +6 -6
- data/spec/models/persistors/store_spec.rb +7 -7
- data/spec/models/validations_spec.rb +3 -3
- data/spec/page/bindings/content_binding_spec.rb +7 -7
- data/spec/page/bindings/template_binding_spec.rb +4 -5
- data/spec/page/sub_context_spec.rb +2 -2
- data/spec/reactive/computation_spec.rb +10 -10
- data/spec/reactive/dependency_spec.rb +2 -2
- data/spec/reactive/eventable_spec.rb +4 -4
- data/spec/reactive/reactive_array_spec.rb +13 -13
- data/spec/router/routes_spec.rb +5 -5
- data/spec/server/html_parser/sandlebars_parser_spec.rb +9 -9
- data/spec/server/html_parser/view_parser_spec.rb +27 -27
- data/spec/server/rack/asset_files_spec.rb +5 -5
- data/spec/server/rack/component_paths_spec.rb +2 -2
- data/spec/tasks/live_query_spec.rb +2 -2
- data/spec/tasks/query_tasks.rb +1 -1
- data/spec/tasks/query_tracker_spec.rb +1 -1
- data/spec/templates/targets/binding_document/component_node_spec.rb +2 -2
- data/spec/utils/generic_counting_pool_spec.rb +2 -2
- data/spec/utils/generic_pool_spec.rb +2 -2
- data/templates/component/controllers/main_controller.rb +1 -1
- data/templates/model/model.rb.tt +2 -2
- data/templates/newgem/app/newgem/controllers/main_controller.rb.tt +2 -2
- data/templates/project/app/main/controllers/main_controller.rb +1 -1
- data/templates/project/config.ru +1 -1
- metadata +10 -3
- data/app/volt/assets/js/vertxbus.js +0 -216
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
module Volt
|
|
2
|
+
class PresenceValidator
|
|
3
|
+
def self.validate(model, field_name, args)
|
|
4
|
+
errors = {}
|
|
5
|
+
value = model.send(field_name)
|
|
6
|
+
if !value || value.blank?
|
|
7
|
+
if args.is_a?(Hash) && args[:message]
|
|
8
|
+
message = args[:message]
|
|
9
|
+
else
|
|
10
|
+
message = "must be specified"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
errors[field_name] = [message]
|
|
10
14
|
end
|
|
11
15
|
|
|
12
|
-
errors
|
|
16
|
+
return errors
|
|
13
17
|
end
|
|
14
|
-
|
|
15
|
-
return errors
|
|
16
18
|
end
|
|
17
19
|
end
|
|
@@ -1,140 +1,140 @@
|
|
|
1
1
|
require 'volt/page/bindings/base_binding'
|
|
2
2
|
require 'volt/page/targets/attribute_target'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
module Volt
|
|
5
|
+
class AttributeBinding < BaseBinding
|
|
6
|
+
def initialize(page, target, context, binding_name, attribute_name, getter, setter)
|
|
7
|
+
super(page, target, context, binding_name)
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
@attribute_name = attribute_name
|
|
10
|
+
@getter = getter
|
|
11
|
+
@setter = setter
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
setup
|
|
14
|
+
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
def setup
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
# Listen for changes
|
|
19
|
+
@computation = -> do
|
|
20
|
+
begin
|
|
21
|
+
update(@context.instance_eval(&@getter))
|
|
22
|
+
rescue => e
|
|
23
|
+
Volt.logger.error("AttributeBinding Error: #{e.inspect}")
|
|
24
|
+
update('')
|
|
25
|
+
end
|
|
26
|
+
end.watch!
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
@is_radio = element.is('[type=radio]')
|
|
29
|
+
if @is_radio
|
|
30
|
+
@selected_value = element.attr('value')
|
|
31
|
+
end
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
# Bind so when this value updates, we update
|
|
34
|
+
case @attribute_name
|
|
35
|
+
when 'value'
|
|
36
|
+
element.on('input.attrbind') { changed }
|
|
37
|
+
when 'checked'
|
|
38
|
+
element.on('change.attrbind') { |event| changed(event) }
|
|
39
|
+
end
|
|
38
40
|
end
|
|
39
|
-
end
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
def changed(event=nil)
|
|
43
|
+
case @attribute_name
|
|
44
|
+
when 'value'
|
|
45
|
+
current_value = element.value
|
|
46
|
+
else
|
|
47
|
+
current_value = element.is(':checked')
|
|
48
|
+
end
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
if @is_radio
|
|
51
|
+
if current_value
|
|
52
|
+
# if it is a radio button and its checked
|
|
53
|
+
@context.instance_exec(@selected_value, &@setter)
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
@context.instance_exec(current_value, &@setter)
|
|
53
57
|
end
|
|
54
|
-
else
|
|
55
|
-
@context.instance_exec(current_value, &@setter)
|
|
56
58
|
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def element
|
|
60
|
-
Element.find('#' + binding_name)
|
|
61
|
-
end
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
update_checked(new_value)
|
|
66
|
-
return
|
|
60
|
+
def element
|
|
61
|
+
Element.find('#' + binding_name)
|
|
67
62
|
end
|
|
68
63
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
def update(new_value)
|
|
65
|
+
if @attribute_name == 'checked'
|
|
66
|
+
update_checked(new_value)
|
|
67
|
+
return
|
|
68
|
+
end
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@string_template_renderer = new_value
|
|
70
|
+
# Stop any previous reactive template computations
|
|
71
|
+
@string_template_renderer_computation.stop if @string_template_renderer_computation
|
|
72
|
+
@string_template_renderer.remove if @string_template_renderer
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if new_value.is_a?(NilMethodCall) || new_value.nil?
|
|
83
|
-
new_value = ''
|
|
84
|
-
end
|
|
74
|
+
if new_value.is_a?(StringTemplateRender)
|
|
75
|
+
# We don't need to refetch the whole reactive template to
|
|
76
|
+
# update, we can just depend on it and update directly.
|
|
77
|
+
@string_template_renderer = new_value
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
79
|
+
@string_template_renderer_computation = -> do
|
|
80
|
+
self.value = @string_template_renderer.html
|
|
81
|
+
end.watch!
|
|
82
|
+
else
|
|
83
|
+
if new_value.is_a?(NilMethodCall) || new_value.nil?
|
|
84
|
+
new_value = ''
|
|
85
|
+
end
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
case @attribute_name
|
|
92
|
-
when 'value'
|
|
93
|
-
# TODO: only update if its not the same, this keeps it from moving the
|
|
94
|
-
# cursor in text fields.
|
|
95
|
-
if val != element.value
|
|
96
|
-
element.value = val
|
|
87
|
+
self.value = new_value
|
|
97
88
|
end
|
|
98
|
-
else
|
|
99
|
-
element[@attribute_name] = val
|
|
100
89
|
end
|
|
101
|
-
end
|
|
102
90
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
91
|
+
def value=(val)
|
|
92
|
+
case @attribute_name
|
|
93
|
+
when 'value'
|
|
94
|
+
# TODO: only update if its not the same, this keeps it from moving the
|
|
95
|
+
# cursor in text fields.
|
|
96
|
+
if val != element.value
|
|
97
|
+
element.value = val
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
element[@attribute_name] = val
|
|
101
|
+
end
|
|
106
102
|
end
|
|
107
103
|
|
|
108
|
-
|
|
109
|
-
value
|
|
110
|
-
|
|
104
|
+
def update_checked(value)
|
|
105
|
+
if value.is_a?(NilMethodCall) || value.nil?
|
|
106
|
+
value = false
|
|
107
|
+
end
|
|
111
108
|
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
if @is_radio
|
|
110
|
+
value = (@selected_value == value)
|
|
111
|
+
end
|
|
114
112
|
|
|
115
|
-
|
|
116
|
-
# Unbind events, leave the element there since attribute bindings
|
|
117
|
-
# aren't responsible for it being there.
|
|
118
|
-
case @attribute_name
|
|
119
|
-
when 'value'
|
|
120
|
-
element.off('input.attrbind', nil)
|
|
121
|
-
when 'checked'
|
|
122
|
-
element.off('change.attrbind', nil)
|
|
113
|
+
element.prop('checked', value)
|
|
123
114
|
end
|
|
124
115
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
116
|
+
def remove
|
|
117
|
+
# Unbind events, leave the element there since attribute bindings
|
|
118
|
+
# aren't responsible for it being there.
|
|
119
|
+
case @attribute_name
|
|
120
|
+
when 'value'
|
|
121
|
+
element.off('input.attrbind', nil)
|
|
122
|
+
when 'checked'
|
|
123
|
+
element.off('change.attrbind', nil)
|
|
124
|
+
end
|
|
134
125
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
126
|
+
@string_template_renderer.remove if @string_template_renderer
|
|
127
|
+
@string_template_renderer_computation.stop if @string_template_renderer_computation
|
|
128
|
+
@computation.stop if @computation
|
|
138
129
|
|
|
130
|
+
# Clear any references
|
|
131
|
+
@target = nil
|
|
132
|
+
@context = nil
|
|
133
|
+
@getter = nil
|
|
134
|
+
end
|
|
139
135
|
|
|
136
|
+
def remove_anchors
|
|
137
|
+
raise "attribute bindings do not have anchors, can not remove them"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
140
|
end
|
|
@@ -8,32 +8,34 @@
|
|
|
8
8
|
# 3. context - the context object the binding will be evaluated in
|
|
9
9
|
# 4. binding_name - the id for the comment (or id for attributes) where the
|
|
10
10
|
# binding will be inserted.
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
module Volt
|
|
12
|
+
class BaseBinding
|
|
13
|
+
attr_accessor :target, :context, :binding_name
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
def initialize(page, target, context, binding_name)
|
|
16
|
+
@page = page
|
|
17
|
+
@target = target
|
|
18
|
+
@context = context
|
|
19
|
+
@binding_name = binding_name
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
@@binding_number ||= 10000
|
|
22
|
+
end
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
def dom_section
|
|
25
|
+
@dom_section ||= target.dom_section(@binding_name)
|
|
26
|
+
end
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
def remove
|
|
29
|
+
@dom_section.remove if @dom_section
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
# Clear any references
|
|
32
|
+
@target = nil
|
|
33
|
+
@context = nil
|
|
34
|
+
@dom_section = nil
|
|
35
|
+
end
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
def remove_anchors
|
|
38
|
+
@dom_section.remove_anchors if @dom_section
|
|
39
|
+
end
|
|
38
40
|
end
|
|
39
41
|
end
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
require 'volt/page/bindings/base_binding'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
3
|
+
module Volt
|
|
4
|
+
class ContentBinding < BaseBinding
|
|
5
|
+
def initialize(page, target, context, binding_name, getter)
|
|
6
|
+
# puts "New Content Binding: #{self.inspect}"
|
|
7
|
+
super(page, target, context, binding_name)
|
|
8
|
+
|
|
9
|
+
# Listen for changes
|
|
10
|
+
@computation = -> do
|
|
11
|
+
begin
|
|
12
|
+
update(@context.instance_eval(&getter))
|
|
13
|
+
rescue => e
|
|
14
|
+
Volt.logger.error("ContentBinding Error: #{e.inspect}")
|
|
15
|
+
update('')
|
|
16
|
+
end
|
|
17
|
+
end.watch!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def update(value)
|
|
21
|
+
value = value.or('')
|
|
22
|
+
|
|
23
|
+
# Exception values display the exception as a string
|
|
24
|
+
value = value.to_s
|
|
25
|
+
|
|
26
|
+
# Update the html in this section
|
|
27
|
+
# TODO: Move the formatter into another class.
|
|
28
|
+
dom_section.html = value.gsub("\n", "<br />\n")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def remove
|
|
32
|
+
@computation.stop if @computation
|
|
33
|
+
@computation = nil
|
|
34
|
+
|
|
35
|
+
super
|
|
36
|
+
end
|
|
28
37
|
end
|
|
29
|
-
|
|
30
|
-
def remove
|
|
31
|
-
@computation.stop if @computation
|
|
32
|
-
@computation = nil
|
|
33
|
-
|
|
34
|
-
super
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
|
|
38
38
|
end
|