-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcapture_compatibility_patch.rb
More file actions
46 lines (40 loc) · 1.66 KB
/
capture_compatibility_patch.rb
File metadata and controls
46 lines (40 loc) · 1.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# frozen_string_literal: true
module ViewComponent
module CaptureCompatibilityPatch
end
# CaptureCompatibility is a module that patches #capture to fix issues
# related to ViewComponent and functionality that relies on `capture`
# like forms, capture itself, turbo frames, etc.
#
# This underlying incompatibility with ViewComponent and capture is
# that several features like forms keep a reference to the primary
# `ActionView::Base` instance which has its own @output_buffer. When
# `#capture` is called on the original `ActionView::Base` instance while
# evaluating a block from a ViewComponent the @output_buffer is overridden
# in the ActionView::Base instance, and *not* the component. This results
# in a double render due to `#capture` implementation details.
#
# To resolve the issue, we override `#capture` so that we can delegate
# the `capture` logic to the ViewComponent that created the block.
module CaptureCompatibility
def self.included(base)
return if base < InstanceMethods
base.class_eval do
alias_method :original_capture, :capture
end
base.prepend(InstanceMethods)
end
module InstanceMethods
def capture(*args, &block)
# Handle blocks that originate from C code and raise, such as `&:method`
return original_capture(*args, &block) if block.source_location.nil?
block_context = block.binding.receiver
if block_context != self && block_context.class.present? && block_context.class < ActionView::Base
block_context.original_capture(*args, &block)
else
original_capture(*args, &block)
end
end
end
end
end