Skip to content

Commit 995c507

Browse files
authored
Support custom form builders (#291)
1 parent f6f9d27 commit 995c507

16 files changed

+75
-192
lines changed

lib/phlex/rails.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@ module Rails
77
class HelpersCalledBeforeRenderError < StandardError; end
88

99
autoload :Buffered, "phlex/rails/buffered"
10-
autoload :Decorator, "phlex/rails/decorator"
11-
12-
autoload :FormBuilder, "phlex/rails/form_builder"
13-
autoload :LabelBuilder, "phlex/rails/label_builder"
14-
autoload :CheckboxBuilder, "phlex/rails/checkbox_builder"
15-
autoload :RadioButtonBuilder, "phlex/rails/radio_button_builder"
1610

1711
autoload :CSV, "phlex/rails/csv"
1812

@@ -26,6 +20,8 @@ class HelpersCalledBeforeRenderError < StandardError; end
2620
autoload :Layout, "phlex/rails/layout"
2721
autoload :Partial, "phlex/rails/partial"
2822
autoload :Streaming, "phlex/rails/streaming"
23+
24+
autoload :Builder, "phlex/rails/builder"
2925
end
3026

3127
CSV.prepend(Phlex::Rails::CSV)

lib/phlex/rails/builder.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
class Phlex::Rails::Builder < BasicObject
4+
def initialize(object, component:)
5+
@object = object
6+
@component = component
7+
end
8+
9+
define_method :send, ::Kernel.instance_method(:send)
10+
11+
def respond_to_missing?(method_name, include_private = false)
12+
@object.respond_to?(method_name, include_private)
13+
end
14+
15+
def method_missing(*, **, &block)
16+
output = if block
17+
@object.public_send(*, **) do |builder|
18+
yield ::Phlex::Rails::Builder.new(builder, component: @component)
19+
end
20+
else
21+
@object.public_send(*, **)
22+
end
23+
24+
case output
25+
when ::ActiveSupport::SafeBuffer
26+
@component.raw(output)
27+
else
28+
output
29+
end
30+
end
31+
end

lib/phlex/rails/checkbox_builder.rb

Lines changed: 0 additions & 10 deletions
This file was deleted.

lib/phlex/rails/decorator.rb

Lines changed: 0 additions & 28 deletions
This file was deleted.

lib/phlex/rails/form_builder.rb

Lines changed: 0 additions & 123 deletions
This file was deleted.

lib/phlex/rails/helper_macros.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ def #{method_name}(*args, **kwargs, &block)
3333
RUBY
3434
end
3535

36-
def register_builder_yielding_helper(method_name, builder)
36+
def register_builder_yielding_helper(method_name)
3737
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
3838
# frozen_string_literal: true
3939
4040
def #{method_name}(*args, **kwargs)
4141
output = if block_given?
4242
view_context.#{method_name}(*args, **kwargs) { |builder|
43-
yield #{builder.name}.new(builder, component: self)
43+
yield Phlex::Rails::Builder.new(builder, component: self)
4444
}
4545
else
4646
view_context.#{method_name}(*args, **kwargs)

lib/phlex/rails/helpers/collection_check_boxes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::CollectionCheckBoxes
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_check_boxes)
7-
register_builder_yielding_helper def collection_check_boxes(...) = nil, Phlex::Rails::CheckboxBuilder
7+
register_builder_yielding_helper def collection_check_boxes(...) = nil
88
end

lib/phlex/rails/helpers/collection_radio_buttons.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::CollectionRadioButtons
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_radio_buttons)
7-
register_builder_yielding_helper def collection_radio_buttons(...) = nil, Phlex::Rails::RadioButtonBuilder
7+
register_builder_yielding_helper def collection_radio_buttons(...) = nil
88
end

lib/phlex/rails/helpers/fields.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::Fields
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields)
7-
register_builder_yielding_helper def fields(...) = nil, Phlex::Rails::FormBuilder
7+
register_builder_yielding_helper def fields(...) = nil
88
end

lib/phlex/rails/helpers/fields_for.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::FieldsFor
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for)
7-
register_builder_yielding_helper def fields_for(...) = nil, Phlex::Rails::FormBuilder
7+
register_builder_yielding_helper def fields_for(...) = nil
88
end

lib/phlex/rails/helpers/form_for.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::FormFor
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for)
7-
register_builder_yielding_helper def form_for(...) = nil, Phlex::Rails::FormBuilder
7+
register_builder_yielding_helper def form_for(...) = nil
88
end

lib/phlex/rails/helpers/form_with.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::FormWith
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with)
7-
register_builder_yielding_helper def form_with(...) = nil, Phlex::Rails::FormBuilder
7+
register_builder_yielding_helper def form_with(...) = nil
88
end

lib/phlex/rails/helpers/label.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ module Phlex::Rails::Helpers::Label
44
extend Phlex::Rails::HelperMacros
55

66
# [Rails Docs](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-label)
7-
register_builder_yielding_helper def label(...) = nil, Phlex::Rails::LabelBuilder
7+
register_builder_yielding_helper def label(...) = nil
88
end

lib/phlex/rails/label_builder.rb

Lines changed: 0 additions & 6 deletions
This file was deleted.

lib/phlex/rails/radio_button_builder.rb

Lines changed: 0 additions & 10 deletions
This file was deleted.

test/helpers/form_with.test.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,36 @@
4242
</form>
4343
HTML
4444
end
45+
46+
class CustomFormBuilder < ActionView::Helpers::FormBuilder
47+
def fancy_input(attribute, options = {})
48+
@template.content_tag(:div, class: "fancy-input") do
49+
"Fancy input for #{attribute}"
50+
end
51+
end
52+
end
53+
54+
test "form_with with custom builder" do
55+
component = Class.new(Phlex::HTML) do
56+
include Phlex::Rails::Helpers::FormWith
57+
58+
define_method :view_template do
59+
form_with(url: "/", builder: CustomFormBuilder) do |form|
60+
form.fancy_input :bar
61+
nil # important, otherwise the return value is output
62+
end
63+
end
64+
end
65+
66+
controller.define_singleton_method(:form_authenticity_token) { |_| "(example form authenticity token)" }
67+
68+
output = render(component)
69+
70+
assert_equivalent_html output, <<~HTML
71+
<form action="/" accept-charset="UTF-8" method="post">
72+
<input name="utf8" type="hidden" value="" autocomplete="off">
73+
<input type="hidden" name="authenticity_token" value="(example form authenticity token)" autocomplete="off">
74+
<div class="fancy-input">Fancy input for bar</div>
75+
</form>
76+
HTML
77+
end

0 commit comments

Comments
 (0)