Class: Vedeu::Events::Event

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Repositories::Model
Defined in:
lib/vedeu/events/event.rb

Overview

Contains all the logic of an event. Handles debouncing and throttling.

Vedeu provides an event mechanism to facilitate the functionality of your application. The events are either Vedeu defined, ie. system events or user defined, ie. user events. User events allow you to orchestrate behaviour within your application, ie. the user presses a specific key, you trigger an event to make something happen. Eg. pressing ‘p’ instructs the player to play.

Events described here assume that you have bound the events within your classes:

class SomeClassInYourApplication
  Vedeu.bind(:event_name) do |arg1, arg2|
    # Things that should happen when the event is triggered;
    # these can be method calls or the triggering of another
    # event or events.
  end

  Vedeu.bind(:event_name) do
    # Not all events you define will have arguments; like
    # methods.
    :do_stuff
  end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, closure, options = {}) ⇒ Vedeu::Events::Event

Returns a new instance of Vedeu::Events::Event.



137
138
139
140
141
142
143
144
145
# File 'lib/vedeu/events/event.rb', line 137

def initialize(name, closure, options = {})
  @name         = name
  @options      = options
  @closure      = closure
  @deadline     = 0
  @executed_at  = 0
  @now          = 0
  @repository   = Vedeu.events
end

Instance Attribute Details

#closureString (readonly, protected)



179
180
181
# File 'lib/vedeu/events/event.rb', line 179

def closure
  @closure
end

#nameString (readonly, protected)



183
184
185
# File 'lib/vedeu/events/event.rb', line 183

def name
  @name
end

#repositoryVedeu::Repositories::Repository Originally defined in module Repositories::Model

Class Method Details

.bind(name, options = {}, &block) ⇒ TrueClass

Register an event by name with optional delay (throttling) which when triggered will execute the code contained within the passed block.

Examples:

Vedeu.bind :my_event do |some, args|
  # ... some code here ...

  Vedeu.trigger(:my_other_event)
end

T = Triggered, X = Executed, i = Ignored.

0.0.....0.2.....0.4.....0.6.....0.8.....1.0.....1.2.....1.4.....1.6.
.T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T..
.X...i...i...i...i...X...i...i...i...i...X...i...i...i...i...i...i..

Vedeu.bind(:my_delayed_event, { delay: 0.5 })
  # ... some code here ...
end

T = Triggered, X = Executed, i = Ignored.

0.0.....0.2.....0.4.....0.6.....0.8.....1.0.....1.2.....1.4.....1.6.
.T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T..
.i...i...i...i...i...i...i...X...i...i...i...i...i...i...X...i...i..

Vedeu.bind(:my_debounced_event, { debounce: 0.7 })
  # ... some code here ...
end

Options Hash (options):

  • :delay (Fixnum|Float)

    Limits the execution of the triggered event to only execute when first triggered, with subsequent triggering being ignored until the delay has expired.

  • :debounce (Fixnum|Float)

    Limits the execution of the triggered event to only execute once the debounce has expired. Subsequent triggers before debounce expiry are ignored.



86
87
88
89
90
# File 'lib/vedeu/events/event.rb', line 86

def bind(name, options = {}, &block)
  Vedeu.log(type: :event, message: "Binding: '#{name.inspect}'".freeze)

  new(name, block, options).bind
end

.bound?(name) ⇒ Boolean

Return a boolean indicating whether the named event is registered.

Examples:

Vedeu.bound?(:some_event)


102
103
104
105
# File 'lib/vedeu/events/event.rb', line 102

def bound?(name)
  Vedeu.events.registered?(name) ||
    Vedeu::Events::Aliases.registered?(name)
end

.eventTrueClass

Register an event by name with optional delay (throttling) which when triggered will execute the code contained within the passed block.

Examples:

Vedeu.bind :my_event do |some, args|
  # ... some code here ...

  Vedeu.trigger(:my_other_event)
end

T = Triggered, X = Executed, i = Ignored.

0.0.....0.2.....0.4.....0.6.....0.8.....1.0.....1.2.....1.4.....1.6.
.T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T..
.X...i...i...i...i...X...i...i...i...i...X...i...i...i...i...i...i..

Vedeu.bind(:my_delayed_event, { delay: 0.5 })
  # ... some code here ...
end

T = Triggered, X = Executed, i = Ignored.

0.0.....0.2.....0.4.....0.6.....0.8.....1.0.....1.2.....1.4.....1.6.
.T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T..
.i...i...i...i...i...i...i...X...i...i...i...i...i...i...X...i...i..

Vedeu.bind(:my_debounced_event, { debounce: 0.7 })
  # ... some code here ...
end


91
92
93
94
95
# File 'lib/vedeu/events/event.rb', line 91

def bind(name, options = {}, &block)
  Vedeu.log(type: :event, message: "Binding: '#{name.inspect}'".freeze)

  new(name, block, options).bind
end

.registerTrueClass

Register an event by name with optional delay (throttling) which when triggered will execute the code contained within the passed block.

Examples:

Vedeu.bind :my_event do |some, args|
  # ... some code here ...

  Vedeu.trigger(:my_other_event)
end

T = Triggered, X = Executed, i = Ignored.

0.0.....0.2.....0.4.....0.6.....0.8.....1.0.....1.2.....1.4.....1.6.
.T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T..
.X...i...i...i...i...X...i...i...i...i...X...i...i...i...i...i...i..

Vedeu.bind(:my_delayed_event, { delay: 0.5 })
  # ... some code here ...
end

T = Triggered, X = Executed, i = Ignored.

0.0.....0.2.....0.4.....0.6.....0.8.....1.0.....1.2.....1.4.....1.6.
.T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T...T..
.i...i...i...i...i...i...i...X...i...i...i...i...i...i...X...i...i..

Vedeu.bind(:my_debounced_event, { debounce: 0.7 })
  # ... some code here ...
end


92
93
94
95
96
# File 'lib/vedeu/events/event.rb', line 92

def bind(name, options = {}, &block)
  Vedeu.log(type: :event, message: "Binding: '#{name.inspect}'".freeze)

  new(name, block, options).bind
end

.unbind(name) ⇒ Boolean

Unbind events from a named handler.

Removes all events associated with the given name.

Examples:

Vedeu.unbind(:some_event)


116
117
118
119
120
121
122
123
124
125
# File 'lib/vedeu/events/event.rb', line 116

def unbind(name)
  return false unless Vedeu.bound?(name)

  Vedeu.log(type:    :event,
            message: "Unbinding: '#{name.inspect}'".freeze)

  Vedeu.events.remove(name)

  true
end

Instance Method Details

#absent?(variable) ⇒ Boolean Originally defined in module Common

Returns a boolean indicating whether a variable is nil or empty.

#bindObject

See Also:



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/vedeu/events/event.rb', line 148

def bind
  if repository.registered?(name)
    new_collection = repository.find(name).add(self)

  else
    new_collection = Vedeu::Events::Collection.new([self], nil, name)

  end

  repository.store(new_collection)

  true
end

#deadline?Boolean (private)

Returns a boolean indicating whether this event has a deadline.



262
263
264
# File 'lib/vedeu/events/event.rb', line 262

def deadline?
  @deadline > 0
end

#debounceFixnum|Float (private)

Return the amount of time in seconds to debounce the event by.



269
270
271
# File 'lib/vedeu/events/event.rb', line 269

def debounce
  options[:debounce] || defaults[:debounce]
end

#debounce_expired?Boolean (private)

Returns a boolean indicating whether the debounce has expired.



250
251
252
253
254
255
256
# File 'lib/vedeu/events/event.rb', line 250

def debounce_expired?
  return true if (@executed_at = @now) > @deadline

  Vedeu.log(type: :event, message: "Debouncing: '#{name.inspect}'".freeze)

  false
end

#debouncing?Boolean (private)

Returns a boolean indicating whether debouncing is required for this event. Setting the debounce option to any value greater than 0 will enable debouncing. Sets the deadline for when this event can be executed to a point in the future determined by the amount of debounce time left.



239
240
241
242
243
244
245
# File 'lib/vedeu/events/event.rb', line 239

def debouncing?
  @now = Time.now.to_f

  @deadline = @now + debounce unless deadline?

  options[:debounce] > 0
end

#defaultsHash (private)

The default values for a new instance of this class.



291
292
293
294
295
296
# File 'lib/vedeu/events/event.rb', line 291

def defaults
  {
    delay:      0.0,
    debounce:   0.0,
  }
end

#delayFixnum|Float (private)

Return the amount of time in seconds to throttle the event by.



276
277
278
# File 'lib/vedeu/events/event.rb', line 276

def delay
  options[:delay] || defaults[:delay]
end

#demodulize(klass) ⇒ String Originally defined in module Common

Removes the module part from the expression in the string.

Examples:

demodulize('Vedeu::SomeModule::SomeClass') # => "SomeClass"

#deputy(client = nil) ⇒ void Originally defined in module Repositories::Model

This method returns an undefined value.

Returns a DSL instance responsible for defining the DSL methods of this model.

#dsl_classString (private) Originally defined in module Repositories::Model

Returns the DSL class name responsible for this model.

#execute(*args) ⇒ void (private)

This method returns an undefined value.

Execute the code stored in the event closure.



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/vedeu/events/event.rb', line 191

def execute(*args)
  @deadline    = 0    # reset deadline
  @executed_at = @now # set execution time to now
  @now         = 0    # reset now

  message = "Triggering: '#{name.inspect}'"

  if args.size > 1
    message << " with #{args.inspect}"
  elsif args.one?
    message << " for #{args.first.inspect}"
  end

  Vedeu.log(type: :event, message: message)

  closure.call(*args)
end

#optionsHash (private)

Combines the options provided at instantiation with the default values.



284
285
286
# File 'lib/vedeu/events/event.rb', line 284

def options
  defaults.merge!(@options)
end

#present?(variable) ⇒ Boolean Originally defined in module Common

Returns a boolean indicating whether a variable has a useful value.

#snake_case(name) ⇒ String Originally defined in module Common

Converts a class name to a lowercase snake case string.

Examples:

snake_case(MyClassName) # => "my_class_name"
snake_case(NameSpaced::ClassName)
# => "name_spaced/class_name"

#storevoid Originally defined in module Repositories::Model

TODO:

Perhaps some validation could be added here?

Note:

If a block is given, store the model, return the model after yielding.

This method returns an undefined value.

Returns The model instance stored in the repository.

#throttle_expired?Boolean (private)

Returns a boolean indicating whether the throttle has expired.



223
224
225
226
227
228
229
# File 'lib/vedeu/events/event.rb', line 223

def throttle_expired?
  return true if (@now - @executed_at) > delay

  Vedeu.log(type: :event, message: "Throttling: '#{name.inspect}'".freeze)

  false
end

#throttling?Boolean (private)

Returns a boolean indicating whether throttling is required for this event. Setting the delay option to any value greater than 0 will enable throttling.



214
215
216
217
218
# File 'lib/vedeu/events/event.rb', line 214

def throttling?
  @now = Time.now.to_f

  options[:delay] > 0
end

#trigger(*args) ⇒ void

This method returns an undefined value.

Triggers the event based on debouncing and throttling conditions.



167
168
169
170
171
172
173
# File 'lib/vedeu/events/event.rb', line 167

def trigger(*args)
  return execute(*args) unless debouncing? || throttling?

  return execute(*args) if debouncing? && debounce_expired?

  return execute(*args) if throttling? && throttle_expired?
end