Class: DjangoSignal

Inherits:
Object
  • Object
show all
Defined in:
lib/django_signal.rb

Overview

DjangoSignal See docs.djangoproject.com/en/dev/topics/signals/#defining-and-sending-signals

Obviously, I didn’t wire this signals to ActiveRecord.

Also, I took the liberty to make some adaptations. Namely:

  • No explicit weakref stuff. Want a weakref? Build if yourself. Invalid refs are handled gracefuly.

  • No providing_args, since they had no functional relevance.

Defined Under Namespace

Classes: InvalidReceiver

Instance Method Summary collapse

Constructor Details

#initializeDjangoSignal

Create a new signal.



20
21
22
23
# File 'lib/django_signal.rb', line 20

def initialize
  @receivers = {}
  @lock = Mutex.new
end

Instance Method Details

#connect(receiver, sender = nil, dispatch_uid = nil) ⇒ Object

Connect receiver to sender for signal.

receiver

A callable which is to receive signals. The receiver must be able to handler 2+ arguments (+signal, sender, *send_args+).

If dispatch_uid is given, the receiver will not be added if
another receiver already exists with that dispatch_uid.
sender

The sender to which the receiver should respond or nil to receive events from any sender.

dispatch_uid

An identifier used to uniquely identify a particular instance of a receiver. This will usually be a symbol, though it may be anything with an object_id.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/django_signal.rb', line 38

def connect(receiver, sender=nil, dispatch_uid=nil)
  lookup_key = make_key(receiver, sender, dispatch_uid)

  begin
    receiver.method(:call) rescue nil or raise NoMethodError
    if -1 < receiver.arity && receiver.arity < 2
      raise InvalidReceiver, 'Receiver must be able to handle 2+ arguments.'
    end
  rescue NoMethodError
    raise InvalidReceiver, 'Receiver must be a callable (and respond to arity method).'
  end


  @lock.synchronize {
    @receivers[lookup_key] ||= receiver
  }
end

#disconnect(receiver, sender = nil, dispatch_uid = nil) ⇒ Object

Disconnect receiver from sender for signal.

If weak references are used, disconnect need not be called. The receiver will be remove from dispatch automatically.

receiver

The registered receiver to disconnect. May be nil if dispatch_uid is specified.

sender

The registered sender to disconnect

dispatch_uid

the unique identifier of the receiver to disconnect



67
68
69
70
71
72
73
# File 'lib/django_signal.rb', line 67

def disconnect(receiver, sender=nil, dispatch_uid=nil)
  lookup_key = make_key(receiver, sender, dispatch_uid)

  @lock.synchronize {
    @receivers.delete(lookup_key)
  }
end

#send(sender, *args) ⇒ Object

Send signal from sender to all connected receivers.

If any receiver raises an error, the error propagates back through send, terminating the dispatch loop, so it is quite possible to not have all receivers called if a raises an error.

sender

The sender of the signal. Either a specific object or nil.

args

Args which will be passed to receivers.

Returns a hash {receiver => response, … }.



87
88
89
# File 'lib/django_signal.rb', line 87

def send(sender, *args)
  self.mapper(self.method(:simple_call), sender, *args)
end

#send_robust(sender, *args) ⇒ Object

Send signal from sender to all connected receivers catching errors.

If any receiver raises an error (specifically any subclass of Exception), the error instance is returned as the result for that receiver.

sender

The sender of the signal. Either a specific object or nil.

args

Args which will be passed to receivers.

Returns a hash {receiver => response, … }.



102
103
104
# File 'lib/django_signal.rb', line 102

def send_robust(sender, *args)
  self.mapper(self.method(:robust_call), sender, *args)
end