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.



5
6
7
8
9
10
11
12
13
14
# File 'lib/react_on_rails_pro/stream_request.rb', line 5

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



38
39
40
41
# File 'lib/react_on_rails_pro/stream_request.rb', line 38

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



54
55
56
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
# File 'lib/react_on_rails_pro/stream_request.rb', line 54

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



48
49
50
51
52
# File 'lib/react_on_rails_pro/stream_request.rb', line 48

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

#prependObject

Add a prepend action



17
18
19
20
# File 'lib/react_on_rails_pro/stream_request.rb', line 17

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

#rescue(&block) ⇒ Object



43
44
45
46
# File 'lib/react_on_rails_pro/stream_request.rb', line 43

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

#transformObject

Add a transformation action



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/react_on_rails_pro/stream_request.rb', line 23

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