volt 0.8.14 → 0.8.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Readme.md +8 -2
  4. data/VERSION +1 -1
  5. data/app/volt/controllers/notices_controller.rb +1 -1
  6. data/app/volt/models/user.rb +2 -2
  7. data/app/volt/tasks/live_query/live_query_pool.rb +1 -1
  8. data/app/volt/tasks/query_tasks.rb +1 -1
  9. data/app/volt/tasks/store_tasks.rb +1 -1
  10. data/app/volt/tasks/user_tasks.rb +2 -2
  11. data/lib/volt/boot.rb +2 -2
  12. data/lib/volt/cli/asset_compile.rb +31 -27
  13. data/lib/volt/cli.rb +64 -65
  14. data/lib/volt/config.rb +25 -23
  15. data/lib/volt/console.rb +17 -16
  16. data/lib/volt/controllers/model_controller.rb +82 -80
  17. data/lib/volt/data_stores/data_store.rb +2 -2
  18. data/lib/volt/data_stores/mongo_driver.rb +2 -2
  19. data/lib/volt/extra_core/inflections.rb +2 -2
  20. data/lib/volt/extra_core/inflector/inflections.rb +185 -183
  21. data/lib/volt/extra_core/inflector/methods.rb +50 -48
  22. data/lib/volt/extra_core/string.rb +2 -2
  23. data/lib/volt/models/array_model.rb +93 -92
  24. data/lib/volt/models/cursor.rb +3 -2
  25. data/lib/volt/models/model.rb +248 -251
  26. data/lib/volt/models/model_hash_behaviour.rb +44 -44
  27. data/lib/volt/models/model_helpers.rb +38 -36
  28. data/lib/volt/models/model_state.rb +16 -17
  29. data/lib/volt/models/model_wrapper.rb +25 -24
  30. data/lib/volt/models/persistors/array_store.rb +145 -143
  31. data/lib/volt/models/persistors/base.rb +18 -16
  32. data/lib/volt/models/persistors/flash.rb +24 -22
  33. data/lib/volt/models/persistors/local_store.rb +46 -44
  34. data/lib/volt/models/persistors/model_identity_map.rb +10 -8
  35. data/lib/volt/models/persistors/model_store.rb +76 -76
  36. data/lib/volt/models/persistors/params.rb +19 -17
  37. data/lib/volt/models/persistors/query/query_listener.rb +65 -63
  38. data/lib/volt/models/persistors/query/query_listener_pool.rb +12 -10
  39. data/lib/volt/models/persistors/store.rb +28 -28
  40. data/lib/volt/models/persistors/store_factory.rb +12 -10
  41. data/lib/volt/models/persistors/store_state.rb +33 -31
  42. data/lib/volt/models/url.rb +96 -104
  43. data/lib/volt/models/validations.rb +56 -54
  44. data/lib/volt/models/validators/length_validator.rb +24 -22
  45. data/lib/volt/models/validators/presence_validator.rb +14 -12
  46. data/lib/volt/page/bindings/attribute_binding.rb +106 -106
  47. data/lib/volt/page/bindings/base_binding.rb +23 -21
  48. data/lib/volt/page/bindings/component_binding.rb +3 -1
  49. data/lib/volt/page/bindings/content_binding.rb +34 -34
  50. data/lib/volt/page/bindings/each_binding.rb +113 -113
  51. data/lib/volt/page/bindings/event_binding.rb +38 -34
  52. data/lib/volt/page/bindings/if_binding.rb +56 -54
  53. data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +24 -22
  54. data/lib/volt/page/bindings/template_binding.rb +182 -185
  55. data/lib/volt/page/channel.rb +79 -77
  56. data/lib/volt/page/channel_stub.rb +29 -27
  57. data/lib/volt/page/document.rb +6 -5
  58. data/lib/volt/page/document_events.rb +54 -52
  59. data/lib/volt/page/page.rb +139 -138
  60. data/lib/volt/page/string_template_renderer.rb +36 -36
  61. data/lib/volt/page/sub_context.rb +26 -25
  62. data/lib/volt/page/targets/attribute_section.rb +27 -25
  63. data/lib/volt/page/targets/attribute_target.rb +7 -6
  64. data/lib/volt/page/targets/base_section.rb +27 -26
  65. data/lib/volt/page/targets/binding_document/base_node.rb +3 -1
  66. data/lib/volt/page/targets/binding_document/component_node.rb +85 -82
  67. data/lib/volt/page/targets/binding_document/html_node.rb +11 -9
  68. data/lib/volt/page/targets/dom_section.rb +78 -77
  69. data/lib/volt/page/targets/dom_target.rb +8 -6
  70. data/lib/volt/page/targets/dom_template.rb +90 -88
  71. data/lib/volt/page/targets/helpers/comment_searchers.rb +51 -49
  72. data/lib/volt/page/tasks.rb +59 -57
  73. data/lib/volt/page/template_renderer.rb +17 -14
  74. data/lib/volt/page/url_tracker.rb +26 -24
  75. data/lib/volt/reactive/computation.rb +87 -88
  76. data/lib/volt/reactive/dependency.rb +30 -28
  77. data/lib/volt/reactive/eventable.rb +64 -62
  78. data/lib/volt/reactive/hash_dependency.rb +25 -23
  79. data/lib/volt/reactive/reactive_accessors.rb +34 -32
  80. data/lib/volt/reactive/reactive_array.rb +162 -162
  81. data/lib/volt/reactive/reactive_hash.rb +37 -35
  82. data/lib/volt/router/routes.rb +99 -101
  83. data/lib/volt/server/component_handler.rb +20 -21
  84. data/lib/volt/server/component_templates.rb +72 -70
  85. data/lib/volt/server/html_parser/attribute_scope.rb +109 -99
  86. data/lib/volt/server/html_parser/each_scope.rb +17 -16
  87. data/lib/volt/server/html_parser/if_view_scope.rb +51 -49
  88. data/lib/volt/server/html_parser/sandlebars_parser.rb +184 -177
  89. data/lib/volt/server/html_parser/textarea_scope.rb +24 -22
  90. data/lib/volt/server/html_parser/view_handler.rb +66 -65
  91. data/lib/volt/server/html_parser/view_parser.rb +23 -21
  92. data/lib/volt/server/html_parser/view_scope.rb +142 -141
  93. data/lib/volt/server/rack/asset_files.rb +81 -79
  94. data/lib/volt/server/rack/component_code.rb +17 -15
  95. data/lib/volt/server/rack/component_html_renderer.rb +14 -12
  96. data/lib/volt/server/rack/component_paths.rb +72 -71
  97. data/lib/volt/server/rack/index_files.rb +36 -39
  98. data/lib/volt/server/rack/opal_files.rb +43 -41
  99. data/lib/volt/server/rack/source_map_server.rb +23 -21
  100. data/lib/volt/server/socket_connection_handler.rb +46 -45
  101. data/lib/volt/server/socket_connection_handler_stub.rb +21 -19
  102. data/lib/volt/server.rb +60 -58
  103. data/lib/volt/spec/setup.rb +3 -3
  104. data/lib/volt/tasks/dispatcher.rb +24 -23
  105. data/lib/volt/tasks/task_handler.rb +35 -33
  106. data/lib/volt/utils/ejson.rb +8 -6
  107. data/lib/volt/utils/generic_counting_pool.rb +33 -31
  108. data/lib/volt/utils/generic_pool.rb +73 -70
  109. data/lib/volt/utils/local_storage.rb +42 -38
  110. data/lib/volt/volt/environment.rb +1 -1
  111. data/lib/volt.rb +44 -42
  112. data/spec/apps/kitchen_sink/app/main/assets/css/todos.css +28 -0
  113. data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
  114. data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +2 -2
  115. data/spec/apps/kitchen_sink/app/main/controllers/todos_controller.rb +17 -0
  116. data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -0
  117. data/spec/apps/kitchen_sink/app/main/views/todos/index.html +24 -0
  118. data/spec/apps/kitchen_sink/config.ru +1 -1
  119. data/spec/controllers/reactive_accessors_spec.rb +5 -5
  120. data/spec/extra_core/inflector_spec.rb +2 -2
  121. data/spec/integration/list_spec.rb +68 -0
  122. data/spec/models/model_spec.rb +57 -57
  123. data/spec/models/persistors/params_spec.rb +6 -6
  124. data/spec/models/persistors/store_spec.rb +7 -7
  125. data/spec/models/validations_spec.rb +3 -3
  126. data/spec/page/bindings/content_binding_spec.rb +7 -7
  127. data/spec/page/bindings/template_binding_spec.rb +4 -5
  128. data/spec/page/sub_context_spec.rb +2 -2
  129. data/spec/reactive/computation_spec.rb +10 -10
  130. data/spec/reactive/dependency_spec.rb +2 -2
  131. data/spec/reactive/eventable_spec.rb +4 -4
  132. data/spec/reactive/reactive_array_spec.rb +13 -13
  133. data/spec/router/routes_spec.rb +5 -5
  134. data/spec/server/html_parser/sandlebars_parser_spec.rb +9 -9
  135. data/spec/server/html_parser/view_parser_spec.rb +27 -27
  136. data/spec/server/rack/asset_files_spec.rb +5 -5
  137. data/spec/server/rack/component_paths_spec.rb +2 -2
  138. data/spec/tasks/live_query_spec.rb +2 -2
  139. data/spec/tasks/query_tasks.rb +1 -1
  140. data/spec/tasks/query_tracker_spec.rb +1 -1
  141. data/spec/templates/targets/binding_document/component_node_spec.rb +2 -2
  142. data/spec/utils/generic_counting_pool_spec.rb +2 -2
  143. data/spec/utils/generic_pool_spec.rb +2 -2
  144. data/templates/component/controllers/main_controller.rb +1 -1
  145. data/templates/model/model.rb.tt +2 -2
  146. data/templates/newgem/app/newgem/controllers/main_controller.rb.tt +2 -2
  147. data/templates/project/app/main/controllers/main_controller.rb +1 -1
  148. data/templates/project/config.ru +1 -1
  149. metadata +10 -3
  150. data/app/volt/assets/js/vertxbus.js +0 -216
@@ -2,235 +2,232 @@ require 'volt/page/bindings/base_binding'
2
2
  require 'volt/page/template_renderer'
3
3
  require 'volt/page/bindings/template_binding/grouped_controllers'
4
4
 
5
- class TemplateBinding < BaseBinding
6
- def initialize(page, target, context, binding_name, binding_in_path, getter)
7
- super(page, target, context, binding_name)
8
-
9
- # Binding in path is the path for the template this binding is in
10
- setup_path(binding_in_path)
11
-
12
- @current_template = nil
13
-
14
- # Run the initial render
15
- @computation = -> do
16
- # Don't try to render if this has been removed
17
- if @context
18
- # Render
19
- update(*@context.instance_eval(&getter))
20
- end
21
- end.watch!
22
- end
5
+ module Volt
6
+ class TemplateBinding < BaseBinding
7
+ def initialize(page, target, context, binding_name, binding_in_path, getter)
8
+ super(page, target, context, binding_name)
9
+
10
+ # Binding in path is the path for the template this binding is in
11
+ setup_path(binding_in_path)
12
+
13
+ @current_template = nil
14
+
15
+ # Run the initial render
16
+ @computation = -> do
17
+ # Don't try to render if this has been removed
18
+ if @context
19
+ # Render
20
+ update(*@context.instance_eval(&getter))
21
+ end
22
+ end.watch!
23
+ end
23
24
 
24
- def setup_path(binding_in_path)
25
- path_parts = binding_in_path.split('/')
26
- @collection_name = path_parts[0]
27
- @controller_name = path_parts[1]
28
- @page_name = path_parts[2]
29
- end
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
30
31
 
31
- # Returns true if there is a template at the path
32
- def check_for_template?(path)
33
- @page.templates[path]
34
- end
32
+ # Returns true if there is a template at the path
33
+ def check_for_template?(path)
34
+ @page.templates[path]
35
+ end
35
36
 
36
- # Takes in a lookup path and returns the full path for the matching
37
- # template. Also returns the controller and action name if applicable.
38
- #
39
- # Looking up a path is fairly simple. There are 4 parts needed to find
40
- # the html to be rendered. File paths look like this:
41
- # app/{component}/views/{controller_name}/{view}.html
42
- # Within the html file may be one or more sections.
43
- # 1. component (app/{comp})
44
- # 2. controller
45
- # 3. view
46
- # 4. sections
47
- #
48
- # When searching for a file, the lookup starts at the section, and moves up.
49
- # when moving up, default values are provided for the section, then view/section, etc..
50
- # until a file is either found or the component level is reached.
51
- #
52
- # The defaults are as follows:
53
- # 1. component - main
54
- # 2. controller - main
55
- # 3. view - main
56
- # 4. section - body
57
- def path_for_template(lookup_path, force_section=nil)
58
- parts = lookup_path.split('/')
59
- parts_size = parts.size
60
-
61
- default_parts = ['main', 'main', 'index', 'body']
62
-
63
- # When forcing a sub template, we can default the sub template section
64
- default_parts[-1] = force_section if force_section
65
-
66
- (5 - parts_size).times do |path_position|
67
- # If they passed in a force_section, we can skip the first
68
- next if force_section && path_position == 0
69
-
70
- full_path = [@collection_name, @controller_name, @page_name, nil]
71
-
72
- start_at = full_path.size - parts_size - path_position
73
-
74
- full_path.size.times do |index|
75
- if index >= start_at
76
- if part = parts[index-start_at]
77
- full_path[index] = part
78
- else
79
- full_path[index] = default_parts[index]
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 - main
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 = ['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
80
82
  end
81
83
  end
82
- end
83
84
 
84
- path = full_path.join('/')
85
- if check_for_template?(path)
86
- controller = nil
85
+ path = full_path.join('/')
86
+ if check_for_template?(path)
87
+ controller = nil
87
88
 
88
- # Don't return a controller if we are just getting another section
89
- # from the same controller
90
- if path_position >= 1
91
- # Lookup the controller
92
- controller = [full_path[0], full_path[1] + '_controller', full_path[2]]
89
+ # Don't return a controller if we are just getting another section
90
+ # from the same controller
91
+ if path_position >= 1
92
+ # Lookup the controller
93
+ controller = [full_path[0], full_path[1] + '_controller', full_path[2]]
94
+ end
95
+ return path, controller
93
96
  end
94
- return path, controller
95
97
  end
98
+
99
+ return nil, nil
96
100
  end
97
101
 
98
- return nil, nil
99
- end
102
+ def update(path, section_or_arguments=nil, options={})
103
+ Computation.run_without_tracking do
104
+ # Remove existing template and call _removed
105
+ controller_send(:"#{@action}_removed") if @action && @controller
106
+ @current_template.remove if @current_template
100
107
 
101
- def update(path, section_or_arguments=nil, options={})
102
- Computation.run_without_tracking do
103
- # Remove existing template and call _removed
104
- controller_send(:"#{@action}_removed") if @action && @controller
105
- @current_template.remove if @current_template
108
+ @options = options
106
109
 
107
- @options = options
110
+ # A blank path needs to load a missing template, otherwise it tries to load
111
+ # the same template.
112
+ path = path.blank? ? '---missing---' : path
108
113
 
109
- # A blank path needs to load a missing template, otherwise it tries to load
110
- # the same template.
111
- path = path.blank? ? '---missing---' : path
114
+ section = nil
115
+ @arguments = nil
112
116
 
113
- section = nil
114
- @arguments = nil
117
+ if section_or_arguments.is_a?(String)
118
+ # Render this as a section
119
+ section = section_or_arguments
120
+ else
121
+ # Use the value passed in as the default arguments
122
+ @arguments = section_or_arguments
123
+ end
115
124
 
116
- if section_or_arguments.is_a?(String)
117
- # Render this as a section
118
- section = section_or_arguments
119
- else
120
- # Use the value passed in as the default arguments
121
- @arguments = section_or_arguments
125
+ # Sometimes we want multiple template bindings to share the same controller (usually
126
+ # when displaying a :Title and a :Body), this instance tracks those.
127
+ if @options && (controller_group = @options[:controller_group])
128
+ @grouped_controller = GroupedControllers.new(controller_group)
129
+ else
130
+ clear_grouped_controller
131
+ end
132
+
133
+ full_path, controller_path = path_for_template(path, section)
134
+ render_template(full_path, controller_path)
135
+
136
+ queue_clear_grouped_controller
122
137
  end
138
+ end
123
139
 
124
- # Sometimes we want multiple template bindings to share the same controller (usually
125
- # when displaying a :Title and a :Body), this instance tracks those.
126
- if @options && (controller_group = @options[:controller_group])
127
- @grouped_controller = GroupedControllers.new(controller_group)
140
+ # On the next tick, we clear the grouped controller so that any changes to template paths
141
+ # will create a new controller and trigger the action.
142
+ def queue_clear_grouped_controller
143
+ if Volt.in_browser?
144
+ # In the browser, we want to keep a grouped controller around during a single run
145
+ # of the event loop. To make that happen, we clear it on the next tick.
146
+ `setImmediate(function() {`
147
+ clear_grouped_controller
148
+ `});`
128
149
  else
150
+ # For the backend, clear it immediately
129
151
  clear_grouped_controller
130
152
  end
131
-
132
- full_path, controller_path = path_for_template(path, section)
133
- render_template(full_path, controller_path)
134
-
135
- queue_clear_grouped_controller
136
153
  end
137
- end
138
154
 
139
- # On the next tick, we clear the grouped controller so that any changes to template paths
140
- # will create a new controller and trigger the action.
141
- def queue_clear_grouped_controller
142
- if Volt.in_browser?
143
- # In the browser, we want to keep a grouped controller around during a single run
144
- # of the event loop. To make that happen, we clear it on the next tick.
145
- `setImmediate(function() {`
146
- clear_grouped_controller
147
- `})`
148
- else
149
- # For the backend, clear it immediately
150
- clear_grouped_controller
155
+ def clear_grouped_controller
156
+ if @grouped_controller
157
+ @grouped_controller.clear
158
+ @grouped_controller = nil
159
+ end
151
160
  end
152
- end
153
161
 
154
- def clear_grouped_controller
155
- if @grouped_controller
156
- @grouped_controller.clear
157
- @grouped_controller = nil
158
- end
159
- end
162
+ # The context for templates can be either a controller, or the original context.
163
+ def render_template(full_path, controller_path)
164
+ args = @arguments ? [SubContext.new(@arguments)] : []
160
165
 
161
- # The context for templates can be either a controller, or the original context.
162
- def render_template(full_path, controller_path)
163
- if @arguments
164
- args = [SubContext.new(@arguments)]
165
- else
166
- args = []
167
- end
166
+ @controller = nil
167
+
168
+ # Fetch grouped controllers if we're grouping
169
+ @controller = @grouped_controller.get if @grouped_controller
168
170
 
169
- @controller = nil
171
+ # The action to be called and rendered
172
+ @action = nil
170
173
 
171
- # Fetch grouped controllers if we're grouping
172
- @controller = @grouped_controller.get if @grouped_controller
174
+ if @controller
175
+ # Track that we're using the group controller
176
+ @grouped_controller.inc if @grouped_controller
177
+ else
178
+ # Otherwise, make a new controller
179
+ controller_class, @action = get_controller(controller_path)
173
180
 
174
- # The action to be called and rendered
175
- @action = nil
181
+ if controller_class
182
+ # Setup the controller
183
+ @controller = controller_class.new(*args)
184
+ else
185
+ @controller = ModelController.new(*args)
186
+ end
176
187
 
177
- if @controller
178
- # Track that we're using the group controller
179
- @grouped_controller.inc if @grouped_controller
180
- else
181
- # Otherwise, make a new controller
182
- controller_class, @action = get_controller(controller_path)
188
+ # Trigger the action
189
+ controller_send(@action) if @action
183
190
 
184
- if controller_class
185
- # Setup the controller
186
- @controller = controller_class.new(*args)
187
- else
188
- @controller = ModelController.new(*args)
191
+ # Track the grouped controller
192
+ @grouped_controller.set(@controller) if @grouped_controller
189
193
  end
190
194
 
191
- # Trigger the action
192
- controller_send(@action) if @action
195
+ @current_template = TemplateRenderer.new(@page, @target, @controller, @binding_name, full_path)
193
196
 
194
- # Track the grouped controller
195
- @grouped_controller.set(@controller) if @grouped_controller
197
+ call_ready
196
198
  end
197
199
 
198
- @current_template = TemplateRenderer.new(@page, @target, @controller, @binding_name, full_path)
199
-
200
- call_ready
201
- end
200
+ def call_ready
201
+ if @controller
202
+ # Set the current section on the controller if it wants so it can manipulate
203
+ # the dom if needed
204
+ if @controller.respond_to?(:section=)
205
+ @controller.section = @current_template.dom_section
206
+ end
202
207
 
203
- def call_ready
204
- if @controller
205
- # Set the current section on the controller if it wants so it can manipulate
206
- # the dom if needed
207
- if @controller.respond_to?(:section=)
208
- @controller.section = @current_template.dom_section
208
+ controller_send(:"#{@action}_ready") if @action
209
209
  end
210
-
211
- controller_send(:"#{@action}_ready") if @action
212
210
  end
213
- end
214
211
 
215
- def remove
216
- clear_grouped_controller
212
+ def remove
213
+ clear_grouped_controller
217
214
 
218
- if @current_template
219
- # Remove the template if one has been rendered, when the template binding is
220
- # removed.
221
- @current_template.remove
222
- end
215
+ if @current_template
216
+ # Remove the template if one has been rendered, when the template binding is
217
+ # removed.
218
+ @current_template.remove
219
+ end
223
220
 
224
- super
221
+ super
225
222
 
226
- if @controller
227
- controller_send(:"#{@action}_removed") if @action
223
+ if @controller
224
+ controller_send(:"#{@action}_removed") if @action
228
225
 
229
- @controller = nil
226
+ @controller = nil
227
+ end
230
228
  end
231
- end
232
229
 
233
- private
230
+ private
234
231
  # Sends the action to the controller if it exists
235
232
  def controller_send(action_name)
236
233
  if @controller.respond_to?(action_name)
@@ -245,7 +242,7 @@ class TemplateBinding < BaseBinding
245
242
  action = controller_path[-1]
246
243
 
247
244
  # Get the constant parts
248
- parts = controller_path[0..-2].map {|v| v.gsub('-', '_').camelize }
245
+ parts = controller_path[0..-2].map { |v| v.gsub('-', '_').camelize }
249
246
 
250
247
  # Home doesn't get namespaced
251
248
  if parts.first == 'Main'
@@ -265,5 +262,5 @@ class TemplateBinding < BaseBinding
265
262
 
266
263
  return obj, action
267
264
  end
268
-
265
+ end
269
266
  end
@@ -4,101 +4,103 @@ require 'json'
4
4
  require 'volt/reactive/reactive_accessors'
5
5
  require 'volt/reactive/eventable'
6
6
 
7
- class Channel
8
- include ReactiveAccessors
9
- include Eventable
10
-
11
- reactive_accessor :connected, :status, :error, :reconnect_interval, :retry_count
7
+ module Volt
8
+ class Channel
9
+ include ReactiveAccessors
10
+ include Eventable
11
+
12
+ reactive_accessor :connected, :status, :error, :reconnect_interval, :retry_count
13
+
14
+ def initialize
15
+ @socket = nil
16
+ self.status = :opening
17
+ self.connected = false
18
+ self.error = nil
19
+ self.retry_count = 0
20
+ @queue = []
21
+
22
+ connect!
23
+ end
12
24
 
13
- def initialize
14
- @socket = nil
15
- self.status = :opening
16
- self.connected = false
17
- self.error = nil
18
- self.retry_count = 0
19
- @queue = []
25
+ def connected?
26
+ self.connected
27
+ end
20
28
 
21
- connect!
22
- end
29
+ def connect!
30
+ %x{
31
+ this.socket = new SockJS('/channel');
23
32
 
24
- def connected?
25
- self.connected
26
- end
33
+ this.socket.onopen = function() {
34
+ self.$opened();
35
+ };
27
36
 
28
- def connect!
29
- %x{
30
- this.socket = new SockJS('/channel');
37
+ this.socket.onmessage = function(message) {
38
+ self['$message_received'](message.data);
39
+ };
31
40
 
32
- this.socket.onopen = function() {
33
- self.$opened();
34
- };
41
+ this.socket.onclose = function(error) {
42
+ self.$closed(error);
43
+ };
44
+ }
45
+ end
35
46
 
36
- this.socket.onmessage = function(message) {
37
- self['$message_received'](message.data);
38
- };
47
+ def opened
48
+ old_status = @status
49
+ @status = :open
50
+ @connected = true
51
+ @reconnect_interval = nil
52
+ @retry_count = 0
53
+ @queue.each do |message|
54
+ send_message(message)
55
+ end
56
+ end
39
57
 
40
- this.socket.onclose = function(error) {
41
- self.$closed(error);
42
- };
43
- }
44
- end
58
+ def closed(error)
59
+ self.status = :closed
60
+ self.connected = false
61
+ self.error = `error.reason`
45
62
 
46
- def opened
47
- old_status = @status
48
- @status = :open
49
- @connected = true
50
- @reconnect_interval = nil
51
- @retry_count = 0
52
- @queue.each do |message|
53
- send_message(message)
63
+ reconnect!
54
64
  end
55
- end
56
65
 
57
- def closed(error)
58
- self.status = :closed
59
- self.connected = false
60
- self.error = `error.reason`
66
+ def reconnect!
67
+ self.status = :reconnecting
68
+ self.reconnect_interval ||= 0
69
+ self.reconnect_interval += (2000 + rand(5000))
70
+ self.retry_count += 1
61
71
 
62
- reconnect!
63
- end
64
-
65
- def reconnect!
66
- self.status = :reconnecting
67
- self.reconnect_interval ||= 0
68
- self.reconnect_interval += (2000 + rand(5000))
69
- self.retry_count += 1
72
+ interval = self.reconnect_interval
70
73
 
71
- interval = self.reconnect_interval
74
+ %x{
75
+ setTimeout(function() {
76
+ self['$connect!']();
77
+ }, interval);
78
+ }
79
+ end
72
80
 
73
- %x{
74
- setTimeout(function() {
75
- self['$connect!']();
76
- }, interval);
77
- }
78
- end
81
+ def message_received(message)
82
+ message = JSON.parse(message)
79
83
 
80
- def message_received(message)
81
- message = JSON.parse(message)
84
+ trigger!('message', *message)
85
+ end
82
86
 
83
- trigger!('message', *message)
84
- end
87
+ def send_message(message)
88
+ if self.status != :open
89
+ @queue << message
90
+ else
91
+ # TODO: Temp: wrap message in an array, so we're sure its valid JSON
92
+ message = JSON.dump([message])
93
+ %x{
94
+ this.socket.send(message);
95
+ }
96
+ end
97
+ end
85
98
 
86
- def send_message(message)
87
- if self.status != :open
88
- @queue << message
89
- else
90
- # TODO: Temp: wrap message in an array, so we're sure its valid JSON
91
- message = JSON.dump([message])
99
+ def close!
100
+ self.status = :closed
92
101
  %x{
93
- this.socket.send(message);
102
+ this.socket.close();
94
103
  }
95
104
  end
96
105
  end
97
-
98
- def close!
99
- self.status = :closed
100
- %x{
101
- this.socket.close();
102
- }
103
- end
104
106
  end
@@ -4,32 +4,34 @@
4
4
  require 'volt/tasks/dispatcher'
5
5
  require 'volt/reactive/eventable'
6
6
 
7
- # Behaves the same as the Channel class, only the Channel class uses
8
- # sockjs to pass messages to the backend. ChannelStub, simply passes
9
- # them directly to SocketConnectionHandlerStub.
10
- class ChannelStub
11
- include Eventable
12
-
13
- attr_reader :state, :error, :reconnect_interval
14
-
15
- def initiailze
16
- @state = :connected
17
- end
18
-
19
- def opened
20
- trigger!('open')
21
- trigger!('changed')
22
- end
23
-
24
- def message_received(*message)
25
- trigger!('message', *message)
26
- end
27
-
28
- def send_message(message)
29
- SocketConnectionHandlerStub.new(self).process_message(message)
30
- end
31
-
32
- def close!
33
- raise "close! should not be called on the backend channel"
7
+ module Volt
8
+ # Behaves the same as the Channel class, only the Channel class uses
9
+ # sockjs to pass messages to the backend. ChannelStub, simply passes
10
+ # them directly to SocketConnectionHandlerStub.
11
+ class ChannelStub
12
+ include Eventable
13
+
14
+ attr_reader :state, :error, :reconnect_interval
15
+
16
+ def initiailze
17
+ @state = :connected
18
+ end
19
+
20
+ def opened
21
+ trigger!('open')
22
+ trigger!('changed')
23
+ end
24
+
25
+ def message_received(*message)
26
+ trigger!('message', *message)
27
+ end
28
+
29
+ def send_message(message)
30
+ SocketConnectionHandlerStub.new(self).process_message(message)
31
+ end
32
+
33
+ def close!
34
+ raise "close! should not be called on the backend channel"
35
+ end
34
36
  end
35
37
  end