lib/rydux/store.rb in rydux-0.9.2 vs lib/rydux/store.rb in rydux-0.9.3

- old
+ new

@@ -5,17 +5,25 @@ def initialize(reducers) @state, @listeners = {}, [] @reducers = strap_reducers(reducers) end - def subscribe(listener) - @listeners << listener + # Allow subscribing either by passing a reference to self + # or by passing a block which defines the state keys that + # this listener cares about + def subscribe(caller = nil, &block) + if block_given? + notify_when = block.call(state) + @listeners << { obj: block.binding.receiver, notify_when: notify_when } + else + @listeners << { obj: caller } + end end # Unsubscribes a listener from the store def abandon(listener) - @listeners.delete(listener) + @listeners.delete_if {|l| l[:obj] == listener } end # Dispatches an action to all reducers. Can be called any of the following ways: # Takes in an action and an optional callback proc, which will be called after the # dispatch is finished. @@ -55,24 +63,28 @@ end # Argument 1 should always be the key within state that we're mutating # Argument 2 should be the actual state object def set_state(k, v) - @state[k] = v + if @state[k] != v # Only set state if it has actually changed + @state[k] = v - if !self.methods.include? k - self.define_singleton_method(k.to_sym) do - return State.new(@state[k]) + if !self.methods.include? k + self.define_singleton_method(k.to_sym) do + return State.new(@state[k]) + end end - end - notify_listeners + notify_listeners(k) + end end - def notify_listeners + def notify_listeners(state_key) @listeners.each do |listener| - if listener.respond_to? :state_changed - listener.public_send(:state_changed, state) + # If no notify_when, the user wants ALL state notifications + # Otherwise, only send the state notifications they've subscribed to. + if (!listener[:notify_when] || listener[:notify_when].include?(state_key)) && listener[:obj].respond_to?(:state_changed) + listener[:obj].public_send(:state_changed, state) end end end end