Class: ReactOnRailsPro::StreamDecorator

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

Instance Method Summary collapse

Constructor Details

#initialize(component) ⇒ StreamDecorator

Returns a new instance of StreamDecorator.



8
9
10
11
12
13
14
15
16
17
# File 'lib/react_on_rails_pro/stream_request.rb', line 8

def initialize(component)
  @component = component
  # @type [Array[Proc]]
  # Proc receives 2 arguments: chunk, position
  # @param chunk [String] The chunk to be processed
  # @param position [Symbol] The position of the chunk in the stream (:first, :middle, or :last)
  # The position parameter is used by actions that add content to the beginning or end of the stream
  @actions = [] # List to store all actions
  @rescue_blocks = []
end

Instance Method Details

#appendObject

Add an append action



41
42
43
44
# File 'lib/react_on_rails_pro/stream_request.rb', line 41

def append
  @actions << ->(chunk, position) { position == :last ? "#{chunk}#{yield}" : chunk }
  self # Return self to allow chaining
end

#each_chunk(&block) ⇒ Object

rubocop:disable Metrics/CyclomaticComplexity



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/react_on_rails_pro/stream_request.rb', line 57

def each_chunk(&block) # rubocop:disable Metrics/CyclomaticComplexity
  return enum_for(:each_chunk) unless block

  first_chunk = true
  @component.each_chunk do |chunk|
    position = first_chunk ? :first : :middle
    modified_chunk = handle_chunk(chunk, position)
    yield(modified_chunk)
    first_chunk = false
  end

  # The last chunk contains the append content after the transformation
  # All transformations are applied to the append content
  last_chunk = handle_chunk("", :last)
  yield(last_chunk) unless last_chunk.empty?
rescue StandardError => e
  current_error = e
  rescue_block_index = 0
  while current_error.present? && (rescue_block_index < @rescue_blocks.size)
    begin
      @rescue_blocks[rescue_block_index].call(current_error, &block)
      current_error = nil
    rescue StandardError => inner_error
      current_error = inner_error
    end
    rescue_block_index += 1
  end
  raise current_error if current_error.present?
end

#handle_chunk(chunk, position) ⇒ Object



51
52
53
54
55
# File 'lib/react_on_rails_pro/stream_request.rb', line 51

def handle_chunk(chunk, position)
  @actions.reduce(chunk) do |acc, action|
    action.call(acc, position)
  end
end

#prependObject

Add a prepend action



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

def prepend
  @actions << ->(chunk, position) { position == :first ? "#{yield}#{chunk}" : chunk }
  self # Return self to allow chaining
end

#rescue(&block) ⇒ Object



46
47
48
49
# File 'lib/react_on_rails_pro/stream_request.rb', line 46

def rescue(&block)
  @rescue_blocks << block
  self # Return self to allow chaining
end

#transformObject

Add a transformation action



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/react_on_rails_pro/stream_request.rb', line 26

def transform
  @actions << lambda { |chunk, position|
    if position == :last && chunk.empty?
      # Return the empty chunk without modification for the last chunk
      # This is related to the `handleChunk(:last, "")` call which gets all the appended content
      # We don't want to make an extra call to the transformer block if there is no content appended
      chunk
    else
      yield(chunk)
    end
  }
  self # Return self to allow chaining
end