Skip to content

Commit

Permalink
Merge pull request #226 from phlex-ruby/unbuffered-bug
Browse files Browse the repository at this point in the history
Fix unbuffered bug
  • Loading branch information
joeldrapper authored Sep 8, 2024
2 parents 6c1e183 + 645b1bd commit e7e4e48
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 56 deletions.
29 changes: 8 additions & 21 deletions lib/phlex/rails/sgml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,33 +55,20 @@ def render(*args, **kwargs, &block)
nil
end

def render_in(view_context, &block)
def render_in(view_context, &erb)
fragments = if view_context.request && (fragment_header = view_context.request.headers["X-Fragment"])
fragment_header.split
end

if block_given?
call(view_context:, fragments:) do |*args|
original_length = @_context.target.bytesize

if args.length == 1 && Phlex::SGML === args[0] && !block.source_location&.[](0)&.end_with?(".rb")
output = view_context.capture(
Phlex::Rails::Unbuffered.new(args[0]),
&block
)
if erb
call(view_context:, fragments:) { |*args|
if args.length == 1 && Phlex::SGML === args[0] && !erb.source_location&.[](0)&.end_with?(".rb")
unbuffered = Phlex::Rails::Unbuffered.new(args[0])
raw(helpers.capture(unbuffered, &erb))
else
output = view_context.capture(*args, &block)
end

unchanged = (original_length == @_context.target.bytesize)

if unchanged
case output
when ActiveSupport::SafeBuffer
@_context.target << output
end
raw(helpers.capture(*args, &erb))
end
end.html_safe
}.html_safe
else
call(view_context:, fragments:).html_safe
end
Expand Down
3 changes: 2 additions & 1 deletion lib/phlex/rails/testing.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# frozen_string_literal: true

require "phlex/rails"
require "phlex/testing"
Expand All @@ -13,5 +14,5 @@ def controller
end

Phlex::Testing::SGML.include(
Phlex::Testing::RailsContext
Phlex::Testing::RailsContext,
)
60 changes: 26 additions & 34 deletions lib/phlex/rails/unbuffered.rb
Original file line number Diff line number Diff line change
@@ -1,59 +1,51 @@
# frozen_string_literal: true

# @api private
class Phlex::Rails::Unbuffered < BasicObject
def initialize(object)
@object = object
class Phlex::Rails::Unbuffered
def initialize(component)
@component = component
end

def inspect
"Unbuffered(#{@object.class.name})[object: #{@object.inspect}]"
end

define_method :__class__,
::Object.instance_method(:class)

def respond_to_missing?(...)
@object.respond_to?(...)
@component.respond_to?(...)
end

def method_missing(name, ...)
if @object.respond_to?(name)
__class__.define_method(name) do |*a, **k, &b|
@object.capture do
if b
@object.public_send(name, *a, **k) do |*aa|
if aa.length == 1 && ::Phlex::SGML === aa[0]
@object.helpers.capture(
::Phlex::Rails::Unbuffered.new(aa[0]),
&b
)
else
@object.helpers.capture(*aa, &b)
end
end
else
@object.public_send(name, *a, **k)
def method_missing(method_name, *, &erb)
if @component.respond_to?(method_name)
output = @component.capture do
if erb
@component.public_send(method_name, *) do
@component.raw(
@component.helpers.capture(
&erb
),
)
end
else # no erb block
@component.public_send(
method_name,
*,
)
end
end

__send__(name, ...)
else
super
end
end

# Forward some methods to the original underlying object
def inspect
"Unbuffered(#{@component.inspect})"
end

def call(...)
@object.call(...)
@component.call(...)
end

def send(...)
@object.__send__(...)
@component.__send__(...)
end

def public_send(...)
@object.public_send(...)
@component.public_send(...)
end
end
3 changes: 3 additions & 0 deletions test/dummy/app/controllers/rendering_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ def partial_from_phlex
def view_component_from_phlex
render Rendering::ViewComponentFromPhlex.new
end

def phlex_component_from_erb
end
end
11 changes: 11 additions & 0 deletions test/dummy/app/views/components/card.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class Card < ApplicationComponent
def view_template(&)
article(class: "card", &)
end

def title(&)
h1(class: "title", &)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div class="outside">
<%= render Card.new do |t| %>
<div class="inside">
<%= t.title do %>
<strong class="inside-slot">Hi</strong>
<% end %>
</div>
<% end %>
</div>
1 change: 1 addition & 0 deletions test/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@

get "/rendering/partial_from_phlex", to: "rendering#partial_from_phlex"
get "/rendering/view_component_from_phlex", to: "rendering#view_component_from_phlex"
get "/rendering/phlex_component_from_erb", to: "rendering#phlex_component_from_erb"
end
6 changes: 6 additions & 0 deletions test/phlex/render_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@ class RenderTest < ActionDispatch::IntegrationTest
assert_response :success
assert_select "#phlex", "Rendered from Phlex"
end

test "rendering Phlex component from ERB view" do
get "/rendering/phlex_component_from_erb"
assert_response :success
assert_select ".outside .card .inside .title .inside-slot", "Hi"
end
end

0 comments on commit e7e4e48

Please sign in to comment.