Question

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.

Was it helpful?

Solution

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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top