Skip to content

Commit 42b44a6

Browse files
pixeltrixSam Phippen
authored and
Sam Phippen
committed
Fix empty template rendering for Rails 4.2.5.1
Closes #1532. Refactor the template rendering overrides in controller specs to be more compatible with the Action View public api. Previously `EmptyTemplatePathSetDecorator` overrode the `find_all` method to wrap a path set. However `ActionView::PathSet` is not public api so instead create a subclass of `ActionView::FileSystemResolver` to return an empty template and treat `view_paths` as an array of string-like objects.
1 parent 7382c10 commit 42b44a6

File tree

3 files changed

+88
-15
lines changed

3 files changed

+88
-15
lines changed

example_app_generator/generate_stuff.rb

+4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ def using_source_path(path)
110110
"This is a template for a custom action.",
111111
:force => true
112112

113+
file "app/views/errors/401.html.erb",
114+
"This is a template for rendering an error page",
115+
:force => true
116+
113117
# Use the absolute path so we can load it without active record too
114118
apply File.join(DEFAULT_SOURCE_PATH, 'generate_action_mailer_specs.rb')
115119
using_source_path(File.expand_path('..', __FILE__)) do

features/controller_specs/anonymous_controller.feature

+71-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Feature: anonymous controller
3131
end
3232
```
3333

34-
Scenario: Specify error handling in `ApplicationController`
34+
Scenario: Specify error handling in `ApplicationController` with redirect
3535
Given a file named "spec/controllers/application_controller_spec.rb" with:
3636
"""ruby
3737
require "rails_helper"
@@ -66,6 +66,76 @@ Feature: anonymous controller
6666
When I run `rspec spec`
6767
Then the examples should all pass
6868

69+
Scenario: Specify error handling in `ApplicationController` with render
70+
Given a file named "spec/controllers/application_controller_spec.rb" with:
71+
"""ruby
72+
require "rails_helper"
73+
74+
class ApplicationController < ActionController::Base
75+
class AccessDenied < StandardError; end
76+
77+
rescue_from AccessDenied, :with => :access_denied
78+
79+
private
80+
81+
def access_denied
82+
render "errors/401"
83+
end
84+
end
85+
86+
RSpec.describe ApplicationController, :type => :controller do
87+
controller do
88+
def index
89+
raise ApplicationController::AccessDenied
90+
end
91+
end
92+
93+
describe "handling AccessDenied exceptions" do
94+
it "renders the errors/401 template" do
95+
get :index
96+
expect(response).to render_template("errors/401")
97+
end
98+
end
99+
end
100+
"""
101+
When I run `rspec spec`
102+
Then the examples should all pass
103+
104+
Scenario: Specify error handling in `ApplicationController` with render :file
105+
Given a file named "spec/controllers/application_controller_spec.rb" with:
106+
"""ruby
107+
require "rails_helper"
108+
109+
class ApplicationController < ActionController::Base
110+
class AccessDenied < StandardError; end
111+
112+
rescue_from AccessDenied, :with => :access_denied
113+
114+
private
115+
116+
def access_denied
117+
render :file => "errors/401"
118+
end
119+
end
120+
121+
RSpec.describe ApplicationController, :type => :controller do
122+
controller do
123+
def index
124+
raise ApplicationController::AccessDenied
125+
end
126+
end
127+
128+
describe "handling AccessDenied exceptions" do
129+
it "renders the errors/401 template" do
130+
get :index
131+
expect(response).to render_template("errors/401")
132+
end
133+
end
134+
end
135+
"""
136+
When I run `rspec spec`
137+
Then the examples should all pass
138+
69139
Scenario: Specify error handling in a subclass
70140
Given a file named "spec/controllers/application_controller_subclass_spec.rb" with:
71141
"""ruby

lib/rspec/rails/view_rendering.rb

+13-14
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,11 @@ def render_views?
4343
# with modified source
4444
#
4545
# @private
46-
class EmptyTemplatePathSetDecorator < ::ActionView::Resolver
47-
attr_reader :original_path_set
48-
49-
def initialize(original_path_set)
50-
@original_path_set = original_path_set
51-
end
46+
class EmptyTemplateResolver < ::ActionView::FileSystemResolver
47+
private
5248

53-
def find_all(*args)
54-
original_path_set.find_all(*args).map do |template|
49+
def find_templates(*args)
50+
super.map do |template|
5551
::ActionView::Template.new(
5652
"",
5753
template.identifier,
@@ -85,23 +81,26 @@ def append_view_path(new_path)
8581
private
8682

8783
def _path_decorator(path)
88-
EmptyTemplatePathSetDecorator.new(ActionView::PathSet.new(Array.wrap(path)))
84+
EmptyTemplateResolver.new(path)
8985
end
9086
end
9187

9288
included do
9389
before do
9490
unless render_views?
95-
@_empty_view_path_set_delegator = EmptyTemplatePathSetDecorator.new(controller.class.view_paths)
96-
controller.class.view_paths = ::ActionView::PathSet.new.push(@_empty_view_path_set_delegator)
91+
@_original_path_set = controller.class.view_paths
92+
93+
empty_template_path_set = @_original_path_set.map do |resolver|
94+
EmptyTemplateResolver.new(resolver.to_s)
95+
end
96+
97+
controller.class.view_paths = empty_template_path_set
9798
controller.extend(EmptyTemplates)
9899
end
99100
end
100101

101102
after do
102-
unless render_views?
103-
controller.class.view_paths = @_empty_view_path_set_delegator.original_path_set
104-
end
103+
controller.class.view_paths = @_original_path_set unless render_views?
105104
end
106105
end
107106
end

0 commit comments

Comments
 (0)