Class: Rails::GraphQL::Event

Inherits:
Object
  • Object
show all
Defined in:
lib/rails/graphql/event.rb

Overview

GraphQL Event

This class is responsible for triggering events. It also contains the data that can be used on the event handlers.

Direct Known Subclasses

Request::Authorizable::Event, Request::Event

Constant Summary collapse

TRIGGER_TYPES =

List of trigger types used on trigger shortcut

{
  all?: :trigger_all,
  stack?: :trigger_all,
  object?: :trigger_object,
  single?: :trigger,
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, source, **data) ⇒ Event

Returns a new instance of Event.



33
34
35
36
37
38
39
40
41
# File 'lib/rails/graphql/event.rb', line 33

def initialize(name, source, **data)
  @collect = data.delete(:collect?)
  @reverse = data.delete(:reverse?)

  @event_name = name
  @data = data
  @source = source
  @layers = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name) ⇒ Object (private)

If the method_name matches any key entry of the provided data, just return the value stored there



163
164
165
# File 'lib/rails/graphql/event.rb', line 163

def method_missing(method_name, *)
  data.key?(method_name) ? data[method_name] : super
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



10
11
12
# File 'lib/rails/graphql/event.rb', line 10

def data
  @data
end

#event_nameObject (readonly)

Returns the value of attribute event_name.



10
11
12
# File 'lib/rails/graphql/event.rb', line 10

def event_name
  @event_name
end

#last_resultObject (readonly)

Returns the value of attribute last_result.



10
11
12
# File 'lib/rails/graphql/event.rb', line 10

def last_result
  @last_result
end

#objectObject (readonly)

Returns the value of attribute object.



10
11
12
# File 'lib/rails/graphql/event.rb', line 10

def object
  @object
end

#sourceObject (readonly)

Returns the value of attribute source.



10
11
12
# File 'lib/rails/graphql/event.rb', line 10

def source
  @source
end

Class Method Details

.trigger(event_name, object, source, **xargs, &block) ⇒ Object

Event trigger shortcut that can perform any mode of trigger



23
24
25
26
27
28
29
30
31
# File 'lib/rails/graphql/event.rb', line 23

def self.trigger(event_name, object, source, **xargs, &block)
  extra = xargs.slice!(*TRIGGER_TYPES.keys)
  fallback = extra.delete(:fallback_trigger!) || :trigger
  method_name = xargs.find { |k, v| break TRIGGER_TYPES[k] if v } || fallback

  instance = new(event_name, source, **extra)
  instance.instance_variable_set(:@object, object) if block.present?
  instance.public_send(method_name, block || object)
end

Instance Method Details

#call_nextObject

Call the next item on the queue and return its result



136
137
138
139
140
# File 'lib/rails/graphql/event.rb', line 136

def call_next
  trigger(@items.next)
rescue StopIteration
  # Do not do anything when missing next/super
end

#parameter(name) ⇒ Object Also known as: []

Return a given name information from the event



55
56
57
# File 'lib/rails/graphql/event.rb', line 55

def parameter(name)
  respond_to?(name) ? public_send(name) : data[name]
end

#parameter?(name) ⇒ Boolean Also known as: key?

Check if the event has a given name information

Returns:

  • (Boolean)


62
63
64
# File 'lib/rails/graphql/event.rb', line 62

def parameter?(name)
  respond_to?(name) || data.key?(name)
end

#same_source?(other) ⇒ Boolean

Check if the provided other is equal to the source of the event. If other is a directive, then check if the source is using that directive TODO: Other cannot be an instance

Returns:

  • (Boolean)


46
47
48
49
50
51
52
# File 'lib/rails/graphql/event.rb', line 46

def same_source?(other)
  if other.is_a?(Directive) || (other.is_a?(Module) && other < Directive)
    event_name == :attach || source.using?(other)
  else
    source == other
  end
end

#set_on(instance, &block) ⇒ Object Also known as: on_instance

Temporarily attach the event into an instance ensuring to set the previous value back



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/rails/graphql/event.rb', line 70

def set_on(instance, &block)
  send_args = block.arity.eql?(1) ? [instance] : []
  old_event = instance.instance_variable_get(:@event) \
    if instance.instance_variable_defined?(:@event)

  return block.call(*send_args) if old_event === self

  begin
    instance.instance_variable_set(:@event, self)
    block.call(*send_args)
  ensure
    instance.instance_variable_set(:@event, old_event)
  end
end

#stop(*result, layer: nil) ⇒ Object

Stop the execution of an event using a given layer. The default is to get the last activated layer and stop it



130
131
132
133
# File 'lib/rails/graphql/event.rb', line 130

def stop(*result, layer: nil)
  layer = @layers[layer] if layer.is_a?(Numeric)
  throw(layer || @layers.first, *result)
end

#trigger(block) ⇒ Object

Call a given block and send the event as reference



124
125
126
# File 'lib/rails/graphql/event.rb', line 124

def trigger(block)
  @last_result = catchable(:item) { block.call(self) }
end

#trigger_all(*objects) ⇒ Object

From the list of all given objects, run the trigger_object



88
89
90
91
92
93
94
# File 'lib/rails/graphql/event.rb', line 88

def trigger_all(*objects)
  catchable(:stack) do
    iterator = @collect ? :map : :each
    objects = objects.first if objects.size == 1 && objects.first.is_a?(Enumerable)
    objects.flatten.send(iterator, &method(:trigger_object))
  end
end

#trigger_object(object, events = nil) ⇒ Object

Fetch all the events from the object, get only the ones that are from the same name as the instance of this class and call trigger. It runs in reverse order, so first in first out. Since events can sometimes be cached, using events avoid calculating the all_events



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/rails/graphql/event.rb', line 100

def trigger_object(object, events = nil)
  @items ||= nil
  @object ||= nil
  @last_result ||= nil

  old_items, old_object, old_result, @object = @items, @object, @last_result, object

  catchable(:object) do
    events ||= object.all_events.try(:[], event_name)
    stop if events.blank?

    @items = @reverse ? events.reverse_each : events.each
    call_next while @items.peek
  rescue StopIteration
    # TODO: Make sure that the +@collect+ works
    return @last_result
  end
ensure
  @items = old_items
  @object = old_object
  @last_result = old_result
end