volt 0.6.5 → 0.7.0
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/Readme.md +47 -40
- data/VERSION +1 -1
- data/app/volt/controllers/notices_controller.rb +3 -3
- data/app/volt/tasks/live_query/data_store.rb +2 -2
- data/app/volt/tasks/live_query/live_query.rb +20 -20
- data/app/volt/tasks/live_query/live_query_pool.rb +6 -6
- data/app/volt/tasks/live_query/query_tracker.rb +15 -15
- data/app/volt/tasks/query_tasks.rb +13 -13
- data/app/volt/tasks/store_tasks.rb +7 -7
- data/app/volt/views/notices/index.html +17 -18
- data/lib/volt/assets/test.rb +2 -2
- data/lib/volt/benchmark/benchmark.rb +25 -23
- data/lib/volt/cli/asset_compile.rb +11 -0
- data/lib/volt/cli/new_gem.rb +16 -16
- data/lib/volt/cli.rb +14 -12
- data/lib/volt/console.rb +5 -6
- data/lib/volt/controllers/model_controller.rb +18 -18
- data/lib/volt/extra_core/array.rb +4 -4
- data/lib/volt/extra_core/hash.rb +3 -3
- data/lib/volt/extra_core/object.rb +6 -6
- data/lib/volt/extra_core/string.rb +6 -6
- data/lib/volt/extra_core/symbol.rb +5 -5
- data/lib/volt/extra_core/time.rb +4 -4
- data/lib/volt/extra_core/true_false.rb +6 -6
- data/lib/volt/extra_core/try.rb +9 -9
- data/lib/volt/models/array_model.rb +26 -26
- data/lib/volt/models/model.rb +35 -35
- data/lib/volt/models/model_hash_behaviour.rb +15 -15
- data/lib/volt/models/model_helpers.rb +8 -8
- data/lib/volt/models/model_wrapper.rb +6 -6
- data/lib/volt/models/persistors/array_store.rb +36 -36
- data/lib/volt/models/persistors/base.rb +6 -6
- data/lib/volt/models/persistors/flash.rb +5 -5
- data/lib/volt/models/persistors/model_identity_map.rb +2 -2
- data/lib/volt/models/persistors/model_store.rb +22 -22
- data/lib/volt/models/persistors/params.rb +3 -3
- data/lib/volt/models/persistors/query/query_listener.rb +14 -14
- data/lib/volt/models/persistors/query/query_listener_pool.rb +2 -2
- data/lib/volt/models/persistors/store.rb +8 -8
- data/lib/volt/models/persistors/store_factory.rb +2 -2
- data/lib/volt/models/url.rb +37 -37
- data/lib/volt/page/bindings/attribute_binding.rb +14 -14
- data/lib/volt/page/bindings/base_binding.rb +9 -9
- data/lib/volt/page/bindings/component_binding.rb +7 -7
- data/lib/volt/page/bindings/content_binding.rb +3 -3
- data/lib/volt/page/bindings/each_binding.rb +13 -13
- data/lib/volt/page/bindings/event_binding.rb +4 -4
- data/lib/volt/page/bindings/if_binding.rb +12 -12
- data/lib/volt/page/bindings/template_binding.rb +30 -30
- data/lib/volt/page/channel.rb +19 -19
- data/lib/volt/page/channel_stub.rb +6 -6
- data/lib/volt/page/document.rb +2 -2
- data/lib/volt/page/document_events.rb +4 -4
- data/lib/volt/page/draw_cycle.rb +3 -3
- data/lib/volt/page/memory_test.rb +6 -6
- data/lib/volt/page/page.rb +19 -19
- data/lib/volt/page/reactive_template.rb +9 -9
- data/lib/volt/page/sub_context.rb +5 -5
- data/lib/volt/page/targets/attribute_section.rb +9 -9
- data/lib/volt/page/targets/attribute_target.rb +3 -3
- data/lib/volt/page/targets/base_section.rb +2 -2
- data/lib/volt/page/targets/binding_document/component_node.rb +23 -23
- data/lib/volt/page/targets/binding_document/html_node.rb +2 -2
- data/lib/volt/page/targets/dom_section.rb +40 -38
- data/lib/volt/page/targets/dom_target.rb +2 -2
- data/lib/volt/page/tasks.rb +12 -12
- data/lib/volt/page/template_renderer.rb +4 -4
- data/lib/volt/page/url_tracker.rb +6 -6
- data/lib/volt/reactive/array_extensions.rb +2 -2
- data/lib/volt/reactive/destructive_methods.rb +5 -5
- data/lib/volt/reactive/event_chain.rb +25 -25
- data/lib/volt/reactive/events.rb +33 -33
- data/lib/volt/reactive/object_tracker.rb +21 -21
- data/lib/volt/reactive/object_tracking.rb +2 -2
- data/lib/volt/reactive/reactive_array.rb +57 -57
- data/lib/volt/reactive/reactive_tags.rb +16 -16
- data/lib/volt/reactive/reactive_value.rb +72 -72
- data/lib/volt/reactive/string_extensions.rb +3 -3
- data/lib/volt/router/routes.rb +22 -23
- data/lib/volt/server/component_handler.rb +5 -5
- data/lib/volt/server/component_templates.rb +14 -11
- data/lib/volt/server/html_parser/attribute_scope.rb +116 -0
- data/lib/volt/server/html_parser/each_scope.rb +18 -0
- data/lib/volt/server/html_parser/if_view_scope.rb +71 -0
- data/lib/volt/server/html_parser/sandlebars_parser.rb +219 -0
- data/lib/volt/server/html_parser/textarea_scope.rb +31 -0
- data/lib/volt/server/html_parser/view_handler.rb +82 -0
- data/lib/volt/server/html_parser/view_parser.rb +23 -0
- data/lib/volt/server/html_parser/view_scope.rb +145 -0
- data/lib/volt/server/rack/asset_files.rb +17 -17
- data/lib/volt/server/rack/component_paths.rb +18 -18
- data/lib/volt/server/rack/index_files.rb +8 -8
- data/lib/volt/server/rack/opal_files.rb +11 -11
- data/lib/volt/server/socket_connection_handler.rb +13 -13
- data/lib/volt/server/socket_connection_handler_stub.rb +2 -2
- data/lib/volt/server.rb +18 -18
- data/lib/volt/tasks/dispatcher.rb +5 -5
- data/lib/volt/utils/ejson.rb +2 -2
- data/lib/volt/utils/generic_counting_pool.rb +8 -8
- data/lib/volt/utils/generic_pool.rb +16 -16
- data/lib/volt/volt/environment.rb +4 -4
- data/lib/volt.rb +6 -6
- data/spec/integration/test_integration_spec.rb +2 -2
- data/spec/models/event_chain_spec.rb +38 -38
- data/spec/models/model_spec.rb +128 -128
- data/spec/models/old_model_spec.rb +17 -17
- data/spec/models/persistors/params_spec.rb +3 -3
- data/spec/models/persistors/store_spec.rb +7 -7
- data/spec/models/reactive_array_spec.rb +82 -82
- data/spec/models/reactive_generator_spec.rb +11 -11
- data/spec/models/reactive_tags_spec.rb +6 -6
- data/spec/models/reactive_value_spec.rb +70 -70
- data/spec/models/store_spec.rb +4 -4
- data/spec/models/string_extensions_spec.rb +13 -13
- data/spec/page/bindings/content_binding_spec.rb +6 -6
- data/spec/page/sub_context_spec.rb +1 -1
- data/spec/router/routes_spec.rb +3 -3
- data/spec/server/html_parser/sample_page.html +595 -0
- data/spec/server/html_parser/sandlebars_parser_spec.rb +192 -0
- data/spec/server/html_parser/view_parser_spec.rb +286 -0
- data/spec/server/rack/asset_files_spec.rb +6 -6
- data/spec/server/rack/component_paths_spec.rb +5 -5
- data/spec/spec_helper.rb +4 -5
- data/spec/store/mongo_spec.rb +3 -3
- data/spec/tasks/live_query_spec.rb +6 -6
- data/spec/tasks/query_tasks.rb +4 -4
- data/spec/tasks/query_tracker_spec.rb +20 -20
- data/spec/templates/targets/binding_document/component_node_spec.rb +4 -4
- data/spec/templates/template_binding_spec.rb +28 -28
- data/spec/utils/generic_counting_pool_spec.rb +5 -5
- data/spec/utils/generic_pool_spec.rb +14 -14
- data/templates/newgem/app/newgem/views/index/index.html +1 -2
- data/templates/project/app/home/config/dependencies.rb +1 -1
- data/templates/project/app/home/controllers/index_controller.rb +1 -1
- data/templates/project/app/home/views/index/about.html +4 -6
- data/templates/project/app/home/views/index/home.html +4 -5
- data/templates/project/app/home/views/index/index.html +8 -9
- data/templates/project/spec/spec_helper.rb +1 -1
- metadata +17 -8
- data/lib/volt/server/binding_setup.rb +0 -2
- data/lib/volt/server/if_binding_setup.rb +0 -31
- data/lib/volt/server/scope.rb +0 -43
- data/lib/volt/server/template_parser.rb +0 -453
- data/spec/server/template_parser_spec.rb +0 -50
|
@@ -10,7 +10,7 @@ class Object
|
|
|
10
10
|
def cur
|
|
11
11
|
self
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def reactive?
|
|
15
15
|
false
|
|
16
16
|
end
|
|
@@ -20,7 +20,7 @@ class ReactiveValue < BasicObject
|
|
|
20
20
|
# methods on ReactiveValues:
|
|
21
21
|
# reactive?, cur, with, on, data, trigger!
|
|
22
22
|
# - everything else is forwarded to the ReactiveManager
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# Methods we should skip wrapping the results in
|
|
25
25
|
# We skip .hash because in uniq it has .to_int called on it, which needs to
|
|
26
26
|
# return a Fixnum instance.
|
|
@@ -34,11 +34,11 @@ class ReactiveValue < BasicObject
|
|
|
34
34
|
def initialize(getter, setter=nil, scope=nil)
|
|
35
35
|
@reactive_manager = ::ReactiveManager.new(getter, setter, scope)
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
def reactive?
|
|
39
39
|
true
|
|
40
40
|
end
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
# Proxy methods to the ReactiveManager. We want to have as few
|
|
43
43
|
# as possible methods on reactive values, so all other methods
|
|
44
44
|
# are forwarded to the object the reactive value points to.
|
|
@@ -47,16 +47,16 @@ class ReactiveValue < BasicObject
|
|
|
47
47
|
@reactive_manager.send(method_name, *args, &block)
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
def reactive_manager
|
|
52
52
|
@reactive_manager
|
|
53
53
|
end
|
|
54
|
-
alias_method :rm, :reactive_manager
|
|
55
|
-
|
|
54
|
+
alias_method :rm, :reactive_manager
|
|
55
|
+
|
|
56
56
|
def puts(*args)
|
|
57
57
|
::Object.send(:puts, *args)
|
|
58
58
|
end
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
def __is_destructive?(method_name)
|
|
61
61
|
last_char = method_name[-1]
|
|
62
62
|
if last_char == '=' && method_name[-2] != '='
|
|
@@ -73,7 +73,7 @@ class ReactiveValue < BasicObject
|
|
|
73
73
|
return false
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
def method_missing(method_name, *args, &block)
|
|
78
78
|
# Unroll send into a direct call
|
|
79
79
|
if method_name == :send
|
|
@@ -85,13 +85,13 @@ class ReactiveValue < BasicObject
|
|
|
85
85
|
# Also skip if this is a destructive method
|
|
86
86
|
if SKIP_METHODS.include?(method_name) || __is_destructive?(method_name)
|
|
87
87
|
current_obj = self.cur
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
# Unwrap arguments if the method doesn't want reactive values
|
|
90
90
|
pass_args = reactive_manager.unwrap_if_pass_reactive(args, method_name, current_obj)
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
return current_obj.__send__(method_name, *pass_args, &block)
|
|
93
93
|
end
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
result = @reactive_manager.with_and_options(args) do |val, in_args|
|
|
96
96
|
# Unwrap arguments if the method doesn't want reactive values
|
|
97
97
|
# TODO: Should cache the lookup on pass_reactive
|
|
@@ -100,18 +100,18 @@ class ReactiveValue < BasicObject
|
|
|
100
100
|
# puts "GET #{method_name.inspect}"
|
|
101
101
|
val.__send__(method_name, *pass_args, &block)
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
manager = result.reactive_manager
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
setup_setter(manager, method_name, args)
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
manager.set_scope!([method_name, *args, block])
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
# result = result.with(block_reactives) if block
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
return result
|
|
113
113
|
end
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
def setup_setter(manager, method_name, args)
|
|
116
116
|
# See if we can automatically create a setter. If we are fetching a
|
|
117
117
|
# value via a read, we can probably reassign it with .name=
|
|
@@ -126,30 +126,30 @@ class ReactiveValue < BasicObject
|
|
|
126
126
|
manager.setter! do |val|
|
|
127
127
|
# Call an array setter
|
|
128
128
|
self.cur.send(:"#{method_name}=", args[0], val)
|
|
129
|
-
end
|
|
129
|
+
end
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
|
-
#
|
|
132
|
+
#
|
|
133
133
|
# def respond_to?(name, include_private=false)
|
|
134
134
|
# [:event_added, :event_removed].include?(name) || super
|
|
135
135
|
# end
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
def respond_to_missing?(name, include_private=false)
|
|
138
138
|
cur.respond_to?(name)
|
|
139
139
|
end
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
def with(*args, &block)
|
|
142
142
|
return @reactive_manager.with(*args, &block)
|
|
143
143
|
end
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
def inspect
|
|
146
146
|
"@#{cur.inspect}"
|
|
147
147
|
end
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
def pretty_inspect
|
|
150
150
|
inspect
|
|
151
151
|
end
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
# Not 100% sure why, but we need to define this directly, it doesn't call
|
|
154
154
|
# on method missing
|
|
155
155
|
def ==(val)
|
|
@@ -160,11 +160,11 @@ class ReactiveValue < BasicObject
|
|
|
160
160
|
def !
|
|
161
161
|
method_missing(:!)
|
|
162
162
|
end
|
|
163
|
-
|
|
163
|
+
|
|
164
164
|
def to_s
|
|
165
165
|
cur.to_s
|
|
166
166
|
end
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
def coerce(other)
|
|
169
169
|
if other.reactive?
|
|
170
170
|
return [other, self]
|
|
@@ -173,7 +173,7 @@ class ReactiveValue < BasicObject
|
|
|
173
173
|
return [wrapped_object, self]
|
|
174
174
|
end
|
|
175
175
|
end
|
|
176
|
-
|
|
176
|
+
|
|
177
177
|
# Return a new reactive value that listens for changes on any
|
|
178
178
|
# ReactiveValues inside of its children (hash values, array items, etc..)
|
|
179
179
|
# This is useful if someone is passing in a set of options, but the main
|
|
@@ -192,7 +192,7 @@ class ReactiveGenerator
|
|
|
192
192
|
# any ReactiveValue's inside of the hash (or children).
|
|
193
193
|
def self.from_hash(hash, skip_if_no_reactives=false)
|
|
194
194
|
reactives = find_reactives(hash)
|
|
195
|
-
|
|
195
|
+
|
|
196
196
|
if skip_if_no_reactives && reactives.size == 0
|
|
197
197
|
# There weren't any reactives, we can just use the hash
|
|
198
198
|
return hash
|
|
@@ -200,11 +200,11 @@ class ReactiveGenerator
|
|
|
200
200
|
# Create a new reactive value that listens on all of its
|
|
201
201
|
# child reactive values.
|
|
202
202
|
value = ReactiveValue.new(hash)
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
reactives.each do |child|
|
|
205
205
|
value.reactive_manager.add_parent!(child)
|
|
206
206
|
end
|
|
207
|
-
|
|
207
|
+
|
|
208
208
|
return value
|
|
209
209
|
end
|
|
210
210
|
end
|
|
@@ -215,7 +215,7 @@ class ReactiveGenerator
|
|
|
215
215
|
found = []
|
|
216
216
|
if object.reactive?
|
|
217
217
|
found << object
|
|
218
|
-
|
|
218
|
+
|
|
219
219
|
found += find_reactives(object.cur)
|
|
220
220
|
elsif object.is_a?(Array)
|
|
221
221
|
object.each do |item|
|
|
@@ -227,50 +227,50 @@ class ReactiveGenerator
|
|
|
227
227
|
found += find_reactives(value)
|
|
228
228
|
end
|
|
229
229
|
end
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
return found.flatten
|
|
232
232
|
end
|
|
233
233
|
end
|
|
234
234
|
|
|
235
235
|
class ReactiveManager
|
|
236
236
|
include ::Events
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
attr_reader :scope, :parents
|
|
239
|
-
|
|
239
|
+
|
|
240
240
|
# When created, ReactiveValue's get a getter (a proc)
|
|
241
241
|
def initialize(getter, setter=nil, scope=nil)
|
|
242
242
|
@getter = getter
|
|
243
243
|
@setter = setter
|
|
244
244
|
@scope = scope
|
|
245
|
-
|
|
245
|
+
|
|
246
246
|
@parents = []
|
|
247
247
|
end
|
|
248
|
-
|
|
248
|
+
|
|
249
249
|
def reactive?
|
|
250
250
|
true
|
|
251
251
|
end
|
|
252
|
-
|
|
252
|
+
|
|
253
253
|
def inspect
|
|
254
254
|
"@<#{self.class.to_s}:#{reactive_object_id} #{cur.inspect}>"
|
|
255
255
|
end
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
def reactive_object_id
|
|
258
258
|
@reactive_object_id ||= rand(100000)
|
|
259
259
|
end
|
|
260
|
-
|
|
261
|
-
|
|
260
|
+
|
|
261
|
+
|
|
262
262
|
def event_added(event, scope, first)
|
|
263
263
|
# When the first event is registered, we need to start listening on our current object
|
|
264
264
|
# for it to publish events.
|
|
265
265
|
object_tracker.enable! if first
|
|
266
266
|
end
|
|
267
|
-
|
|
267
|
+
|
|
268
268
|
def event_removed(event, last)
|
|
269
269
|
# If no one is listening on the reactive value, then we don't need to listen on our
|
|
270
270
|
# current object for events, because no one cares.
|
|
271
271
|
object_tracker.disable! if @listeners.size == 0
|
|
272
272
|
end
|
|
273
|
-
|
|
273
|
+
|
|
274
274
|
def object_tracker
|
|
275
275
|
@object_tracker ||= ::ObjectTracker.new(self)
|
|
276
276
|
end
|
|
@@ -284,7 +284,7 @@ class ReactiveManager
|
|
|
284
284
|
# if ObjectTracker.cache_version == @cached_version
|
|
285
285
|
# return @cached_obj
|
|
286
286
|
# end
|
|
287
|
-
|
|
287
|
+
|
|
288
288
|
if @getter.class == ::Proc
|
|
289
289
|
# Get the current value, capture any errors
|
|
290
290
|
begin
|
|
@@ -296,33 +296,33 @@ class ReactiveManager
|
|
|
296
296
|
# getter is just an object, return it
|
|
297
297
|
result = @getter
|
|
298
298
|
end
|
|
299
|
-
|
|
299
|
+
|
|
300
300
|
if result.reactive?
|
|
301
301
|
# Unwrap any stored reactive values
|
|
302
302
|
result = result.cur
|
|
303
303
|
end
|
|
304
|
-
|
|
304
|
+
|
|
305
305
|
# if ObjectTracker.cache_enabled
|
|
306
306
|
# @cached_obj = result
|
|
307
307
|
# @cached_version = ObjectTracker.cache_version
|
|
308
308
|
# end
|
|
309
|
-
|
|
309
|
+
|
|
310
310
|
return result
|
|
311
311
|
end
|
|
312
|
-
|
|
312
|
+
|
|
313
313
|
def cur=(val)
|
|
314
314
|
if @setter
|
|
315
315
|
@setter.call(val)
|
|
316
316
|
elsif @scope == nil
|
|
317
317
|
@getter = val
|
|
318
318
|
@setter = nil
|
|
319
|
-
|
|
319
|
+
|
|
320
320
|
trigger!('changed')
|
|
321
321
|
else
|
|
322
322
|
raise "Value can not be updated"
|
|
323
323
|
end
|
|
324
324
|
end
|
|
325
|
-
|
|
325
|
+
|
|
326
326
|
# Returns a copy of the object with where all ReactiveValue's are replaced
|
|
327
327
|
# with their current value.
|
|
328
328
|
# NOTE: Classes need to implement their own deep_cur method for this to work,
|
|
@@ -330,28 +330,28 @@ class ReactiveManager
|
|
|
330
330
|
def deep_cur
|
|
331
331
|
self.cur.deep_cur
|
|
332
332
|
end
|
|
333
|
-
|
|
333
|
+
|
|
334
334
|
# Method calls can be tagged so the reactive value knows
|
|
335
335
|
# how to handle them. This lets you check the state of
|
|
336
336
|
# the tags.
|
|
337
337
|
def check_tag(method_name, tag_name, current_obj)
|
|
338
338
|
if current_obj.respond_to?(:reactive_method_tag)
|
|
339
339
|
tag = current_obj.reactive_method_tag(method_name, tag_name)
|
|
340
|
-
|
|
340
|
+
|
|
341
341
|
unless tag
|
|
342
342
|
# Get the tag from the all methods if its not directly specified
|
|
343
343
|
tag = current_obj.reactive_method_tag(:__all_methods, tag_name)
|
|
344
344
|
end
|
|
345
|
-
|
|
345
|
+
|
|
346
346
|
# Evaluate now if its a proc
|
|
347
347
|
tag = tag.call(method_name) if tag.class == ::Proc
|
|
348
|
-
|
|
348
|
+
|
|
349
349
|
return tag
|
|
350
350
|
end
|
|
351
|
-
|
|
351
|
+
|
|
352
352
|
return nil
|
|
353
353
|
end
|
|
354
|
-
|
|
354
|
+
|
|
355
355
|
def unwrap_if_pass_reactive(args, method_name, current_obj)
|
|
356
356
|
# Check to see if the method we're calling wants to receive reactive values.
|
|
357
357
|
pass_reactive = check_tag(method_name, :pass_reactive, current_obj)
|
|
@@ -359,33 +359,33 @@ class ReactiveManager
|
|
|
359
359
|
# Unwrap arguments if the method doesn't want reactive values
|
|
360
360
|
return pass_reactive ? args : args.map{|v| v.cur }
|
|
361
361
|
end
|
|
362
|
-
|
|
362
|
+
|
|
363
363
|
# With returns a new reactive value dependent on any arguments passed in.
|
|
364
364
|
# If a block is passed in, the getter is the block its self, which will
|
|
365
365
|
# be passed the .cur and the .cur of any reactive arguments.
|
|
366
366
|
def with(*args, &block)
|
|
367
367
|
return with_and_options(args, &block)
|
|
368
368
|
end
|
|
369
|
-
|
|
369
|
+
|
|
370
370
|
def with_and_options(args, &block)
|
|
371
371
|
getter = @getter
|
|
372
372
|
setter = @setter
|
|
373
373
|
scope = @scope
|
|
374
|
-
|
|
374
|
+
|
|
375
375
|
if block
|
|
376
376
|
# If a block was passed in, the getter now becomes a proc that calls
|
|
377
377
|
# the passed in block with the right arguments.
|
|
378
|
-
getter = ::Proc.new do
|
|
378
|
+
getter = ::Proc.new do
|
|
379
379
|
# TODO: Calling cur every time
|
|
380
380
|
current_val = self.cur
|
|
381
|
-
|
|
381
|
+
|
|
382
382
|
if current_val.is_a?(Exception)
|
|
383
383
|
current_val
|
|
384
384
|
else
|
|
385
385
|
block.call(current_val, args)
|
|
386
386
|
end
|
|
387
387
|
end
|
|
388
|
-
|
|
388
|
+
|
|
389
389
|
# TODO: Make this work with custom setters
|
|
390
390
|
setter = nil
|
|
391
391
|
|
|
@@ -393,9 +393,9 @@ class ReactiveManager
|
|
|
393
393
|
# method because we don't know enough about what methods its calling.
|
|
394
394
|
scope = nil
|
|
395
395
|
end
|
|
396
|
-
|
|
396
|
+
|
|
397
397
|
new_val = ReactiveValue.new(getter, setter, scope)
|
|
398
|
-
|
|
398
|
+
|
|
399
399
|
# Add the ReactiveValue we're building from
|
|
400
400
|
new_val.reactive_manager.add_parent!(self)
|
|
401
401
|
|
|
@@ -403,34 +403,34 @@ class ReactiveManager
|
|
|
403
403
|
args.select(&:reactive?).each do |arg|
|
|
404
404
|
new_val.reactive_manager.add_parent!(arg.reactive_manager)
|
|
405
405
|
end
|
|
406
|
-
|
|
406
|
+
|
|
407
407
|
return new_val
|
|
408
408
|
end
|
|
409
|
-
|
|
409
|
+
|
|
410
410
|
def add_parent!(parent)
|
|
411
411
|
@parents << parent
|
|
412
412
|
event_chain.add_object(parent)
|
|
413
413
|
end
|
|
414
|
-
|
|
414
|
+
|
|
415
415
|
def remove_parent!(parent)
|
|
416
416
|
@parents.delete(parent)
|
|
417
417
|
event_chain.remove_object(parent)
|
|
418
418
|
end
|
|
419
419
|
|
|
420
|
-
|
|
420
|
+
|
|
421
421
|
def set_scope!(new_scope)
|
|
422
422
|
@scope = new_scope
|
|
423
|
-
|
|
423
|
+
|
|
424
424
|
self
|
|
425
425
|
end
|
|
426
|
-
|
|
426
|
+
|
|
427
427
|
def set_scope(new_scope)
|
|
428
428
|
dup.scope!(new_scope)
|
|
429
429
|
end
|
|
430
|
-
|
|
430
|
+
|
|
431
431
|
# Sets the setter
|
|
432
432
|
def setter!(setter=nil, &block)
|
|
433
433
|
@setter = setter || block
|
|
434
434
|
end
|
|
435
435
|
|
|
436
|
-
end
|
|
436
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class String
|
|
2
2
|
include ReactiveTags
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
alias :__old_plus :+
|
|
5
5
|
if RUBY_PLATFORM != 'opal'
|
|
6
6
|
alias :__old_concat :<<
|
|
@@ -14,7 +14,7 @@ class String
|
|
|
14
14
|
if val.reactive? && !result.reactive?
|
|
15
15
|
result = ReactiveValue.new(result)
|
|
16
16
|
end
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
return result
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -24,7 +24,7 @@ class String
|
|
|
24
24
|
raise "Cannot append a reactive string to non-reactive string. Use + instead"
|
|
25
25
|
end
|
|
26
26
|
result = __old_concat(val)
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
return result
|
|
29
29
|
end
|
|
30
30
|
end
|
data/lib/volt/router/routes.rb
CHANGED
|
@@ -5,18 +5,18 @@ class Routes
|
|
|
5
5
|
|
|
6
6
|
def initialize
|
|
7
7
|
@routes = []
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
if Volt.server?
|
|
10
10
|
@path_matchers = []
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def define(&block)
|
|
15
15
|
instance_eval(&block)
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
return self
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def get(path, options={})
|
|
21
21
|
if path.index('{') && path.index('}')
|
|
22
22
|
# The path contains bindings.
|
|
@@ -24,10 +24,10 @@ class Routes
|
|
|
24
24
|
else
|
|
25
25
|
add_path_matcher([path]) if Volt.server?
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
@routes << [path, options]
|
|
29
29
|
end
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
# Takes the path and splits it up into sections around any
|
|
32
32
|
# bindings in the path. Those are then used to create a proc
|
|
33
33
|
# that will return the path with the current params in it.
|
|
@@ -35,15 +35,15 @@ class Routes
|
|
|
35
35
|
def build_path_matcher(path, options)
|
|
36
36
|
sections = path.split(/(\{[^\}]+\})/)
|
|
37
37
|
sections = sections.reject {|v| v == '' }
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
sections.each do |section|
|
|
40
40
|
if section[0] == '{' && section[-1] == '}'
|
|
41
41
|
options[section[1..-2]] = nil
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
add_path_matcher(sections) if Volt.server?
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
# Create a path that takes in the params and returns the main
|
|
48
48
|
# part of the url with the params filled in.
|
|
49
49
|
path = Proc.new do |params|
|
|
@@ -55,7 +55,7 @@ class Routes
|
|
|
55
55
|
end
|
|
56
56
|
end.join('')
|
|
57
57
|
end
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
return path
|
|
60
60
|
end
|
|
61
61
|
|
|
@@ -69,19 +69,19 @@ class Routes
|
|
|
69
69
|
match_path = match_path + section
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
@path_matchers << (/^#{match_path}$/)
|
|
74
74
|
end
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
# Takes in params and generates a path and the remaining params
|
|
77
77
|
# that should be shown in the url.
|
|
78
|
-
def url_for_params(params)
|
|
78
|
+
def url_for_params(params)
|
|
79
79
|
routes.each do |route|
|
|
80
80
|
if params_match_options?(params, route[1])
|
|
81
81
|
return path_and_params(params, route[0], route[1])
|
|
82
82
|
end
|
|
83
83
|
end
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
return '/', params
|
|
86
86
|
end
|
|
87
87
|
|
|
@@ -92,30 +92,29 @@ class Routes
|
|
|
92
92
|
# TODO: Finish nested routes
|
|
93
93
|
if false && route[0].class == Proc
|
|
94
94
|
# puts route[0].call(params).inspect
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
return false
|
|
97
97
|
elsif route[0] == path
|
|
98
98
|
# Found the matching route
|
|
99
99
|
return route[1]
|
|
100
100
|
end
|
|
101
101
|
end
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
return {}
|
|
104
104
|
end
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
private
|
|
107
107
|
def path_and_params(params, path, options)
|
|
108
108
|
params = params.attributes.dup
|
|
109
|
-
puts params.inspect if path.class == Proc
|
|
110
109
|
path = path.call(params) if path.class == Proc
|
|
111
|
-
|
|
110
|
+
|
|
112
111
|
options.keys.each do |key|
|
|
113
112
|
params.delete(key)
|
|
114
113
|
end
|
|
115
|
-
|
|
114
|
+
|
|
116
115
|
return path, params
|
|
117
116
|
end
|
|
118
|
-
|
|
117
|
+
|
|
119
118
|
# Match one route against the current params.
|
|
120
119
|
def params_match_options?(params, options)
|
|
121
120
|
options.each_pair do |key, value|
|
|
@@ -136,7 +135,7 @@ class Routes
|
|
|
136
135
|
return false
|
|
137
136
|
end
|
|
138
137
|
end
|
|
139
|
-
|
|
138
|
+
|
|
140
139
|
return true
|
|
141
140
|
end
|
|
142
|
-
end
|
|
141
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'stringio'
|
|
2
2
|
require 'volt'
|
|
3
|
-
require 'volt/server/
|
|
3
|
+
require 'volt/server/html_parser/view_parser'
|
|
4
4
|
require 'volt/server/component_templates'
|
|
5
5
|
require 'volt/server/rack/asset_files'
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ class ComponentHandler
|
|
|
8
8
|
def initialize(component_paths)
|
|
9
9
|
@component_paths = component_paths
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def call(env)
|
|
13
13
|
req = Rack::Request.new(env)
|
|
14
14
|
|
|
@@ -16,13 +16,13 @@ class ComponentHandler
|
|
|
16
16
|
component_name = req.path.strip.gsub(/^\/components\//, '').gsub(/[.]js$/, '')
|
|
17
17
|
|
|
18
18
|
code = ''
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
asset_files = AssetFiles.new(component_name, @component_paths)
|
|
21
21
|
asset_files.component_paths.each do |component_path, component_name|
|
|
22
22
|
code << ComponentTemplates.new(component_path, component_name).code
|
|
23
23
|
code << "\n\n"
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
javascript_code = Opal.compile(code)
|
|
27
27
|
|
|
28
28
|
# puts "ENV: #{env.inspect}"
|
|
@@ -30,4 +30,4 @@ class ComponentHandler
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
end
|
|
33
|
+
end
|
|
@@ -5,11 +5,11 @@ class ComponentTemplates
|
|
|
5
5
|
@component_path = component_path
|
|
6
6
|
@component_name = component_name
|
|
7
7
|
end
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
def code
|
|
10
10
|
return generate_controller_code + generate_view_code + generate_model_code + generate_routes_code
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
def generate_view_code
|
|
14
14
|
code = ''
|
|
15
15
|
views_path = "#{@component_path}/views/"
|
|
@@ -20,14 +20,17 @@ class ComponentTemplates
|
|
|
20
20
|
template_path = view_path[views_path.size..((-1 * ('.html'.size + 1)))]
|
|
21
21
|
template_path = "#{@component_name}/#{template_path}"
|
|
22
22
|
|
|
23
|
-
all_templates = TemplateParser.new(File.read(view_path), template_path)
|
|
23
|
+
# all_templates = TemplateParser.new(File.read(view_path), template_path)
|
|
24
|
+
all_templates = ViewParser.new(File.read(view_path), template_path)
|
|
24
25
|
|
|
25
26
|
binding_initializers = []
|
|
26
27
|
all_templates.templates.each_pair do |name, template|
|
|
27
28
|
binding_code = []
|
|
28
29
|
|
|
29
|
-
template['bindings']
|
|
30
|
-
|
|
30
|
+
if template['bindings']
|
|
31
|
+
template['bindings'].each_pair do |key,value|
|
|
32
|
+
binding_code << "#{key.inspect} => [#{value.join(', ')}]"
|
|
33
|
+
end
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
binding_code = "{#{binding_code.join(', ')}}"
|
|
@@ -51,26 +54,26 @@ class ComponentTemplates
|
|
|
51
54
|
|
|
52
55
|
return code
|
|
53
56
|
end
|
|
54
|
-
|
|
57
|
+
|
|
55
58
|
def generate_model_code
|
|
56
59
|
code = ''
|
|
57
60
|
models_path = "#{@component_path}/models/"
|
|
58
61
|
|
|
59
62
|
Dir["#{models_path}*.rb"].sort.each do |model_path|
|
|
60
63
|
code << File.read(model_path) + "\n\n"
|
|
61
|
-
|
|
64
|
+
|
|
62
65
|
model_name = model_path.match(/([^\/]+)[.]rb$/)[1]
|
|
63
|
-
|
|
66
|
+
|
|
64
67
|
code << "$page.add_model(#{model_name.inspect})\n\n"
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
return code
|
|
68
71
|
end
|
|
69
|
-
|
|
72
|
+
|
|
70
73
|
def generate_routes_code
|
|
71
74
|
code = ''
|
|
72
75
|
routes_path = "#{@component_path}/config/routes.rb"
|
|
73
|
-
|
|
76
|
+
|
|
74
77
|
if File.exists?(routes_path)
|
|
75
78
|
code << "$page.add_routes do\n"
|
|
76
79
|
code << "\n" + File.read(routes_path) + "\n"
|
|
@@ -79,4 +82,4 @@ class ComponentTemplates
|
|
|
79
82
|
|
|
80
83
|
return code
|
|
81
84
|
end
|
|
82
|
-
end
|
|
85
|
+
end
|