volt 0.6.5 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -5,25 +5,25 @@ class AssetFiles
|
|
5
5
|
@assets = []
|
6
6
|
@included_components = {}
|
7
7
|
@components = []
|
8
|
-
|
8
|
+
|
9
9
|
component('volt')
|
10
10
|
component(component_name)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def load_dependencies(path)
|
14
14
|
if path
|
15
15
|
dependencies_file = File.join(path, "config/dependencies.rb")
|
16
16
|
else
|
17
17
|
raise "Unable to find component #{component_name.inspect}"
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
if File.exists?(dependencies_file)
|
21
21
|
# Run the dependencies file in this asset files context
|
22
22
|
code = File.read(dependencies_file)
|
23
23
|
instance_eval(code)
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def component(name)
|
28
28
|
unless @included_components[name]
|
29
29
|
# Get the path to the component
|
@@ -34,17 +34,17 @@ class AssetFiles
|
|
34
34
|
|
35
35
|
# Load the dependencies
|
36
36
|
load_dependencies(path)
|
37
|
-
|
37
|
+
|
38
38
|
# Add any assets
|
39
39
|
add_assets(path)
|
40
40
|
@components << [path, name]
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def components
|
45
45
|
@included_components.keys
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def javascript_file(url)
|
49
49
|
@assets << [:javascript_file, url]
|
50
50
|
end
|
@@ -52,19 +52,19 @@ class AssetFiles
|
|
52
52
|
def css_file(url)
|
53
53
|
@assets << [:css_file, url]
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def component_paths
|
57
57
|
return @components
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def add_assets(path)
|
61
61
|
asset_folder = File.join(path, 'assets')
|
62
62
|
if File.directory?(asset_folder)
|
63
63
|
@assets << [:folder, asset_folder]
|
64
64
|
end
|
65
65
|
end
|
66
|
-
|
67
|
-
|
66
|
+
|
67
|
+
|
68
68
|
def javascript_files(opal_files)
|
69
69
|
javascript_files = []
|
70
70
|
@assets.each do |type, path|
|
@@ -75,7 +75,7 @@ class AssetFiles
|
|
75
75
|
javascript_files << path
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
opal_js_files = []
|
80
80
|
if Volt.source_maps?
|
81
81
|
opal_js_files += opal_files.environment['volt/page/page'].to_a.map {|v| '/assets/' + v.logical_path + '?body=1' }
|
@@ -85,10 +85,10 @@ class AssetFiles
|
|
85
85
|
opal_js_files << '/components/home.js'
|
86
86
|
|
87
87
|
javascript_files += opal_js_files
|
88
|
-
|
88
|
+
|
89
89
|
return javascript_files
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
def css_files
|
93
93
|
css_files = []
|
94
94
|
@assets.each do |type, path|
|
@@ -99,8 +99,8 @@ class AssetFiles
|
|
99
99
|
css_files << path
|
100
100
|
end
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
return css_files
|
104
104
|
end
|
105
|
-
|
106
|
-
end
|
105
|
+
|
106
|
+
end
|
@@ -3,62 +3,62 @@ class ComponentPaths
|
|
3
3
|
def initialize(root=nil)
|
4
4
|
@root = root || Dir.pwd
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
# Yield for every folder where we might find components
|
8
8
|
def app_folders
|
9
9
|
# Find all app folders
|
10
10
|
@app_folders ||= begin
|
11
11
|
app_folders = ["#{@root}/app", "#{@root}/vendor/app"].map {|f| File.expand_path(f) }
|
12
|
-
|
12
|
+
|
13
13
|
# Gem folders with volt in them
|
14
14
|
# TODO: we should probably qualify this a bit more
|
15
15
|
app_folders += Gem.loaded_specs.values.map { |g| g.full_gem_path }.reject {|g| g !~ /volt/ }.map {|f| f + '/app' }
|
16
16
|
|
17
17
|
app_folders
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
# Yield each app folder and return a flattened array with
|
21
21
|
# the results
|
22
|
-
|
22
|
+
|
23
23
|
files = []
|
24
24
|
@app_folders.each do |app_folder|
|
25
25
|
files << yield(app_folder)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
return files.flatten
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# returns an array of every folder that is a component
|
32
32
|
def components
|
33
33
|
return @components if @components
|
34
|
-
|
34
|
+
|
35
35
|
@components = {}
|
36
36
|
app_folders do |app_folder|
|
37
37
|
Dir["#{app_folder}/*"].sort.each do |folder|
|
38
38
|
if File.directory?(folder)
|
39
39
|
folder_name = folder[/[^\/]+$/]
|
40
|
-
|
40
|
+
|
41
41
|
@components[folder_name] ||= []
|
42
|
-
@components[folder_name] << folder
|
42
|
+
@components[folder_name] << folder
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
return @components
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# Makes each components classes available on the load path, require classes.
|
51
51
|
def require_in_components
|
52
52
|
# app_folders do |app_folder|
|
53
53
|
# $LOAD_PATH.unshift(app_folder)
|
54
|
-
#
|
54
|
+
#
|
55
55
|
# Dir["#{app_folder}/*/{controllers,model}/*.rb"].each do |ruby_file|
|
56
56
|
# path = ruby_file.gsub(/^#{app_folder}\//, '')[0..-4]
|
57
57
|
# puts "Path: #{path}"
|
58
58
|
# # require(path)
|
59
59
|
# end
|
60
60
|
# end
|
61
|
-
|
61
|
+
|
62
62
|
# add each tasks folder directly
|
63
63
|
components.each do |name,component_folders|
|
64
64
|
component_folders.each do |component_folder|
|
@@ -68,18 +68,18 @@ class ComponentPaths
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Returns the path for a specific component
|
73
73
|
def component_path(name)
|
74
74
|
folders = components[name]
|
75
|
-
|
75
|
+
|
76
76
|
if folders
|
77
77
|
return folders.first
|
78
78
|
else
|
79
79
|
return nil
|
80
80
|
end
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
# Return every asset folder we need to serve from
|
84
84
|
def asset_folders
|
85
85
|
folders = []
|
@@ -88,8 +88,8 @@ class ComponentPaths
|
|
88
88
|
folders << yield(asset_folder)
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
folders.flatten
|
93
93
|
end
|
94
94
|
|
95
|
-
end
|
95
|
+
end
|
@@ -7,7 +7,7 @@ class IndexFiles
|
|
7
7
|
@app = app
|
8
8
|
@component_paths = component_paths
|
9
9
|
@opal_files = opal_files
|
10
|
-
|
10
|
+
|
11
11
|
@@router ||= Routes.new.define do
|
12
12
|
# Find the route file
|
13
13
|
home_path = component_paths.component_path('home')
|
@@ -15,12 +15,12 @@ class IndexFiles
|
|
15
15
|
eval(route_file)
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def route_match?(path)
|
20
20
|
@@router.path_matchers.each do |path_matcher|
|
21
21
|
return true if path =~ path_matcher
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
return false
|
25
25
|
end
|
26
26
|
|
@@ -31,24 +31,24 @@ class IndexFiles
|
|
31
31
|
@app.call env
|
32
32
|
end
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def html
|
36
36
|
index_path = File.expand_path(File.join(Volt.root, "public/index.html"))
|
37
37
|
html = File.read(index_path)
|
38
|
-
|
38
|
+
|
39
39
|
ERB.new(html).result(binding)
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def javascript_files
|
43
43
|
# TODO: Cache somehow, this is being loaded every time
|
44
44
|
AssetFiles.new('home', @component_paths).javascript_files(@opal_files)
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def css_files
|
48
48
|
AssetFiles.new('home', @component_paths).css_files
|
49
49
|
end
|
50
50
|
|
51
|
-
|
51
|
+
|
52
52
|
|
53
53
|
end
|
54
54
|
|
@@ -7,31 +7,31 @@ end
|
|
7
7
|
# Sets up the maps for the opal assets, and source maps if enabled.
|
8
8
|
class OpalFiles
|
9
9
|
attr_reader :environment
|
10
|
-
|
10
|
+
|
11
11
|
def initialize(builder, app_path, component_paths)
|
12
12
|
Opal::Processor.source_map_enabled = Volt.source_maps?
|
13
|
-
|
13
|
+
|
14
14
|
# Don't run arity checks in production
|
15
15
|
# Opal::Processor.arity_check_enabled = !Volt.env.production?
|
16
16
|
# Opal::Processor.dynamic_require_severity = :raise
|
17
17
|
|
18
18
|
@component_paths = component_paths
|
19
19
|
@environment = Opal::Environment.new
|
20
|
-
|
21
|
-
# Since the scope changes in builder blocks, we need to capture
|
20
|
+
|
21
|
+
# Since the scope changes in builder blocks, we need to capture
|
22
22
|
# environment in closure
|
23
23
|
environment = @environment
|
24
|
-
|
24
|
+
|
25
25
|
environment.cache = Sprockets::Cache::FileStore.new("./tmp")
|
26
|
-
|
26
|
+
|
27
27
|
if Volt.env.production?
|
28
28
|
# Compress in production
|
29
29
|
environment.js_compressor = Sprockets::UglifierCompressor
|
30
30
|
environment.css_compressor = Sprockets::YUICompressor
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
environment.append_path(app_path)
|
34
|
-
|
34
|
+
|
35
35
|
volt_gem_lib_path = File.expand_path(File.join(File.dirname(__FILE__), "../../.."))
|
36
36
|
environment.append_path(volt_gem_lib_path)
|
37
37
|
|
@@ -58,11 +58,11 @@ class OpalFiles
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
def add_asset_folders(environment)
|
63
63
|
@component_paths.asset_folders do |asset_folder|
|
64
64
|
environment.append_path(asset_folder)
|
65
65
|
end
|
66
66
|
end
|
67
|
-
|
68
|
-
end
|
67
|
+
|
68
|
+
end
|
@@ -3,15 +3,15 @@ require 'sockjs/session'
|
|
3
3
|
|
4
4
|
class SocketConnectionHandler < SockJS::Session
|
5
5
|
# Create one instance of the dispatcher
|
6
|
-
|
6
|
+
|
7
7
|
def self.dispatcher=(val)
|
8
8
|
@@dispatcher = val
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def self.dispatcher
|
12
12
|
@@dispatcher
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# Sends a message to all, optionally skipping a users channel
|
16
16
|
def self.send_message_all(skip_channel=nil, *args)
|
17
17
|
@@channels.each do |channel|
|
@@ -20,32 +20,32 @@ class SocketConnectionHandler < SockJS::Session
|
|
20
20
|
end
|
21
21
|
channel.send_message(*args)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def initialize(session, *args)
|
27
27
|
@session = session
|
28
28
|
|
29
29
|
@@channels ||= []
|
30
30
|
@@channels << self
|
31
|
-
|
31
|
+
|
32
32
|
super
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def process_message(message)
|
36
36
|
# self.class.message_all(message)
|
37
37
|
# Messages are json and wrapped in an array
|
38
38
|
message = JSON.parse(message).first
|
39
|
-
|
39
|
+
|
40
40
|
@@dispatcher.dispatch(self, message)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def send_message(*args)
|
44
44
|
str = JSON.dump([*args])
|
45
|
-
|
45
|
+
|
46
46
|
send(str)
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def closed
|
50
50
|
puts "CHANNEL CLOSED: #{self.inspect}"
|
51
51
|
# Remove ourself from the available channels
|
@@ -53,9 +53,9 @@ class SocketConnectionHandler < SockJS::Session
|
|
53
53
|
|
54
54
|
QueryTasks.new(self).close!
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def inspect
|
58
58
|
"<#{self.class.to_s}:#{object_id}>"
|
59
59
|
end
|
60
60
|
|
61
|
-
end
|
61
|
+
end
|
@@ -6,7 +6,7 @@ class SocketConnectionHandlerStub
|
|
6
6
|
def self.dispatcher
|
7
7
|
@@dispatcher
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(channel_stub)
|
11
11
|
@channel_stub = channel_stub
|
12
12
|
end
|
@@ -23,4 +23,4 @@ class SocketConnectionHandlerStub
|
|
23
23
|
def send_message(*args)
|
24
24
|
@channel_stub.message_received(*args)
|
25
25
|
end
|
26
|
-
end
|
26
|
+
end
|
data/lib/volt/server.rb
CHANGED
@@ -23,20 +23,20 @@ require 'volt/tasks/dispatcher'
|
|
23
23
|
|
24
24
|
module Rack
|
25
25
|
# TODO: For some reason in Rack (or maybe thin), 304 headers close
|
26
|
-
# the http connection. We might need to make this check if keep
|
26
|
+
# the http connection. We might need to make this check if keep
|
27
27
|
# alive was in the request.
|
28
28
|
class KeepAlive
|
29
29
|
def initialize(app)
|
30
30
|
@app = app
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def call(env)
|
34
34
|
status, headers, body = @app.call(env)
|
35
35
|
|
36
36
|
if status == 304 && env['HTTP_CONNECTION'].downcase == 'keep-alive'
|
37
37
|
headers['Connection'] = 'keep-alive'
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
[status, headers, body]
|
41
41
|
end
|
42
42
|
end
|
@@ -48,18 +48,18 @@ class Server
|
|
48
48
|
Volt.root = root_path
|
49
49
|
|
50
50
|
@app_path = File.expand_path(File.join(root_path, "app"))
|
51
|
-
|
51
|
+
|
52
52
|
@component_paths = ComponentPaths.new(root_path)
|
53
|
-
|
53
|
+
|
54
54
|
setup_change_listener
|
55
|
-
|
55
|
+
|
56
56
|
display_welcome
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def display_welcome
|
60
|
-
puts File.read(File.join(File.dirname(__FILE__), "server/banner.txt"))
|
60
|
+
puts File.read(File.join(File.dirname(__FILE__), "server/banner.txt"))
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
def setup_change_listener
|
64
64
|
# Setup the listeners for file changes
|
65
65
|
listener = Listen.to("#{@app_path}/") do |modified, added, removed|
|
@@ -67,10 +67,10 @@ class Server
|
|
67
67
|
end
|
68
68
|
listener.start
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
def app
|
72
72
|
@app = Rack::Builder.new
|
73
|
-
|
73
|
+
|
74
74
|
# Should only be used in production
|
75
75
|
# @app.use Rack::Deflater
|
76
76
|
|
@@ -80,7 +80,7 @@ class Server
|
|
80
80
|
@app.use Rack::KeepAlive
|
81
81
|
@app.use Rack::ConditionalGet
|
82
82
|
@app.use Rack::ETag
|
83
|
-
|
83
|
+
|
84
84
|
@app.use Rack::CommonLogger
|
85
85
|
@app.use Rack::ShowExceptions
|
86
86
|
|
@@ -88,24 +88,24 @@ class Server
|
|
88
88
|
@app.map '/components' do
|
89
89
|
run ComponentHandler.new(component_paths)
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
# Serve the opal files
|
93
93
|
opal_files = OpalFiles.new(@app, @app_path, @component_paths)
|
94
94
|
|
95
95
|
# Serve the main html files from public, also figure out
|
96
96
|
# which JS/CSS files to serve.
|
97
97
|
@app.use IndexFiles, @component_paths, opal_files
|
98
|
-
|
98
|
+
|
99
99
|
# Handle socks js connection
|
100
100
|
if RUBY_PLATFORM != 'java'
|
101
101
|
component_paths.require_in_components
|
102
102
|
SocketConnectionHandler.dispatcher = Dispatcher.new
|
103
|
-
|
103
|
+
|
104
104
|
@app.map "/channel" do
|
105
105
|
run Rack::SockJS.new(SocketConnectionHandler)#, :websocket => false
|
106
106
|
end
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
@app.use Rack::Static,
|
110
110
|
:urls => ["/"],
|
111
111
|
:root => "public",
|
@@ -115,7 +115,7 @@ class Server
|
|
115
115
|
]
|
116
116
|
|
117
117
|
@app.run lambda{ |env| [ 404, { 'Content-Type' => 'text/html' }, ['404 - page not found'] ] }
|
118
|
-
|
118
|
+
|
119
119
|
return @app
|
120
120
|
end
|
121
|
-
end
|
121
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# The task dispatcher is responsible for taking incoming messages
|
2
2
|
# from the socket channel and dispatching them to the proper handler.
|
3
3
|
class Dispatcher
|
4
|
-
|
4
|
+
|
5
5
|
def dispatch(channel, message)
|
6
6
|
callback_id, class_name, method_name, *args = message
|
7
7
|
|
@@ -9,10 +9,10 @@ class Dispatcher
|
|
9
9
|
if class_name[/Tasks$/] && !class_name['::']
|
10
10
|
# TODO: Improve error on a class we don't have
|
11
11
|
require(class_name.underscore)
|
12
|
-
|
12
|
+
|
13
13
|
# Get the class
|
14
14
|
klass = Object.send(:const_get, class_name)
|
15
|
-
|
15
|
+
|
16
16
|
# Init and send the method
|
17
17
|
begin
|
18
18
|
result = klass.new(channel, self).send(method_name, *args)
|
@@ -24,11 +24,11 @@ class Dispatcher
|
|
24
24
|
result = nil
|
25
25
|
error = e
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
if callback_id
|
29
29
|
# Callback with result
|
30
30
|
channel.send_message('response', callback_id, result, error)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
data/lib/volt/utils/ejson.rb
CHANGED
@@ -2,7 +2,7 @@ require 'volt/utils/generic_pool'
|
|
2
2
|
|
3
3
|
# A counting pool behaves like a normal GenericPool, except for
|
4
4
|
# each time lookup is called, remove should be called when complete.
|
5
|
-
# The item will be completely removed from the GenericCountingPool
|
5
|
+
# The item will be completely removed from the GenericCountingPool
|
6
6
|
# only when it has been removed an equal number of times it has been
|
7
7
|
# looked up.
|
8
8
|
class GenericCountingPool < GenericPool
|
@@ -10,32 +10,32 @@ class GenericCountingPool < GenericPool
|
|
10
10
|
def generate_new(*args)
|
11
11
|
[0, create(*args)]
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# Finds an item and tracks that it was checked out. Use
|
15
15
|
# #remove when the item is no longer needed.
|
16
16
|
def find(*args, &block)
|
17
17
|
item = __lookup(*args, &block)
|
18
|
-
|
18
|
+
|
19
19
|
item[0] += 1
|
20
|
-
|
20
|
+
|
21
21
|
return item[1]
|
22
22
|
end
|
23
23
|
|
24
24
|
# Lookups an item
|
25
25
|
def lookup(*args, &block)
|
26
26
|
item = super(*args, &block)
|
27
|
-
|
27
|
+
|
28
28
|
return item[1]
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def transform_item(item)
|
32
32
|
[0, item]
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def remove(*args)
|
36
36
|
item = __lookup(*args)
|
37
37
|
item[0] -= 1
|
38
|
-
|
38
|
+
|
39
39
|
if item[0] == 0
|
40
40
|
# Last one using this item has removed it.
|
41
41
|
super(*args)
|
@@ -13,19 +13,19 @@ class GenericPool
|
|
13
13
|
def initialize
|
14
14
|
@pool = {}
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def lookup(*args, &block)
|
18
18
|
section = @pool
|
19
|
-
|
19
|
+
|
20
20
|
# TODO: This is to work around opal issue #500
|
21
21
|
if RUBY_PLATFORM == 'opal'
|
22
22
|
args.pop if args.last == nil
|
23
23
|
end
|
24
|
-
|
25
|
-
|
24
|
+
|
25
|
+
|
26
26
|
args.each_with_index do |arg, index|
|
27
27
|
last = (args.size-1) == index
|
28
|
-
|
28
|
+
|
29
29
|
if last
|
30
30
|
# return, creating if needed
|
31
31
|
return(section[arg] ||= create_new_item(*args, &block))
|
@@ -36,7 +36,7 @@ class GenericPool
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
# Does the actual creating, if a block is not passed in, it calls
|
41
41
|
# #create on the class.
|
42
42
|
def create_new_item(*args)
|
@@ -45,28 +45,28 @@ class GenericPool
|
|
45
45
|
else
|
46
46
|
new_item = create(*args)
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
return transform_item(new_item)
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
# Allow other pools to override how the created item gets stored.
|
53
53
|
def transform_item(item)
|
54
54
|
item
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
# Make sure we call the pool one from lookup_all and not
|
58
58
|
# an overridden one.
|
59
59
|
alias_method :__lookup, :lookup
|
60
|
-
|
60
|
+
|
61
61
|
def lookup_all(*args)
|
62
62
|
__lookup(*args).values
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def remove(*args)
|
66
66
|
stack = []
|
67
67
|
section = @pool
|
68
|
-
|
69
|
-
args.each_with_index do |arg, index|
|
68
|
+
|
69
|
+
args.each_with_index do |arg, index|
|
70
70
|
stack << section
|
71
71
|
|
72
72
|
if args.size-1 == index
|
@@ -75,14 +75,14 @@ class GenericPool
|
|
75
75
|
section = section[arg]
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
(stack.size-1).downto(1) do |index|
|
80
80
|
node = stack[index]
|
81
81
|
parent = stack[index-1]
|
82
|
-
|
82
|
+
|
83
83
|
if node.size == 0
|
84
84
|
parent.delete(args[index-1])
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
-
end
|
88
|
+
end
|