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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6dc382e28cc1e24d1fc62104d3eac49143a473f0
4
- data.tar.gz: d9cfbd13dfb26f582c15f11dde6167ce107f00c3
3
+ metadata.gz: d5fa5dd92e489dfa4a0257eccd5509aa2324cb25
4
+ data.tar.gz: 21e58768017cd4b82ec09ee9b9b06a828d3289e8
5
5
  SHA512:
6
- metadata.gz: c40b106ac5195a1df566437905708891744f290e8386c29897c235657d9e4c945ae87dda6582e908261b04c6510583478aabdcd994d78ba1f82468d306a62739
7
- data.tar.gz: ff4b2bc4553bc7829ab50162c3f848cf98535d06eb5b03af03cc0840066135de5c8fe27568b5798fe04972c10e6a2bb4b4c1839b1efbc4890533d64595fb2937
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.7
1
+ 0.4.8
@@ -1,23 +1,45 @@
1
1
  class ChannelTasks
2
2
  @@listeners = {}
3
+ @@channel_listeners = {}
3
4
 
4
- def initialize(channel, dispatcher)
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
- puts "DATA: #{data.merge('_id' => id).symbolize_keys.inspect}"
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/channel_handler_stub'
15
+ require 'volt/server/socket_connection_handler_stub'
16
16
 
17
- ChannelHandlerStub.dispatcher = Dispatcher.new
17
+ SocketConnectionHandlerStub.dispatcher = Dispatcher.new
18
18
 
19
19
 
20
20
  app_path = File.expand_path(File.join(Dir.pwd, "app"))
@@ -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
- $page.tasks.call('ChannelTasks', "#{add_or_remove}_listener", channel_name)
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 ChannelHandlerStub.
9
+ # them directly to SocketConnectionHandlerStub.
10
10
  class ChannelStub
11
11
  include ReactiveTags
12
12
 
@@ -0,0 +1,9 @@
1
+ class DrawCycle
2
+ def initialize
3
+ @queue = {}
4
+ end
5
+
6
+ def queue(binding)
7
+
8
+ end
9
+ end
@@ -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/render_queue'
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, :render_queue
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
- @render_queue = RenderQueue.new
53
+ @draw_cycle = DrawCycle.new
54
54
 
55
55
  if RUBY_PLATFORM == 'opal'
56
56
  # Setup escape binding for console
@@ -31,8 +31,10 @@ class Tasks
31
31
  case name
32
32
  when 'response'
33
33
  response(callback_id, *args)
34
- when 'update'
35
- update(*args)
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 update(model_id, data)
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
@@ -1,4 +1,4 @@
1
- # Used to get a list of the assets from the dependencies
1
+ # Used to get a list of the assets from the dependencies files.
2
2
  class AssetFiles
3
3
  def initialize(component_name, component_paths)
4
4
  @component_paths = component_paths
@@ -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
- ComponentFiles.new('home', @component_paths, true).javascript_files(@opal_files)
43
+ AssetFiles.new('home', @component_paths).javascript_files(@opal_files)
44
44
  end
45
45
 
46
46
  def css_files
47
- ComponentFiles.new('home', @component_paths, true).css_files
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 ChannelHandler < SockJS::Session
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 ChannelHandlerStub
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/channel_handler'
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
- ChannelHandler.send_message_all(nil, 'reload')
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
- ChannelHandler.dispatcher = Dispatcher.new
97
+ SocketConnectionHandler.dispatcher = Dispatcher.new
98
98
 
99
99
  @app.map "/channel" do
100
- run Rack::SockJS.new(ChannelHandler)#, :websocket => false
100
+ run Rack::SockJS.new(SocketConnectionHandler)#, :websocket => false
101
101
  end
102
102
  end
103
103
 
@@ -12,7 +12,6 @@ class Dispatcher
12
12
 
13
13
  # Get the class
14
14
  klass = Object.send(:const_get, class_name)
15
- puts "KLASS: #{klass.inspect}"
16
15
 
17
16
  # Init and send the method
18
17
  result = klass.new(channel, self).send(method_name, *args)
@@ -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.7
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-23 00:00:00.000000000 Z
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:
@@ -1,5 +0,0 @@
1
- class RenderQueue
2
- def initialize
3
- # @queue
4
- end
5
- end