I'm just in the middle of upgrading a large application from Rails 3 to Rails 3.1 and struck a problem with my implementation of the pages controller:
when templates doesnt exist
should render the 404 page (FAILED - 1)
Failures:
1) PagesController automatic paths when templates doesnt exist should render the 404 page
Failure/Error: get 'base_page_processor', :base_page => 'something_that_doesnt_exist'
NoMethodError:
undefined method `map' for "pages":String
# ./app/controllers/pages_controller.rb:5:in `base_page_processor'
# ./spec/controllers/pages_controller_spec.rb:37:in `block (3 levels) in <top (required)>'
Finished in 0.10557 seconds
4 examples, 1 开发者_运维百科failure
Failed examples:
rspec ./spec/controllers/pages_controller_spec.rb:36 # PagesController automatic paths when templates doesnt exist should render the 404 page
This did work in Rails 3.0. Something must of changed with the template_exists method. Here is the controller:
class PagesController < ApplicationController
def base_page_processor
view_prefix = "pages"
if params[:base_page].present? && template_exists?(params[:base_page], view_prefix)
render "#{view_prefix}/#{params[:base_page]}"
else
#TODO : Notify missing url via email error or error notification service
render '/public/404.html', :status => 404
end
end
end
Solution code:
class PagesController < ApplicationController
def base_page_processor
view_prefix = ["pages"]
if params[:base_page].present? && template_exists?(params[:base_page], view_prefix)
render "#{view_prefix[0]}/#{params[:base_page]}"
else
#TODO : Notify missing url via email error or error notification service
render '/errors/404.html', :status => 404
end
end
end
I also noticed that it wasn't rendering the error views (ie: /public/404.html) so I created a directory app/views/errors and put all the error static pages in there and just render them now. It works.
Thanks Andrew.
The template_exists
method parameters indicate that the second parameter, prefix, should be an array. Normally Rails methods accept both by converting something to an array if not, so this is slightly unusual.
exists?(name, prefixes = [], partial = false, keys = [])
This method is also aliased as template_exists?
# File actionpack/lib/action_view/lookup_context.rb, line 93
def exists?(name, prefixes = [], partial = false, keys = [])
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys))
end
So making view_prefix = ["pages"]
should work? (and modifying the remaining string interpolation accordingly)
精彩评论