Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/view_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module ViewComponent
extend ActiveSupport::Autoload

autoload :Base
autoload :Metal
autoload :CaptureCompatibility
autoload :Compiler
autoload :CompileCache
Expand Down
37 changes: 37 additions & 0 deletions lib/view_component/metal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

module ViewComponent
class Metal
undef :p

def self.tag_elements
@@tag_elements ||= ActionView::Helpers::TagHelper::TagBuilder.instance_methods(false)
end

def render_in(view_context)
raise ArgumentError, "#{self.class} does not support passing a block" if block_given?
@view_context = view_context
@view_context.with_output_buffer { call }.to_s
end

def plain(string)
@view_context.concat(string)
end

def method_missing(method, ...)
if self.class.tag_elements.include?(method)
@view_context.concat @view_context.tag.__send__(method, ...)
elsif @view_context.respond_to?(method, false)
@view_context.__send__(method, ...)
else
super
end
end

def respond_to_missing?(method, include_all = false)
return true if super
return true if self.class.tag_elements.include?(method)
@view_context.respond_to?(method, false)
end
end
end
12 changes: 12 additions & 0 deletions test/sandbox/app/components/metal_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class MetalComponent < ViewComponent::Metal
def call
button type: :button do
p "Hello"
span do
strong { " World" }
end
end
end
end
12 changes: 12 additions & 0 deletions test/sandbox/test/metal_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

require "test_helper"

class MetalTest < ViewComponent::TestCase
test "it works" do
render_inline MetalComponent.new

assert_selector "button > span > strong"
assert_text "Hello World"
end
end
Loading