volt 0.4.7 → 0.4.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Readme.md +9 -1
- data/VERSION +1 -1
- data/app/volt/tasks/channel_tasks.rb +25 -3
- data/app/volt/tasks/store_tasks.rb +4 -3
- data/lib/volt/console.rb +2 -2
- data/lib/volt/models/store.rb +1 -1
- data/lib/volt/models/store_array.rb +25 -0
- data/lib/volt/page/channel_stub.rb +1 -1
- data/lib/volt/page/draw_cycle.rb +9 -0
- data/lib/volt/page/page.rb +3 -3
- data/lib/volt/page/tasks.rb +12 -3
- data/lib/volt/server/rack/asset_files.rb +1 -1
- data/lib/volt/server/rack/index_files.rb +2 -2
- data/lib/volt/server/{channel_handler.rb → socket_connection_handler.rb} +6 -2
- data/lib/volt/server/{channel_handler_stub.rb → socket_connection_handler_stub.rb} +1 -4
- data/lib/volt/server.rb +4 -4
- data/lib/volt/tasks/dispatcher.rb +0 -1
- data/spec/tasks/channel_tasks_spec.rb +74 -0
- metadata +7 -5
- data/lib/volt/page/render_queue.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5fa5dd92e489dfa4a0257eccd5509aa2324cb25
|
4
|
+
data.tar.gz: 21e58768017cd4b82ec09ee9b9b06a828d3289e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd684af9e5c24c317c62e97bff34c8a7f732082074424e225db3712386fb1ded60f30b686a5046961600f0f9a48b12a14da42500434f700f50b681b57125de94
|
7
|
+
data.tar.gz: bc38cdd81e222e1ed407fa44819ee1b0adc6edf1796ec597b7022dfd7f7abb74583fbfcd266409d3299f02afe31cc62daea8f387211c82996e21217cbfab4d45
|
data/Readme.md
CHANGED
@@ -382,6 +382,13 @@ in the file.
|
|
382
382
|
|
383
383
|
Dependencies act just like require in ruby, but for whole components.
|
384
384
|
|
385
|
+
Sometimes you may need to include an externally hosted JS file from a component. To do this, simply do the following in the dependencies.rb file:
|
386
|
+
|
387
|
+
javascript_file 'http://code.jquery.com/jquery-2.0.3.min.js'
|
388
|
+
css_file '//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css'
|
389
|
+
|
390
|
+
Note above though that jquery and bootstrap are currently included by default. Using javascript_file and css_file will be mixed in with your component assets at the correct locations according to the order they occur in the dependencies.rb files.
|
391
|
+
|
385
392
|
## Assets
|
386
393
|
|
387
394
|
**Note, asset management is still early, and likely will change quite a bit**
|
@@ -501,4 +508,5 @@ An in browser irb is in the works. We also have source maps support, but they a
|
|
501
508
|
|
502
509
|
MAPS=true volt s
|
503
510
|
|
504
|
-
They are disabled by default because they slow down page rendering because so many files are rendered. We're working with the opal and sprockets teams to make it so everything is still served in one big source maps file (which would show the files as they originated on disk)
|
511
|
+
They are disabled by default because they slow down page rendering because so many files are rendered. We're working with the opal and sprockets teams to make it so everything is still served in one big source maps file (which would show the files as they originated on disk)
|
512
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.8
|
@@ -1,23 +1,45 @@
|
|
1
1
|
class ChannelTasks
|
2
2
|
@@listeners = {}
|
3
|
+
@@channel_listeners = {}
|
3
4
|
|
4
|
-
|
5
|
+
# The dispatcher passes its self in
|
6
|
+
def initialize(channel, dispatcher=nil)
|
5
7
|
@channel = channel
|
6
|
-
@dispatcher = dispatcher
|
7
8
|
end
|
8
9
|
|
9
10
|
def add_listener(channel_name)
|
11
|
+
# Track every channel that is listening
|
10
12
|
@@listeners[channel_name] ||= []
|
11
13
|
@@listeners[channel_name] << @channel
|
14
|
+
|
15
|
+
# Also keep track of which channel names a channel is listening
|
16
|
+
# on so it can be removed if a channel is closed.
|
17
|
+
@@channel_listeners[@channel] ||= {}
|
18
|
+
@@channel_listeners[@channel][channel_name] = true
|
12
19
|
end
|
13
20
|
|
14
21
|
def remove_listener(channel_name)
|
15
22
|
if @@listeners[channel_name]
|
16
23
|
@@listeners[channel_name].delete(@channel)
|
24
|
+
if @@channel_listeners[@channel]
|
25
|
+
@@channel_listeners[@channel].delete(channel_name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Called when a channel is closed, removes its listeners from
|
31
|
+
# all channels.
|
32
|
+
def close!
|
33
|
+
channel_names = @@channel_listeners.delete(@channel)
|
34
|
+
|
35
|
+
if channel_names
|
36
|
+
channel_names.each_pair do |channel_name,val|
|
37
|
+
remove_listener(channel_name)
|
38
|
+
end
|
17
39
|
end
|
18
40
|
end
|
19
41
|
|
20
|
-
def self.send_message_to_channel(channel_name, message, skip_channel)
|
42
|
+
def self.send_message_to_channel(channel_name, message, skip_channel=nil)
|
21
43
|
listeners = @@listeners[channel_name]
|
22
44
|
|
23
45
|
if listeners
|
@@ -3,7 +3,6 @@ require_relative 'channel_tasks'
|
|
3
3
|
|
4
4
|
class StoreTasks
|
5
5
|
def initialize(channel=nil, dispatcher=nil)
|
6
|
-
puts "init store tasks"
|
7
6
|
@@mongo_db ||= Mongo::MongoClient.new("localhost", 27017)
|
8
7
|
@@db ||= @@mongo_db.db("development")
|
9
8
|
|
@@ -22,6 +21,9 @@ class StoreTasks
|
|
22
21
|
begin
|
23
22
|
@@db[collection].insert(data)
|
24
23
|
id = {'_id' => data.delete('_id')}
|
24
|
+
|
25
|
+
# Message that we inserted a new item
|
26
|
+
ChannelTasks.send_message_to_channel("#{collection}", ['added', nil, collection, data.merge('_id' => id).symbolize_keys], @channel)
|
25
27
|
rescue Mongo::OperationFailure => error
|
26
28
|
# Really mongo client?
|
27
29
|
if error.message[/^11000[:]/]
|
@@ -35,8 +37,7 @@ class StoreTasks
|
|
35
37
|
|
36
38
|
id = id['_id']
|
37
39
|
|
38
|
-
|
39
|
-
ChannelTasks.send_message_to_channel("#{collection}##{id}", ['update', nil, id, data.merge('_id' => id).symbolize_keys], @channel)
|
40
|
+
ChannelTasks.send_message_to_channel("#{collection}##{id}", ['changed', nil, id, data.merge('_id' => id).symbolize_keys], @channel)
|
40
41
|
end
|
41
42
|
|
42
43
|
def find(collection, scope, query=nil)
|
data/lib/volt/console.rb
CHANGED
@@ -12,9 +12,9 @@ class Console
|
|
12
12
|
require 'volt'
|
13
13
|
require 'volt/page/page'
|
14
14
|
require 'volt/server/rack/component_paths'
|
15
|
-
require 'volt/server/
|
15
|
+
require 'volt/server/socket_connection_handler_stub'
|
16
16
|
|
17
|
-
|
17
|
+
SocketConnectionHandlerStub.dispatcher = Dispatcher.new
|
18
18
|
|
19
19
|
|
20
20
|
app_path = File.expand_path(File.join(Dir.pwd, "app"))
|
data/lib/volt/models/store.rb
CHANGED
@@ -36,7 +36,7 @@ class Store < Model
|
|
36
36
|
def change_channel_connection(add_or_remove)
|
37
37
|
if attributes && path.size > 1
|
38
38
|
channel_name = "#{path[-2]}##{attributes[:_id]}"
|
39
|
-
|
39
|
+
@tasks.call('ChannelTasks', "#{add_or_remove}_listener", channel_name)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -5,6 +5,31 @@ class StoreArray < ArrayModel
|
|
5
5
|
super(array, parent, path)
|
6
6
|
end
|
7
7
|
|
8
|
+
def event_added(event, scope_provider, first)
|
9
|
+
puts "New event: #{event.inspect} - #{first}"
|
10
|
+
if first && [:added, :removed].include?(event)
|
11
|
+
# Start listening for added items on the collection
|
12
|
+
|
13
|
+
change_channel_connection('add')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def event_removed(event, no_more_events)
|
18
|
+
if no_more_events && [:added, :removed].include?(event)
|
19
|
+
# Stop listening
|
20
|
+
change_channel_connection("remove", event)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def change_channel_connection(add_or_remove, event)
|
26
|
+
if parent.attributes && path.size != 0
|
27
|
+
channel_name = "#{path[-1]}-#{event}"
|
28
|
+
puts "Listen on #{channel_name}"
|
29
|
+
@tasks.call('ChannelTasks', "#{add_or_remove}_listener", channel_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
8
33
|
def new_model(*args)
|
9
34
|
Store.new(@tasks, *args)
|
10
35
|
end
|
@@ -6,7 +6,7 @@ require 'volt/tasks/dispatcher'
|
|
6
6
|
|
7
7
|
# Behaves the same as the Channel class, only the Channel class uses
|
8
8
|
# sockjs to pass messages to the backend. ChannelStub, simply passes
|
9
|
-
# them directly to
|
9
|
+
# them directly to SocketConnectionHandlerStub.
|
10
10
|
class ChannelStub
|
11
11
|
include ReactiveTags
|
12
12
|
|
data/lib/volt/page/page.rb
CHANGED
@@ -29,11 +29,11 @@ require 'volt/models/url'
|
|
29
29
|
require 'volt/page/url_tracker'
|
30
30
|
require 'volt'
|
31
31
|
require 'volt/benchmark/benchmark'
|
32
|
-
require 'volt/page/
|
32
|
+
require 'volt/page/draw_cycle'
|
33
33
|
require 'volt/page/tasks'
|
34
34
|
|
35
35
|
class Page
|
36
|
-
attr_reader :url, :params, :page, :store, :templates, :routes, :
|
36
|
+
attr_reader :url, :params, :page, :store, :templates, :routes, :draw_cycle
|
37
37
|
|
38
38
|
def initialize
|
39
39
|
|
@@ -50,7 +50,7 @@ class Page
|
|
50
50
|
@url_tracker = UrlTracker.new(self)
|
51
51
|
|
52
52
|
@events = DocumentEvents.new
|
53
|
-
@
|
53
|
+
@draw_cycle = DrawCycle.new
|
54
54
|
|
55
55
|
if RUBY_PLATFORM == 'opal'
|
56
56
|
# Setup escape binding for console
|
data/lib/volt/page/tasks.rb
CHANGED
@@ -31,8 +31,10 @@ class Tasks
|
|
31
31
|
case name
|
32
32
|
when 'response'
|
33
33
|
response(callback_id, *args)
|
34
|
-
when '
|
35
|
-
|
34
|
+
when 'changed'
|
35
|
+
changed(*args)
|
36
|
+
when 'added'
|
37
|
+
added(*args)
|
36
38
|
when 'reload'
|
37
39
|
reload
|
38
40
|
end
|
@@ -46,13 +48,20 @@ class Tasks
|
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
def
|
51
|
+
def changed(model_id, data)
|
50
52
|
$loading_models = true
|
51
53
|
puts "UPDATE: #{model_id} with #{data.inspect}"
|
52
54
|
Store.update(model_id, data)
|
53
55
|
$loading_models = false
|
54
56
|
end
|
55
57
|
|
58
|
+
def added(path, data)
|
59
|
+
$loading_models = true
|
60
|
+
puts "Add: #{path.inspect} - #{data.inspect}"
|
61
|
+
$page.store.send(path) << data
|
62
|
+
$loading_models = false
|
63
|
+
end
|
64
|
+
|
56
65
|
def reload
|
57
66
|
puts "RELOAD"
|
58
67
|
$page.page._reloading = true
|
@@ -40,11 +40,11 @@ class IndexFiles
|
|
40
40
|
|
41
41
|
def javascript_files
|
42
42
|
# TODO: Cache somehow, this is being loaded every time
|
43
|
-
|
43
|
+
AssetFiles.new('home', @component_paths).javascript_files(@opal_files)
|
44
44
|
end
|
45
45
|
|
46
46
|
def css_files
|
47
|
-
|
47
|
+
AssetFiles.new('home', @component_paths).css_files
|
48
48
|
end
|
49
49
|
|
50
50
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'sockjs/session'
|
3
3
|
|
4
|
-
class
|
4
|
+
class SocketConnectionHandler < SockJS::Session
|
5
5
|
# Create one instance of the dispatcher
|
6
6
|
|
7
7
|
def self.dispatcher=(val)
|
@@ -47,9 +47,13 @@ class ChannelHandler < SockJS::Session
|
|
47
47
|
send(str)
|
48
48
|
end
|
49
49
|
|
50
|
-
def closed
|
50
|
+
def closed
|
51
|
+
puts "CHANNEL CLOSED"
|
51
52
|
# Remove ourself from the available channels
|
52
53
|
@@channels.delete(self)
|
54
|
+
|
55
|
+
# Remove any listening channels
|
56
|
+
ChannelTasks.new(self).close!
|
53
57
|
end
|
54
58
|
|
55
59
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class
|
1
|
+
class SocketConnectionHandlerStub
|
2
2
|
def self.dispatcher=(val)
|
3
3
|
@@dispatcher = val
|
4
4
|
end
|
@@ -8,7 +8,6 @@ class ChannelHandlerStub
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def initialize(channel_stub)
|
11
|
-
puts "INIT WITH : #{channel_stub.inspect}"
|
12
11
|
@channel_stub = channel_stub
|
13
12
|
end
|
14
13
|
|
@@ -18,12 +17,10 @@ class ChannelHandlerStub
|
|
18
17
|
end
|
19
18
|
|
20
19
|
def process_message(message)
|
21
|
-
puts "GOT: #{message.inspect}"
|
22
20
|
@@dispatcher.dispatch(self, message)
|
23
21
|
end
|
24
22
|
|
25
23
|
def send_message(*args)
|
26
|
-
puts "SEND MSG: #{args.inspect}"
|
27
24
|
@channel_stub.message_received(*args)
|
28
25
|
end
|
29
26
|
end
|
data/lib/volt/server.rb
CHANGED
@@ -13,7 +13,7 @@ require 'listen'
|
|
13
13
|
require 'volt/extra_core/extra_core'
|
14
14
|
require 'volt/server/component_handler'
|
15
15
|
if RUBY_PLATFORM != 'java'
|
16
|
-
require 'volt/server/
|
16
|
+
require 'volt/server/socket_connection_handler'
|
17
17
|
end
|
18
18
|
require 'volt/server/rack/component_paths'
|
19
19
|
require 'volt/server/rack/index_files'
|
@@ -58,7 +58,7 @@ class Server
|
|
58
58
|
def setup_change_listener
|
59
59
|
# Setup the listeners for file changes
|
60
60
|
listener = Listen.to("#{@app_path}/") do |modified, added, removed|
|
61
|
-
|
61
|
+
SocketConnectionHandler.send_message_all(nil, 'reload')
|
62
62
|
end
|
63
63
|
listener.start
|
64
64
|
end
|
@@ -94,10 +94,10 @@ class Server
|
|
94
94
|
# Handle socks js connection
|
95
95
|
if RUBY_PLATFORM != 'java'
|
96
96
|
component_paths.setup_components_load_path
|
97
|
-
|
97
|
+
SocketConnectionHandler.dispatcher = Dispatcher.new
|
98
98
|
|
99
99
|
@app.map "/channel" do
|
100
|
-
run Rack::SockJS.new(
|
100
|
+
run Rack::SockJS.new(SocketConnectionHandler)#, :websocket => false
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
if RUBY_PLATFORM != 'opal'
|
2
|
+
describe "ChannelTasks" do
|
3
|
+
before do
|
4
|
+
load File.join(File.dirname(__FILE__), "../../app/volt/tasks/channel_tasks.rb")
|
5
|
+
end
|
6
|
+
|
7
|
+
after do
|
8
|
+
Object.send(:remove_const, :ChannelTasks)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should let channels be added and removed" do
|
12
|
+
connection = double('socket connection')
|
13
|
+
|
14
|
+
expect(connection).to receive(:send_message).with('message')
|
15
|
+
|
16
|
+
@channel_task = ChannelTasks.new(connection)
|
17
|
+
@channel_task.add_listener('channel1')
|
18
|
+
|
19
|
+
ChannelTasks.send_message_to_channel('channel1', 'message')
|
20
|
+
end
|
21
|
+
|
22
|
+
it "shouldn't send to channels that aren't listening" do
|
23
|
+
connection1 = double('socket connection1')
|
24
|
+
connection2 = double('socket connection2')
|
25
|
+
|
26
|
+
expect(connection1).to receive(:send_message).with('message for 1')
|
27
|
+
expect(connection1).to_not receive(:send_message).with('message for 2')
|
28
|
+
|
29
|
+
expect(connection2).to_not receive(:send_message).with('message for 1')
|
30
|
+
expect(connection2).to receive(:send_message).with('message for 2')
|
31
|
+
|
32
|
+
@channel_task = ChannelTasks.new(connection1)
|
33
|
+
@channel_task.add_listener('channel1')
|
34
|
+
|
35
|
+
@channel_task = ChannelTasks.new(connection2)
|
36
|
+
@channel_task.add_listener('channel2')
|
37
|
+
|
38
|
+
ChannelTasks.send_message_to_channel('channel1', 'message for 1')
|
39
|
+
ChannelTasks.send_message_to_channel('channel2', 'message for 2')
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should remove channels" do
|
43
|
+
connection = double('socket connection')
|
44
|
+
|
45
|
+
expect(connection).to_not receive(:send_message).with('message for channel1')
|
46
|
+
expect(connection).to receive(:send_message).with('message for channel2')
|
47
|
+
|
48
|
+
@channel_task = ChannelTasks.new(connection)
|
49
|
+
@channel_task.add_listener('channel1')
|
50
|
+
@channel_task.add_listener('channel2')
|
51
|
+
|
52
|
+
ChannelTasks.new(connection).remove_listener('channel1')
|
53
|
+
|
54
|
+
ChannelTasks.send_message_to_channel('channel1', 'message for channel1')
|
55
|
+
ChannelTasks.send_message_to_channel('channel2', 'message for channel2')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should remove all when the socket is closed" do
|
59
|
+
connection = double('socket connection')
|
60
|
+
|
61
|
+
expect(connection).to_not receive(:send_message).with('message for channel1')
|
62
|
+
expect(connection).to_not receive(:send_message).with('message for channel2')
|
63
|
+
|
64
|
+
@channel_task = ChannelTasks.new(connection)
|
65
|
+
@channel_task.add_listener('channel1')
|
66
|
+
@channel_task.add_listener('channel2')
|
67
|
+
|
68
|
+
ChannelTasks.new(connection).close!
|
69
|
+
|
70
|
+
ChannelTasks.send_message_to_channel('channel1', 'message for channel1')
|
71
|
+
ChannelTasks.send_message_to_channel('channel2', 'message for channel2')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: volt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Stout
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -341,10 +341,10 @@ files:
|
|
341
341
|
- lib/volt/page/channel.rb
|
342
342
|
- lib/volt/page/channel_stub.rb
|
343
343
|
- lib/volt/page/document_events.rb
|
344
|
+
- lib/volt/page/draw_cycle.rb
|
344
345
|
- lib/volt/page/memory_test.rb
|
345
346
|
- lib/volt/page/page.rb
|
346
347
|
- lib/volt/page/reactive_template.rb
|
347
|
-
- lib/volt/page/render_queue.rb
|
348
348
|
- lib/volt/page/sub_context.rb
|
349
349
|
- lib/volt/page/targets/attribute_section.rb
|
350
350
|
- lib/volt/page/targets/attribute_target.rb
|
@@ -371,8 +371,6 @@ files:
|
|
371
371
|
- lib/volt/server.rb
|
372
372
|
- lib/volt/server/banner.txt
|
373
373
|
- lib/volt/server/binding_setup.rb
|
374
|
-
- lib/volt/server/channel_handler.rb
|
375
|
-
- lib/volt/server/channel_handler_stub.rb
|
376
374
|
- lib/volt/server/component_handler.rb
|
377
375
|
- lib/volt/server/component_templates.rb
|
378
376
|
- lib/volt/server/if_binding_setup.rb
|
@@ -382,6 +380,8 @@ files:
|
|
382
380
|
- lib/volt/server/rack/opal_files.rb
|
383
381
|
- lib/volt/server/rack/source_map_server.rb
|
384
382
|
- lib/volt/server/scope.rb
|
383
|
+
- lib/volt/server/socket_connection_handler.rb
|
384
|
+
- lib/volt/server/socket_connection_handler_stub.rb
|
385
385
|
- lib/volt/server/template_parser.rb
|
386
386
|
- lib/volt/store/mongo.rb
|
387
387
|
- lib/volt/tasks/dispatcher.rb
|
@@ -408,6 +408,7 @@ files:
|
|
408
408
|
- spec/server/template_parser_spec.rb
|
409
409
|
- spec/spec_helper.rb
|
410
410
|
- spec/store/mongo_spec.rb
|
411
|
+
- spec/tasks/channel_tasks_spec.rb
|
411
412
|
- spec/templates/targets/binding_document/component_node_spec.rb
|
412
413
|
- spec/templates/template_binding_spec.rb
|
413
414
|
- templates/.gitignore
|
@@ -493,6 +494,7 @@ test_files:
|
|
493
494
|
- spec/server/template_parser_spec.rb
|
494
495
|
- spec/spec_helper.rb
|
495
496
|
- spec/store/mongo_spec.rb
|
497
|
+
- spec/tasks/channel_tasks_spec.rb
|
496
498
|
- spec/templates/targets/binding_document/component_node_spec.rb
|
497
499
|
- spec/templates/template_binding_spec.rb
|
498
500
|
has_rdoc:
|