Skip to content

Commit 4472154

Browse files
authored
Merge pull request #47 from github/pr/28
Add controller context to components
2 parents 8e88074 + 1275f5c commit 4472154

22 files changed

+159
-49
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Components are rendered with enough controller context to support rendering of partials and forms.
2+
3+
*Patrick Sinclair, Joel Hawksley, Aaron Patterson*
4+
15
# v1.2.1
26

37
* `actionview-component` is now tested against Ruby 2.3/2.4 and Rails 5.0.0.

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
source "https://rubygems.org"
44
gemspec
55

6-
rails_version = "#{ENV['RAILS_VERSION'] || '5.2.3'}"
6+
rails_version = "#{ENV['RAILS_VERSION'] || '6.0.0'}"
77

88
gem "rails", rails_version == "master" ? { github: "rails/rails" } : rails_version

Gemfile.lock

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,61 @@ PATH
66
GEM
77
remote: https://rubygems.org/
88
specs:
9-
actioncable (5.2.3)
10-
actionpack (= 5.2.3)
9+
actioncable (6.0.0)
10+
actionpack (= 6.0.0)
1111
nio4r (~> 2.0)
1212
websocket-driver (>= 0.6.1)
13-
actionmailer (5.2.3)
14-
actionpack (= 5.2.3)
15-
actionview (= 5.2.3)
16-
activejob (= 5.2.3)
13+
actionmailbox (6.0.0)
14+
actionpack (= 6.0.0)
15+
activejob (= 6.0.0)
16+
activerecord (= 6.0.0)
17+
activestorage (= 6.0.0)
18+
activesupport (= 6.0.0)
19+
mail (>= 2.7.1)
20+
actionmailer (6.0.0)
21+
actionpack (= 6.0.0)
22+
actionview (= 6.0.0)
23+
activejob (= 6.0.0)
1724
mail (~> 2.5, >= 2.5.4)
1825
rails-dom-testing (~> 2.0)
19-
actionpack (5.2.3)
20-
actionview (= 5.2.3)
21-
activesupport (= 5.2.3)
26+
actionpack (6.0.0)
27+
actionview (= 6.0.0)
28+
activesupport (= 6.0.0)
2229
rack (~> 2.0)
2330
rack-test (>= 0.6.3)
2431
rails-dom-testing (~> 2.0)
25-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
26-
actionview (5.2.3)
27-
activesupport (= 5.2.3)
32+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
33+
actiontext (6.0.0)
34+
actionpack (= 6.0.0)
35+
activerecord (= 6.0.0)
36+
activestorage (= 6.0.0)
37+
activesupport (= 6.0.0)
38+
nokogiri (>= 1.8.5)
39+
actionview (6.0.0)
40+
activesupport (= 6.0.0)
2841
builder (~> 3.1)
2942
erubi (~> 1.4)
3043
rails-dom-testing (~> 2.0)
31-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
32-
activejob (5.2.3)
33-
activesupport (= 5.2.3)
44+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
45+
activejob (6.0.0)
46+
activesupport (= 6.0.0)
3447
globalid (>= 0.3.6)
35-
activemodel (5.2.3)
36-
activesupport (= 5.2.3)
37-
activerecord (5.2.3)
38-
activemodel (= 5.2.3)
39-
activesupport (= 5.2.3)
40-
arel (>= 9.0)
41-
activestorage (5.2.3)
42-
actionpack (= 5.2.3)
43-
activerecord (= 5.2.3)
48+
activemodel (6.0.0)
49+
activesupport (= 6.0.0)
50+
activerecord (6.0.0)
51+
activemodel (= 6.0.0)
52+
activesupport (= 6.0.0)
53+
activestorage (6.0.0)
54+
actionpack (= 6.0.0)
55+
activejob (= 6.0.0)
56+
activerecord (= 6.0.0)
4457
marcel (~> 0.3.1)
45-
activesupport (5.2.3)
58+
activesupport (6.0.0)
4659
concurrent-ruby (~> 1.0, >= 1.0.2)
4760
i18n (>= 0.7, < 2)
4861
minitest (~> 5.1)
4962
tzinfo (~> 1.1)
50-
arel (9.0.0)
63+
zeitwerk (~> 2.1, >= 2.1.8)
5164
ast (2.4.0)
5265
builder (3.2.3)
5366
concurrent-ruby (1.1.5)
@@ -73,7 +86,7 @@ GEM
7386
mini_mime (1.0.2)
7487
mini_portile2 (2.4.0)
7588
minitest (5.1.0)
76-
nio4r (2.4.0)
89+
nio4r (2.5.2)
7790
nokogiri (1.10.4)
7891
mini_portile2 (~> 2.4.0)
7992
parallel (1.17.0)
@@ -82,30 +95,32 @@ GEM
8295
rack (2.0.7)
8396
rack-test (1.1.0)
8497
rack (>= 1.0, < 3)
85-
rails (5.2.3)
86-
actioncable (= 5.2.3)
87-
actionmailer (= 5.2.3)
88-
actionpack (= 5.2.3)
89-
actionview (= 5.2.3)
90-
activejob (= 5.2.3)
91-
activemodel (= 5.2.3)
92-
activerecord (= 5.2.3)
93-
activestorage (= 5.2.3)
94-
activesupport (= 5.2.3)
98+
rails (6.0.0)
99+
actioncable (= 6.0.0)
100+
actionmailbox (= 6.0.0)
101+
actionmailer (= 6.0.0)
102+
actionpack (= 6.0.0)
103+
actiontext (= 6.0.0)
104+
actionview (= 6.0.0)
105+
activejob (= 6.0.0)
106+
activemodel (= 6.0.0)
107+
activerecord (= 6.0.0)
108+
activestorage (= 6.0.0)
109+
activesupport (= 6.0.0)
95110
bundler (>= 1.3.0)
96-
railties (= 5.2.3)
111+
railties (= 6.0.0)
97112
sprockets-rails (>= 2.0.0)
98113
rails-dom-testing (2.0.3)
99114
activesupport (>= 4.2.0)
100115
nokogiri (>= 1.6)
101116
rails-html-sanitizer (1.2.0)
102117
loofah (~> 2.2, >= 2.2.2)
103-
railties (5.2.3)
104-
actionpack (= 5.2.3)
105-
activesupport (= 5.2.3)
118+
railties (6.0.0)
119+
actionpack (= 6.0.0)
120+
activesupport (= 6.0.0)
106121
method_source
107122
rake (>= 0.8.7)
108-
thor (>= 0.19.0, < 2.0)
123+
thor (>= 0.20.3, < 2.0)
109124
rainbow (3.0.0)
110125
rake (10.5.0)
111126
rubocop (0.74.0)
@@ -141,6 +156,7 @@ GEM
141156
websocket-driver (0.7.1)
142157
websocket-extensions (>= 0.1.0)
143158
websocket-extensions (0.1.4)
159+
zeitwerk (2.1.10)
144160

145161
PLATFORMS
146162
ruby
@@ -150,7 +166,7 @@ DEPENDENCIES
150166
bundler (>= 1.14)
151167
haml (~> 5)
152168
minitest (= 5.1.0)
153-
rails (= 5.2.3)
169+
rails (= 6.0.0)
154170
rake (~> 10.0)
155171
rubocop (~> 0.59)
156172
rubocop-github (~> 0.13.0)

lib/action_view/component/base.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ module ActionView
3030
module Component
3131
class Base < ActionView::Base
3232
include ActiveModel::Validations
33+
include ActiveSupport::Configurable
34+
include ActionController::RequestForgeryProtection
35+
36+
delegate :render, to: :view_context
3337

3438
# Entrypoint for rendering components. Called by ActionView::Base#render.
3539
#
@@ -58,6 +62,12 @@ class Base < ActionView::Base
5862
#
5963
def render_in(view_context, *args, &block)
6064
self.class.compile
65+
self.controller = view_context.controller
66+
@view_context = view_context
67+
@view_renderer ||= view_context.view_renderer
68+
@lookup_context ||= view_context.lookup_context
69+
@view_flow ||= view_context.view_flow
70+
6171
@content = view_context.capture(&block) if block_given?
6272
validate!
6373
call
@@ -136,7 +146,7 @@ def type
136146

137147
private
138148

139-
attr_reader :content
149+
attr_reader :content, :view_context
140150
end
141151
end
142152
end

lib/action_view/component/test_helpers.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ module ActionView
44
module Component
55
module TestHelpers
66
def render_inline(component, **args, &block)
7-
Nokogiri::HTML(ApplicationController.new.view_context.render(component, args, &block))
7+
Nokogiri::HTML(controller.view_context.render(component, args, &block))
8+
end
9+
10+
def controller
11+
@controller ||= ApplicationController.new.tap { |c| c.request = ActionDispatch::TestRequest.create }
812
end
913

1014
def render_component(component, **args, &block)

test/action_view/component_test.rb

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ def test_renders_haml_template
7171
assert_includes result.text, "bar"
7272
end
7373

74+
def test_renders_button_to_component
75+
result = render_inline(ButtonToComponent) { "foo" }
76+
77+
assert_equal '<input type="submit" value="foo">', result.css("input[type=submit]").to_html
78+
assert result.css("form[class='button_to'][action='/'][method='post']").present?
79+
assert result.css("input[type='hidden'][name='authenticity_token']").present?
80+
end
81+
7482
def test_renders_erb_template
7583
result = render_inline(ErbComponent, message: "bar") { "foo" }
7684

@@ -92,12 +100,36 @@ def test_renders_erb_template_with_hash_syntax
92100
assert_includes result.text, "bar"
93101
end
94102

95-
def test_renders_route_helper
96-
result = render_inline(RouteComponent)
103+
def test_renders_partial_template
104+
result = render_inline(PartialComponent)
105+
106+
assert_equal "<div>hello,partial world!</div>", result.css("div").first.to_html
107+
end
108+
109+
def test_renders_content_for_template
110+
result = render_inline(ContentForComponent)
111+
112+
assert_equal "<div>Hello content for</div>", result.css("div").first.to_html
113+
end
114+
115+
def test_renders_path_helper
116+
result = render_inline(PathComponent)
97117

98118
assert_includes result.text, "/"
99119
end
100120

121+
def test_renders_url_helper
122+
result = render_inline(UrlComponent)
123+
124+
assert_includes result.text, "http://test.host/"
125+
end
126+
127+
def test_renders_another_component
128+
result = render_inline(AnotherComponent)
129+
130+
assert_equal trim_result(result.css("div").first.to_html), "<div>hello,world!</div>"
131+
end
132+
101133
def test_template_changes_are_not_reflected_in_production
102134
ActionView::Base.cache_template_loading = true
103135

test/action_view/integration_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ class IntegrationTest < ActionDispatch::IntegrationTest
1515
assert_equal trim_result(response.body), "<span><div>Foobar</div></span>"
1616
end
1717

18+
test "rendering component with a partial" do
19+
get "/partial"
20+
assert_response :success
21+
assert_equal trim_result(response.body), "partial:<div>hello,partialworld!</div>component:<div>hello,partialworld!</div>"
22+
end
23+
1824
test "rendering component in a view with deprecated syntax" do
1925
get "/deprecated"
2026
assert_response :success
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<%= render(MyComponent) %>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# frozen_string_literal: true
2+
3+
class AnotherComponent < ActionView::Component::Base
4+
def initialize(*); end
5+
end
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<%= button_to(content, root_path) %>

0 commit comments

Comments
 (0)