volt 0.3.7 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/volt/assets/css/notices.css.scss +8 -0
  4. data/app/volt/tasks/channel_tasks.rb +33 -0
  5. data/app/volt/tasks/store_tasks.rb +45 -0
  6. data/app/volt/views/notices/index.html +11 -0
  7. data/lib/volt/controllers/model_controller.rb +4 -0
  8. data/lib/volt/models/array_model.rb +11 -1
  9. data/lib/volt/models/model.rb +22 -14
  10. data/lib/volt/models/model_wrapper.rb +13 -6
  11. data/lib/volt/models/params.rb +6 -1
  12. data/lib/volt/models/params_array.rb +9 -0
  13. data/lib/volt/models/store.rb +164 -0
  14. data/lib/volt/models/store_array.rb +15 -0
  15. data/lib/volt/models/url.rb +0 -4
  16. data/lib/volt/models.rb +1 -0
  17. data/lib/volt/{templates → page/bindings}/attribute_binding.rb +8 -7
  18. data/lib/volt/{templates → page/bindings}/base_binding.rb +6 -1
  19. data/lib/volt/{templates → page/bindings}/content_binding.rb +1 -1
  20. data/lib/volt/{templates → page/bindings}/each_binding.rb +15 -6
  21. data/lib/volt/{templates → page/bindings}/event_binding.rb +1 -5
  22. data/lib/volt/{templates → page/bindings}/if_binding.rb +1 -1
  23. data/lib/volt/{templates → page/bindings}/template_binding.rb +16 -7
  24. data/lib/volt/page/channel.rb +105 -0
  25. data/lib/volt/{templates → page}/document_events.rb +0 -0
  26. data/lib/volt/{templates → page}/memory_test.rb +0 -0
  27. data/lib/volt/{templates → page}/page.rb +22 -21
  28. data/lib/volt/{templates → page}/reactive_template.rb +0 -0
  29. data/lib/volt/{templates → page}/render_queue.rb +0 -0
  30. data/lib/volt/{templates → page}/sub_context.rb +0 -0
  31. data/lib/volt/{templates → page}/targets/attribute_section.rb +1 -1
  32. data/lib/volt/{templates → page}/targets/attribute_target.rb +4 -4
  33. data/lib/volt/{templates → page}/targets/base_section.rb +0 -0
  34. data/lib/volt/{templates → page}/targets/binding_document/base_node.rb +0 -0
  35. data/lib/volt/{templates → page}/targets/binding_document/component_node.rb +1 -1
  36. data/lib/volt/{templates → page}/targets/binding_document/html_node.rb +1 -1
  37. data/lib/volt/{templates → page}/targets/dom_section.rb +1 -1
  38. data/lib/volt/{templates → page}/targets/dom_target.rb +2 -2
  39. data/lib/volt/page/tasks.rb +61 -0
  40. data/lib/volt/{templates → page}/template_renderer.rb +1 -1
  41. data/lib/volt/reactive/destructive_methods.rb +19 -0
  42. data/lib/volt/reactive/event_chain.rb +13 -19
  43. data/lib/volt/reactive/events.rb +30 -116
  44. data/lib/volt/reactive/object_tracker.rb +29 -22
  45. data/lib/volt/reactive/reactive_array.rb +2 -3
  46. data/lib/volt/reactive/reactive_tags.rb +7 -0
  47. data/lib/volt/reactive/reactive_value.rb +86 -81
  48. data/lib/volt/reactive/string_extensions.rb +0 -3
  49. data/lib/volt/router/routes.rb +2 -2
  50. data/lib/volt/server/channel_handler.rb +24 -4
  51. data/lib/volt/server/component_handler.rb +2 -1
  52. data/lib/volt/server/rack/component_files.rb +3 -2
  53. data/lib/volt/server/rack/component_paths.rb +11 -1
  54. data/lib/volt/server/rack/index_files.rb +1 -1
  55. data/lib/volt/server.rb +16 -0
  56. data/lib/volt/store/mongo.rb +1 -1
  57. data/lib/volt/tasks/dispatcher.rb +25 -0
  58. data/spec/models/model_spec.rb +90 -15
  59. data/spec/models/params_spec.rb +16 -0
  60. data/spec/models/reactive_array_spec.rb +17 -18
  61. data/spec/models/reactive_value_spec.rb +11 -0
  62. data/spec/models/store_spec.rb +16 -0
  63. data/spec/server/rack/component_files_spec.rb +18 -16
  64. data/spec/server/rack/component_paths_spec.rb +21 -19
  65. data/spec/templates/targets/binding_document/component_node_spec.rb +1 -1
  66. data/spec/templates/template_binding_spec.rb +1 -1
  67. data/templates/project/app/home/views/index/index.html +2 -0
  68. data/volt.gemspec +2 -0
  69. metadata +67 -25
  70. data/lib/volt/templates/channel.rb +0 -47
@@ -1,5 +1,5 @@
1
- require 'volt/templates/base_binding'
2
- require 'volt/templates/template_renderer'
1
+ require 'volt/page/bindings/base_binding'
2
+ require 'volt/page/template_renderer'
3
3
 
4
4
  class TemplateBinding < BaseBinding
5
5
  def initialize(target, context, binding_name, binding_in_path, getter)
@@ -131,7 +131,7 @@ class TemplateBinding < BaseBinding
131
131
  controller = get_controller(controller_name)
132
132
 
133
133
  # Initialize the new controller
134
- current_context = controller.new(*args)
134
+ current_context = (ModelController || controller).new(*args)
135
135
  elsif @model
136
136
  # Passed in attributes, but there is no controller
137
137
  current_context = SubContext.new(@model, current_context)
@@ -169,14 +169,23 @@ class TemplateBinding < BaseBinding
169
169
  # For the home object, we do not need to namespace our controller
170
170
  if controller_name[0] != 'home'
171
171
  # Controller is namespaced, lookup outer module first
172
- base_name = controller_name[0].camelize
173
- base_object = Object.send(:const_get, base_name.to_sym)
172
+ base_name = controller_name[0].camelize.to_sym
173
+ if Object.send(:const_defined?, base_name)
174
+ base_object = Object.send(:const_get, base_name)
175
+ end
174
176
  else
175
177
  # Get controller directlry
176
178
  base_object = Object
177
179
  end
178
-
179
- base_object.send(:const_get, (name + 'Controller').to_sym)
180
+
181
+ if base_object
182
+ name = (name + 'Controller').to_sym
183
+ if base_object.send(:const_defined?, name)
184
+ return base_object.send(:const_get, name)
185
+ end
186
+ end
187
+
188
+ return nil
180
189
  end
181
190
 
182
191
  end
@@ -0,0 +1,105 @@
1
+ # The channel is the connection between the front end and the backend.
2
+
3
+ require 'volt/reactive/events'
4
+ require 'json'
5
+
6
+ class Channel
7
+ include ReactiveTags
8
+
9
+ attr_reader :state, :error, :reconnect_interval
10
+
11
+ def initialize
12
+ @socket = nil
13
+ @state = :opening
14
+ @error = nil
15
+ @queue = []
16
+
17
+ connect!
18
+ end
19
+
20
+ def connect!
21
+ %x{
22
+ this.socket = new SockJS('http://localhost:3000/channel');
23
+
24
+ this.socket.onopen = function() {
25
+ self.$opened();
26
+ };
27
+
28
+ this.socket.onmessage = function(message) {
29
+ self['$message_received'](message.data);
30
+ };
31
+
32
+ this.socket.onclose = function(error) {
33
+ self.$closed(error);
34
+ };
35
+ }
36
+ end
37
+
38
+ def opened
39
+ @state = :open
40
+ @reconnect_interval = nil
41
+ @queue.each do |message|
42
+ send_message(message)
43
+ end
44
+
45
+ trigger!('open')
46
+ trigger!('changed')
47
+ end
48
+
49
+ def closed(error)
50
+ @state = :closed
51
+ @error = `error.reason`
52
+
53
+ trigger!('closed')
54
+ trigger!('changed')
55
+
56
+ reconnect!
57
+ end
58
+
59
+ def reconnect!
60
+ @reconnect_interval ||= 0
61
+ @reconnect_interval += (2000 + rand(5000))
62
+
63
+ # Trigger changed for reconnect interval
64
+ trigger!('changed')
65
+
66
+ interval = @reconnect_interval
67
+
68
+ %x{
69
+ setTimeout(function() {
70
+ self['$connect!']();
71
+ }, interval);
72
+ }
73
+ end
74
+
75
+ def message_received(message)
76
+ message = JSON.parse(message)
77
+ # puts "GOT: #{message.inspect}"
78
+ trigger!('message', nil, *message)
79
+ end
80
+
81
+ tag_method(:send_message) do
82
+ destructive!
83
+ end
84
+ def send_message(message)
85
+ `console.log('do send message');`
86
+ puts "Send #{message.inspect}"
87
+ if @state != :open
88
+ @queue << message
89
+ puts "Queue"
90
+ else
91
+ # TODO: Temp: wrap message in an array, so we're sure its valid JSON
92
+ message = JSON.dump([message])
93
+ %x{
94
+ this.socket.send(message);
95
+ }
96
+ end
97
+ end
98
+
99
+ def close!
100
+ @state = :closed
101
+ %x{
102
+ this.socket.close();
103
+ }
104
+ end
105
+ end
File without changes
File without changes
@@ -6,24 +6,25 @@ require 'opal-jquery'
6
6
  require 'volt/models'
7
7
  require 'volt/models/params'
8
8
  require 'volt/controllers/model_controller'
9
- require 'volt/templates/attribute_binding'
10
- require 'volt/templates/content_binding'
11
- require 'volt/templates/each_binding'
12
- require 'volt/templates/if_binding'
13
- require 'volt/templates/template_binding'
14
- require 'volt/templates/template_renderer'
15
- require 'volt/templates/reactive_template'
16
- require 'volt/templates/event_binding'
17
- require 'volt/templates/document_events'
18
- require 'volt/templates/sub_context'
19
- require 'volt/templates/targets/dom_target'
20
- require 'volt/templates/channel'
9
+ require 'volt/page/bindings/attribute_binding'
10
+ require 'volt/page/bindings/content_binding'
11
+ require 'volt/page/bindings/each_binding'
12
+ require 'volt/page/bindings/if_binding'
13
+ require 'volt/page/bindings/template_binding'
14
+ require 'volt/page/bindings/event_binding'
15
+ require 'volt/page/template_renderer'
16
+ require 'volt/page/reactive_template'
17
+ require 'volt/page/document_events'
18
+ require 'volt/page/sub_context'
19
+ require 'volt/page/targets/dom_target'
20
+ require 'volt/page/channel'
21
21
  require 'volt/router/routes'
22
22
  require 'volt/models/url'
23
23
  require 'volt/page/url_tracker'
24
24
  require 'volt'
25
25
  require 'volt/benchmark/benchmark'
26
- require 'volt/templates/render_queue'
26
+ require 'volt/page/render_queue'
27
+ require 'volt/page/tasks'
27
28
 
28
29
  class Page
29
30
  attr_reader :url, :params, :page, :store, :templates, :routes, :render_queue
@@ -36,7 +37,7 @@ class Page
36
37
 
37
38
  # Run the code to setup the page
38
39
  @page = ReactiveValue.new(Model.new)#({}, nil, 'page', @model_classes))
39
- @store = ReactiveValue.new(Model.new)#({}, nil, 'store', @model_classes))
40
+ @store = ReactiveValue.new(Store.new(tasks))#({}, nil, 'store', @model_classes))
40
41
 
41
42
  @url = ReactiveValue.new(URL.new)
42
43
  @params = @url.params
@@ -63,10 +64,10 @@ class Page
63
64
  return false;
64
65
  });
65
66
  }
66
-
67
- channel.on('message') do |message|
68
- puts "GOT: #{message}"
69
- end
67
+ end
68
+
69
+ def tasks
70
+ @tasks ||= Tasks.new(self)
70
71
  end
71
72
 
72
73
  def link_clicked(url)
@@ -74,9 +75,9 @@ class Page
74
75
  return if url.blank?
75
76
 
76
77
  # Normalize url
77
- # Benchmark.bm(1) do
78
+ Benchmark.bm(1) do
78
79
  @url.parse("http://localhost:3000" + url)
79
- # end
80
+ end
80
81
  end
81
82
 
82
83
  # We provide a binding_name, so we can bind events on the document
@@ -89,7 +90,7 @@ class Page
89
90
  end
90
91
 
91
92
  def channel
92
- @channel ||= Channel.new
93
+ @channel ||= ReactiveValue.new(Channel.new)
93
94
  end
94
95
 
95
96
  def events
File without changes
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  # AttributeSection provides a place to render templates that
2
2
  # will be placed as text into an attribute.
3
3
 
4
- require 'volt/templates/targets/base_section'
4
+ require 'volt/page/targets/base_section'
5
5
 
6
6
  class AttributeSection
7
7
  def initialize(target, binding_name)
@@ -1,7 +1,7 @@
1
- require 'volt/templates/targets/base_section'
2
- require 'volt/templates/targets/attribute_section'
3
- require 'volt/templates/targets/binding_document/component_node'
4
- require 'volt/templates/targets/binding_document/html_node'
1
+ require 'volt/page/targets/base_section'
2
+ require 'volt/page/targets/attribute_section'
3
+ require 'volt/page/targets/binding_document/component_node'
4
+ require 'volt/page/targets/binding_document/html_node'
5
5
 
6
6
  # AttributeTarget's provide an interface that can render bindings into
7
7
  # a string that can then be used to update a attribute binding.
@@ -1,4 +1,4 @@
1
- require 'volt/templates/targets/binding_document/html_node'
1
+ require 'volt/page/targets/binding_document/html_node'
2
2
  require 'volt/reactive/events'
3
3
 
4
4
  # Component nodes contain an array of both HtmlNodes and ComponentNodes.
@@ -1,4 +1,4 @@
1
- require 'volt/templates/targets/binding_document/base_node'
1
+ require 'volt/page/targets/binding_document/base_node'
2
2
 
3
3
  class HtmlNode < BaseNode
4
4
  def initialize(html)
@@ -1,4 +1,4 @@
1
- require 'volt/templates/targets/base_section'
1
+ require 'volt/page/targets/base_section'
2
2
 
3
3
  class DomSection < BaseSection
4
4
  def initialize(binding_name)
@@ -1,5 +1,5 @@
1
- require 'volt/templates/targets/base_section'
2
- require 'volt/templates/targets/dom_section'
1
+ require 'volt/page/targets/base_section'
2
+ require 'volt/page/targets/dom_section'
3
3
 
4
4
  # DomTarget's provide an interface that can render bindings into
5
5
  # the dom. Currently only one "dom" is supported, but multiple
@@ -0,0 +1,61 @@
1
+ # The tasks class provides an interface to call tasks on
2
+ # the backend server.
3
+ class Tasks
4
+ def initialize(page)
5
+ @page = page
6
+ @callback_id = 0
7
+ @callbacks = {}
8
+
9
+ page.channel.on('message') do |_, *args|
10
+ received_message(*args)
11
+ end
12
+ end
13
+
14
+ def call(class_name, method_name, *args, &callback)
15
+ if callback
16
+ callback_id = @callback_id
17
+ @callback_id += 1
18
+
19
+ # Track the callback
20
+ # TODO: Timeout on these callbacks
21
+ @callbacks[callback_id] = callback
22
+ else
23
+ callback_id = nil
24
+ end
25
+
26
+ @page.channel.send_message([callback_id, class_name, method_name, *args])
27
+ end
28
+
29
+
30
+ def received_message(name, callback_id, *args)
31
+ case name
32
+ when 'response'
33
+ response(callback_id, *args)
34
+ when 'update'
35
+ update(*args)
36
+ when 'reload'
37
+ reload
38
+ end
39
+ end
40
+
41
+ def response(callback_id, *args)
42
+ callback = @callbacks.delete(callback_id)
43
+
44
+ if callback
45
+ callback.call(*args)
46
+ end
47
+ end
48
+
49
+ def update(model_id, data)
50
+ $loading_models = true
51
+ puts "UPDATE: #{model_id} with #{data.inspect}"
52
+ Store.update(model_id, data)
53
+ $loading_models = false
54
+ end
55
+
56
+ def reload
57
+ puts "RELOAD"
58
+ $page.page._reloading = true
59
+ `window.location.reload(false);`
60
+ end
61
+ end
@@ -1,4 +1,4 @@
1
- require 'volt/templates/base_binding'
1
+ require 'volt/page/bindings/base_binding'
2
2
 
3
3
  class TemplateRenderer < BaseBinding
4
4
  attr_reader :context
@@ -0,0 +1,19 @@
1
+ # DestructiveMethods tracks the names of all methods that are marked as
2
+ # destructive. This lets us do an optimization where we don't need to
3
+ # check any methods with names that aren't here, we can be sure that they
4
+ # are not destructive. If the method is tracked here, we need to check
5
+ # it on its current class.
6
+ class DestructiveMethods
7
+ @@method_names = {}
8
+
9
+ def self.add_method(method_name)
10
+ @@method_names[method_name] = true
11
+ end
12
+
13
+ # Check to see if a method might be destructive. If this returns
14
+ # false, then we can guarentee that it won't be destructive and
15
+ # we can skip a destructive check.
16
+ def self.might_be_destructive?(method_name)
17
+ return @@method_names[method_name]
18
+ end
19
+ end
@@ -40,40 +40,34 @@ class EventChain
40
40
 
41
41
  # Register an event listener that chains from object to self
42
42
  def setup_listener(event, chain_listener)
43
- return chain_listener.object.on(event, @main_object) do |*args|
43
+ return chain_listener.object.on(event, @main_object) do |filter, *args|
44
44
  if callback = chain_listener.callback
45
- callback.call(event, *args)
45
+ callback.call(event, filter, *args)
46
46
  else
47
47
  # Trigger on this value, when it happens on the parent
48
- @main_object.trigger!(event, *args)
48
+
49
+ # Only pass the filter from non-reactive to reactive? This
50
+ # lets us scope the calls on a proxied object.
51
+ # Filters limit which listeners are triggered, passing them to
52
+ # the ReactiveValue's from non-reactive lets us filter at the
53
+ # reactive level as well.
54
+ filter = nil unless !chain_listener.object.reactive? && @main_object.reactive?
55
+
56
+ @main_object.trigger!(event, filter, *args)
49
57
  end
50
58
  end
51
59
  end
52
-
53
- def all_listening_events
54
- all_listeners = []
55
- all_listeners += @main_object.listeners.keys
56
-
57
- if @main_object
58
- @main_object.event_followers.each do |event_follower|
59
- all_listeners += event_follower.listeners.keys
60
- end
61
- end
62
60
 
63
- return all_listeners.uniq
64
- end
65
-
66
-
67
61
  # We can chain our events to any other object that includes
68
62
  # Events
69
63
  def add_object(object, &block)
70
64
  # puts "ADD OBJECT: #{object.inspect} to #{self.inspect}"
71
-
65
+
72
66
  chain_listener = ChainListener.new(self, object, block)
73
67
 
74
68
  listeners = {}
75
69
 
76
- all_listening_events.uniq.each do |event|
70
+ @main_object.listeners.keys.each do |event|
77
71
  # Create a listener for each event
78
72
  listeners[event] = setup_listener(event, chain_listener)
79
73
  end
@@ -6,7 +6,7 @@ DEBUG = false
6
6
  # A listener gets returned when adding an 'on' event listener. It can be
7
7
  # used to clear the event listener.
8
8
  class Listener
9
- attr_reader :scope_provider
9
+ attr_reader :scope_provider, :klass
10
10
 
11
11
  def initialize(klass, event, scope_provider, callback)
12
12
  @klass = klass
@@ -43,13 +43,13 @@ class Listener
43
43
  end
44
44
 
45
45
  def scope
46
- @scope_provider && @scope_provider.scope
46
+ @scope_provider && scope_provider.respond_to?(:scope) && @scope_provider.scope
47
47
  end
48
48
 
49
49
  def call(*args)
50
50
  # raise "Triggered on removed: #{@event} on #{@klass2.inspect}" if @removed
51
51
  if @removed
52
- puts "Triggered on removed: #{@event}"
52
+ puts "Triggered on a removed event: #{@event}"
53
53
  return
54
54
  end
55
55
 
@@ -98,7 +98,6 @@ class Listener
98
98
  end
99
99
 
100
100
  module Events
101
- attr_accessor :scope
102
101
  # Add a listener for an event
103
102
  def on(event, scope_provider=nil, &block)
104
103
  # puts "Register: #{event} on #{self.inspect}"
@@ -111,7 +110,10 @@ module Events
111
110
  @listeners[event] << new_listener
112
111
 
113
112
  first = @listeners[event].size == 1
114
- add_event_to_chains(event) if first
113
+
114
+ # When events get added, we need to notify event chains so they
115
+ # can update and chain any new events.
116
+ event_chain.add_event(event) if first
115
117
 
116
118
  # Let the included class know that an event was registered. (if it cares)
117
119
  if self.respond_to?(:event_added)
@@ -144,7 +146,9 @@ module Events
144
146
 
145
147
  no_more_events = @listeners[event].size == 0
146
148
  if no_more_events
147
- remove_event_from_chains(event)
149
+ # When events are removed, we need to notify any relevent chains so they
150
+ # can remove any chained events.
151
+ event_chain.remove_event(event)
148
152
 
149
153
  # No registered listeners now on this event
150
154
  @listeners.delete(event)
@@ -157,110 +161,29 @@ module Events
157
161
  end
158
162
  # end
159
163
  end
160
-
161
- # When events get added, we need to notify event chains so they
162
- # can update and chain any new events.
163
- def add_event_to_chains(event)
164
- # First time this event is added, update any chains
165
- event_chain.add_event(event)
166
-
167
- # We need to keep the event chain's updated for any objects we're
168
- # following for events.
169
- event_followings.each {|ef| ef.event_chain.add_event(event) }
170
-
171
- if event != :changed && !@other_event_listener
172
- @other_event_listener = on('changed') { }
173
- end
174
- end
175
-
176
- # When events are removed, we need to notify any relevent chains so they
177
- # can remove any chained events.
178
- def remove_event_from_chains(event)
179
- event_chain.remove_event(event)
180
164
 
181
- # We need to keep the event chain's updated for any objects we're
182
- # following for events.
183
- event_followings.each {|ef| ef.event_chain.remove_event(event) }
184
-
185
- if event != :changed
186
- # See if there are any remaining events that aren't changed
187
- if listeners.keys.reject {|k| k == :changed }.size == 0
188
- @other_event_listener.remove
189
- @other_event_listener = nil
190
- end
191
- end
192
- end
193
-
194
-
195
- # Track the current object that we're following.
196
- def event_followings
197
- @event_followings || []
198
- end
199
-
200
- def add_following(object)
201
- @event_followings ||= []
202
- @event_followings << object
203
-
204
- # Take all of our listeners and add them to the
205
- listeners.keys.each do |event|
206
- object.event_chain.add_event(event)
207
- end
208
- end
209
-
210
- def remove_following(object)
211
- @event_followings.delete(object)
212
-
213
- listeners.keys.each do |event|
214
- object.event_chain.remove_event(event)
215
- end
216
- end
217
-
218
- # Track who's following us
219
- def event_followers
220
- @event_followers || []
221
- end
222
-
223
- def add_event_follower(follower)
224
- @event_followers ||= []
225
- @event_followers << follower
226
-
227
- follower.add_following(self)
228
- end
229
-
230
- def remove_event_follower(follower)
231
- if @event_followers
232
- @event_followers.delete(follower)
233
-
234
- follower.remove_following(self)
235
- end
236
- end
237
-
238
- # Return all listeners for an event on the current object and any event
239
- # following objects.
240
- def all_listeners_for(event)
241
- # TODO: We dup at the moment because some events unregister events, is there
242
- # a better solution than this?
243
- all_listeners = []
244
- all_listeners += @listeners[event].dup if @listeners && @listeners[event]
245
-
246
- if @event_followers
247
- @event_followers.each do |event_follower|
248
- ef_listeners = event_follower.listeners
249
- all_listeners += ef_listeners[event].dup if ef_listeners[event]
250
- end
251
- end
252
-
253
- return all_listeners
254
- end
255
-
256
- def trigger!(event, *args)
257
- ObjectTracker.process_queue if !reactive? && !respond_to?(:skip_current_queue_flush)
165
+ def trigger!(event, filter=nil, *args)
166
+ are_reactive = reactive?
167
+ # puts "TRIGGER FOR: #{event} on #{self.inspect}" if !reactive?
168
+ ObjectTracker.process_queue if !are_reactive# && !respond_to?(:skip_current_queue_flush)
258
169
 
259
170
  event = event.to_sym
260
171
 
261
- all_listeners_for(event).each do |listener|
262
- # Call the event on each listener
263
- listener.call(*args)
172
+ if @listeners && @listeners[event]
173
+ # puts "LISTENERS FOR #{event} on #{self.inspect} - #{@listeners[event].inspect}"
174
+ # TODO: We have to dup here because one trigger might remove another
175
+ @listeners[event].dup.each do |listener|
176
+ # Call the event on each listener
177
+ # If there is no listener, that means another event trigger removed it.
178
+ # If there is no filter, call
179
+ # if we aren't reactive, we should pass to all of our reactive listeners, since they
180
+ # just proxy us.
181
+ # If the filter exists, check it
182
+ # puts "CHECK #{listener.inspect} : #{self.inspect} -- #{listener.klass.inspect}"
183
+ if (!filter || (!are_reactive && listener.scope_provider.reactive?) || filter.call(listener.scope))
184
+ listener.call(filter, *args)
185
+ end
186
+ end
264
187
  end
265
188
 
266
189
  nil
@@ -268,16 +191,7 @@ module Events
268
191
 
269
192
  # Takes a block, which passes in
270
193
  def trigger_by_scope!(event, *args, &block)
271
- ObjectTracker.process_queue if !reactive? && !respond_to?(:skip_current_queue_flush)
272
-
273
- event = event.to_sym
274
-
275
- all_listeners_for(event).each do |listener|
276
- # Call the block, pass in the scope
277
- if block.call(listener.scope)
278
- listener.call(*args)
279
- end
280
- end
194
+ trigger!(event, block, *args)
281
195
  end
282
196
 
283
197
  end