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
data/lib/volt/server.rb
CHANGED
|
@@ -50,85 +50,87 @@ module Rack
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
root_path
|
|
56
|
-
|
|
53
|
+
module Volt
|
|
54
|
+
class Server
|
|
55
|
+
def initialize(root_path=nil)
|
|
56
|
+
root_path ||= Dir.pwd
|
|
57
|
+
Volt.root = root_path
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
@app_path = File.expand_path(File.join(root_path, "app"))
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
# Boot the volt app
|
|
62
|
+
@component_paths = Volt.boot(root_path)
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
setup_change_listener
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
display_welcome
|
|
67
|
+
end
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
def display_welcome
|
|
70
|
+
puts File.read(File.join(File.dirname(__FILE__), "server/banner.txt"))
|
|
71
|
+
end
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
def setup_change_listener
|
|
74
|
+
# Setup the listeners for file changes
|
|
75
|
+
listener = Listen.to("#{@app_path}/") do |modified, added, removed|
|
|
76
|
+
puts "file changed, sending reload"
|
|
77
|
+
SocketConnectionHandler.send_message_all(nil, 'reload')
|
|
78
|
+
end
|
|
79
|
+
listener.start
|
|
77
80
|
end
|
|
78
|
-
listener.start
|
|
79
|
-
end
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
def app
|
|
83
|
+
@app = Rack::Builder.new
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
# Should only be used in production
|
|
86
|
+
if Volt.config.deflate
|
|
87
|
+
@app.use Rack::Deflater
|
|
88
|
+
@app.use Rack::Chunked
|
|
89
|
+
end
|
|
89
90
|
|
|
90
|
-
|
|
91
|
+
@app.use Rack::ContentLength
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
@app.use Rack::KeepAlive
|
|
94
|
+
@app.use Rack::ConditionalGet
|
|
95
|
+
@app.use Rack::ETag
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
@app.use Rack::CommonLogger
|
|
98
|
+
@app.use Rack::ShowExceptions
|
|
98
99
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
component_paths = @component_paths
|
|
101
|
+
@app.map '/components' do
|
|
102
|
+
run ComponentHandler.new(component_paths)
|
|
103
|
+
end
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
# Serve the opal files
|
|
106
|
+
opal_files = OpalFiles.new(@app, @app_path, @component_paths)
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
# Serve the main html files from public, also figure out
|
|
109
|
+
# which JS/CSS files to serve.
|
|
110
|
+
@app.use IndexFiles, @component_paths, opal_files
|
|
110
111
|
|
|
111
|
-
|
|
112
|
+
component_paths.require_in_components
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
# Handle socks js connection
|
|
115
|
+
if RUBY_PLATFORM != 'java'
|
|
116
|
+
SocketConnectionHandler.dispatcher = Dispatcher.new
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
@app.map "/channel" do
|
|
119
|
+
run Rack::SockJS.new(SocketConnectionHandler) #, :websocket => false
|
|
120
|
+
end
|
|
119
121
|
end
|
|
120
|
-
end
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
@app.use Rack::Static,
|
|
124
|
+
:urls => ["/"],
|
|
125
|
+
:root => "public",
|
|
126
|
+
:index => "",
|
|
127
|
+
:header_rules => [
|
|
128
|
+
[:all, {'Cache-Control' => 'public, max-age=86400'}]
|
|
129
|
+
]
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
@app.run lambda { |env| [404, {'Content-Type' => 'text/html; charset=utf-8'}, ['404 - page not found']] }
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
@app
|
|
134
|
+
end
|
|
133
135
|
end
|
|
134
136
|
end
|
data/lib/volt/spec/setup.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
module Volt
|
|
2
2
|
def self.spec_setup(app_path='.')
|
|
3
3
|
if RUBY_PLATFORM == 'opal'
|
|
4
4
|
require 'volt'
|
|
@@ -32,7 +32,7 @@ class Volt
|
|
|
32
32
|
Capybara.default_driver = :poltergeist
|
|
33
33
|
elsif ENV['BROWSER'] == 'chrome'
|
|
34
34
|
Capybara.register_driver :chrome do |app|
|
|
35
|
-
Capybara::Selenium::Driver.new(app, :
|
|
35
|
+
Capybara::Selenium::Driver.new(app, browser: :chrome)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
Capybara.default_driver = :chrome
|
|
@@ -57,4 +57,4 @@ class Volt
|
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
-
end
|
|
60
|
+
end
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
#
|
|
3
|
-
|
|
1
|
+
module Volt
|
|
2
|
+
# The task dispatcher is responsible for taking incoming messages
|
|
3
|
+
# from the socket channel and dispatching them to the proper handler.
|
|
4
|
+
class Dispatcher
|
|
5
|
+
def dispatch(channel, message)
|
|
6
|
+
callback_id, class_name, method_name, *args = message
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
# Get the class
|
|
9
|
+
klass = Object.send(:const_get, class_name)
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
if klass.ancestors.include?(TaskHandler)
|
|
12
|
+
# Init and send the method
|
|
13
|
+
begin
|
|
14
|
+
result = klass.new(channel, self).send(method_name, *args)
|
|
15
|
+
error = nil
|
|
16
|
+
rescue => e
|
|
17
|
+
# TODO: Log these errors better
|
|
18
|
+
puts e.inspect
|
|
19
|
+
puts e.backtrace
|
|
20
|
+
result = nil
|
|
21
|
+
error = e
|
|
22
|
+
end
|
|
10
23
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
error = nil
|
|
16
|
-
rescue => e
|
|
17
|
-
# TODO: Log these errors better
|
|
18
|
-
puts e.inspect
|
|
19
|
-
puts e.backtrace
|
|
20
|
-
result = nil
|
|
21
|
-
error = e
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
if callback_id
|
|
25
|
-
# Callback with result
|
|
26
|
-
channel.send_message('response', callback_id, result, error)
|
|
24
|
+
if callback_id
|
|
25
|
+
# Callback with result
|
|
26
|
+
channel.send_message('response', callback_id, result, error)
|
|
27
|
+
end
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
end
|
|
@@ -1,41 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
module Volt
|
|
2
|
+
class TaskHandler
|
|
3
|
+
if RUBY_PLATFORM == 'opal'
|
|
4
|
+
# On the front-end we setup a proxy class to the backend that returns
|
|
5
|
+
# promises for all calls.
|
|
6
|
+
def self.method_missing(name, *args, &block)
|
|
7
|
+
$page.tasks.call(self.name, name, *args, &block)
|
|
8
|
+
end
|
|
9
|
+
else
|
|
10
|
+
def initialize(channel=nil, dispatcher=nil)
|
|
11
|
+
@channel = channel
|
|
12
|
+
@dispatcher = dispatcher
|
|
13
|
+
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
def self.inherited(subclass)
|
|
16
|
+
@subclasses ||= []
|
|
17
|
+
@subclasses << subclass
|
|
18
|
+
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
def self.known_handlers
|
|
21
|
+
@subclasses ||= []
|
|
22
|
+
end
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
# On the backend, we proxy all class methods like we would
|
|
25
|
+
# on the front-end. This returns promises.
|
|
26
|
+
def self.method_missing(name, *args, &block)
|
|
27
|
+
promise = Promise.new
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
begin
|
|
30
|
+
result = self.new(nil, nil).send(name, *args, &block)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
promise.resolve(result)
|
|
33
|
+
rescue => e
|
|
34
|
+
puts "Task Error: #{e.inspect}"
|
|
35
|
+
puts e.backtrace
|
|
36
|
+
promise.reject(e)
|
|
37
|
+
end
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
return promise
|
|
40
|
+
end
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
|
-
end
|
|
43
|
+
end
|
data/lib/volt/utils/ejson.rb
CHANGED
|
@@ -1,44 +1,46 @@
|
|
|
1
1
|
require 'volt/utils/generic_pool'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
module Volt
|
|
4
|
+
# A counting pool behaves like a normal GenericPool, except for
|
|
5
|
+
# each time lookup is called, remove should be called when complete.
|
|
6
|
+
# The item will be completely removed from the GenericCountingPool
|
|
7
|
+
# only when it has been removed an equal number of times it has been
|
|
8
|
+
# looked up.
|
|
9
|
+
class GenericCountingPool < GenericPool
|
|
10
|
+
# return a created item with a count
|
|
11
|
+
def generate_new(*args)
|
|
12
|
+
[0, create(*args)]
|
|
13
|
+
end
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
# Finds an item and tracks that it was checked out. Use
|
|
16
|
+
# #remove when the item is no longer needed.
|
|
17
|
+
def find(*args, &block)
|
|
18
|
+
item = __lookup(*args, &block)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
item[0] += 1
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
return item[1]
|
|
23
|
+
end
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
# Lookups an item
|
|
26
|
+
def lookup(*args, &block)
|
|
27
|
+
item = super(*args, &block)
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
return item[1]
|
|
30
|
+
end
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
def transform_item(item)
|
|
33
|
+
[0, item]
|
|
34
|
+
end
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
def remove(*args)
|
|
37
|
+
item = __lookup(*args)
|
|
38
|
+
item[0] -= 1
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
if item[0] == 0
|
|
41
|
+
# Last one using this item has removed it.
|
|
42
|
+
super(*args)
|
|
43
|
+
end
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
end
|
|
@@ -1,93 +1,96 @@
|
|
|
1
|
-
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
module Volt
|
|
2
|
+
# GenericPool is a base class you can inherit from to cache items
|
|
3
|
+
# based on a lookup.
|
|
4
|
+
#
|
|
5
|
+
# GenericPool assumes either a block is passed to lookup, or a
|
|
6
|
+
# #create method, that takes the path arguments and reutrns a new instance.
|
|
7
|
+
#
|
|
8
|
+
# GenericPool can handle as deep of paths as needed. You can also lookup
|
|
9
|
+
# all of the items at a sub-path with #lookup_all
|
|
10
|
+
#
|
|
11
|
+
# TODO: make the lookup/create threadsafe
|
|
12
|
+
class GenericPool
|
|
13
|
+
attr_reader :pool
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@pool = {}
|
|
17
|
+
end
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
def lookup(*args, &block)
|
|
20
|
+
section = @pool
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
# TODO: This is to work around opal issue #500
|
|
23
|
+
if RUBY_PLATFORM == 'opal'
|
|
24
|
+
args.pop if args.last == nil
|
|
25
|
+
end
|
|
24
26
|
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
args.each_with_index do |arg, index|
|
|
29
|
+
last = (args.size-1) == index
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
if last
|
|
32
|
+
# return, creating if needed
|
|
33
|
+
return(section[arg] ||= create_new_item(*args, &block))
|
|
34
|
+
else
|
|
35
|
+
next_section = section[arg]
|
|
36
|
+
next_section ||= (section[arg] = {})
|
|
37
|
+
section = next_section
|
|
38
|
+
end
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
|
-
end
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
# Does the actual creating, if a block is not passed in, it calls
|
|
43
|
+
# #create on the class.
|
|
44
|
+
def create_new_item(*args)
|
|
45
|
+
if block_given?
|
|
46
|
+
new_item = yield(*args)
|
|
47
|
+
else
|
|
48
|
+
new_item = create(*args)
|
|
49
|
+
end
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
return transform_item(new_item)
|
|
52
|
+
end
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
# Allow other pools to override how the created item gets stored.
|
|
55
|
+
def transform_item(item)
|
|
56
|
+
item
|
|
57
|
+
end
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
# Make sure we call the pool one from lookup_all and not
|
|
60
|
+
# an overridden one.
|
|
61
|
+
alias_method :__lookup, :lookup
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
def lookup_all(*args)
|
|
64
|
+
result = __lookup(*args) { nil }
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
if result
|
|
67
|
+
return result.values
|
|
68
|
+
else
|
|
69
|
+
return []
|
|
70
|
+
end
|
|
68
71
|
end
|
|
69
|
-
end
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
def remove(*args)
|
|
74
|
+
stack = []
|
|
75
|
+
section = @pool
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
args.each_with_index do |arg, index|
|
|
78
|
+
stack << section
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
if args.size-1 == index
|
|
81
|
+
section.delete(arg)
|
|
82
|
+
else
|
|
83
|
+
section = section[arg]
|
|
84
|
+
end
|
|
82
85
|
end
|
|
83
|
-
end
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
(stack.size-1).downto(1) do |index|
|
|
88
|
+
node = stack[index]
|
|
89
|
+
parent = stack[index-1]
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
if node.size == 0
|
|
92
|
+
parent.delete(args[index-1])
|
|
93
|
+
end
|
|
91
94
|
end
|
|
92
95
|
end
|
|
93
96
|
end
|
|
@@ -1,49 +1,53 @@
|
|
|
1
1
|
if RUBY_PLATFORM == 'opal'
|
|
2
|
-
module
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
module Volt
|
|
3
|
+
module LocalStorage
|
|
4
|
+
def self.[](key)
|
|
5
|
+
%x{
|
|
6
|
+
var val = localStorage.getItem(key);
|
|
7
|
+
return val === null ? nil : val;
|
|
8
|
+
}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.[]=(key, value)
|
|
12
|
+
`localStorage.setItem(key, value)`
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.clear
|
|
16
|
+
`localStorage.clear()`
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.delete(key)
|
|
21
|
+
%x{
|
|
22
|
+
var val = localStorage.getItem(key);
|
|
23
|
+
localStorage.removeItem(key);
|
|
24
|
+
return val === null ? nil : val;
|
|
25
|
+
}
|
|
26
|
+
end
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
29
|
else
|
|
28
|
-
module
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@@store[key]
|
|
32
|
-
end
|
|
30
|
+
module Volt
|
|
31
|
+
module LocalStorage
|
|
32
|
+
@@store = {}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
def self.[](key)
|
|
35
|
+
@@store[key]
|
|
36
|
+
end
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
def self.[]=(key, value)
|
|
39
|
+
@@store[key] = value
|
|
40
|
+
end
|
|
40
41
|
|
|
41
|
-
self
|
|
42
|
-
|
|
42
|
+
def self.clear
|
|
43
|
+
@@store = {}
|
|
44
|
+
|
|
45
|
+
self
|
|
46
|
+
end
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
def self.delete(key)
|
|
49
|
+
@@store.delete(key)
|
|
50
|
+
end
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
|
-
|