Rails "Template is missing" error, though it exists (3.2.1) - ruby-on-rails

I just started using Rails and am not sure what I'm not doing correctly.
In routes.rb I have
resources :pages
In app/controllers/pages_controller.rb I have
class PagesController < ApplicationController
def index
end
end
I have a layout in app/views/layouts/application.html.erb and a template in app/views/home/pages/index.html.erb which I want rendered when I request "/pages". However, I get the error
Template is missing
Missing template pages/index, application/index with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "/###/app/views"
I've been using stackoverflow for ages without posting, but so many different things seem to trigger this error that it's hard to find answers for my particular case. Also I'm a noob :3 Please help!

You say you have app/views/home/pages/index.html.erb to represent the index view for your pages resource. I think the home/ directory is not required.
In other words, your view file should be app/views/pages/index.html.erb.

It's looking to find it in app/views/pages/index but you have it in app/views/home/pages/index. That slight difference makes it so that the Rails convention is lost.
If you must keep your new directory hierarchy, do this on your controller:
class PagesController < ApplicationController
def index
render :partial => "home/pages/index"
end
end
But, by default, if you have a resource, like :pages, it will automatically look in app/views/pages.

I had this problem and I resolved it by just changing the folder name from car to cars. I had to change the folder name from singular to plural.

Related

Why I am getting missing template from a subdirectory?

I have the following in my views/patients/show.html.slim
== render 'era/header'
Of course, views/patients/era/_header.html.slim exists, though it throws a missing template error:
ActionView::MissingTemplate at /patients/12345
Missing partial era/header with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :slim, :haml]}.
Searched in: * "/home/pablo/code/rails/tarjira/app/views"
If I use == render 'patients/era/header' works, same with == render 'era_header' (assuming I have a views/patients/_era_header.html.slim file). The latter makes me think that rails search the actual directory (views/patients), so I don't understand why in the first case I have to prefix with patients/.
I'm using Rails 4.0.4.
To render a partial as part of a view, you use the render method within the view:
== render 'era_header'
This will render a file named _era_header.html.slim at that point within the view being rendered.
== render 'era/header'
This code will pull in the partial from app/views/era/_header.html.slim. Notice how the Rails is forming the path i.e, by prefixing app/views before the given path in render method call i.e., era/header. This is how render method is implemented in Rails.
Read the Rails Guide explanation for Naming Partials
The desire for partial rendering with relative paths seems to have a long history. There's an issue from 2011 and a pull request from 2015.
For now if you just need 1 extra level as described in your question you can place a callback in your application_controller.rb:
class ApplicationController < ActionController::Base
before_action :_append_view_path
def _append_view_path
append_view_path("app/views/#{controller_path}")
end
end
This way your views will gain the ability to use render('subfolder/partial') instead of render('controller/subfolder/partial').

Is it necessary to build Rails views when using Ember.js?

I'm updating a Rails app to utilize Ember.js. Those views that existed within the app prior to integrating ember still work fine, but I've also added several new views. These views have all the necessary ember parts (template, controller, etc), as well as all the Rails parts, excluding the view files.
These views work fine if the user accesses them by clicking on an internal link. However, if the user reloads the page or manually enters the URL, then I get this error:
ActionView::MissingTemplate at /contribute
Missing template pages/contribute, application/contribute with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :slim, :coffee]}. Searched in:
* "/home/sites/whistlr/app/views"
* "/home/.rvm/gems/ruby-2.0.0-p0#whistlr/gems/devise-3.0.0/app/views"
This is clearly happening because I do not have view files. The question is, is this strictly necessary? Is there some way to tell Rails to just load up the Ember views? Ideally, I'd just delete all the old Rails view files once the conversation is complete.
It isn't necessary, but you need to setup the rails routes.rb to have a catch all route that also renders just like your index page which displays the ember app and its html.
namespace :api do
# resources go here
end
root :to 'home#index'
match "/*path" => 'home#index'
Note: You want to customize this path pattern to your project, else 404s would also be send here.
It's not necessary to create individual views. The trick is to catch the exception in the application controller and then force it render the layout:
class ApplicationController < ActionController::Base
rescue_from ActionView::MissingTemplate do |exception|
render "/layouts/application"
end
end

Rails 3.1: Persistent "Template is missing" with JSON format

I have a problem very similar to the one mentioned in this question. However, none of the solutions described in the answers are working.
When trying to access my route, with or without .json extension, as well as with jQuery $.ajax and $.getJSON (with the correct Accept headers), I am getting the following exception:
Missing template users/events/index, application/index with {:handlers=>[:erb, :builder, :coffee, :haml], :formats=>[:json], :locale=>[:en, :en]}.
Since I only need JSON responses for this controller, I don't have nor want any templates for this controller.
My controller is defined like so:
class Users::EventsController < ApplicationController
respond_to(:json)
def index
# Some extra code here...
respond_with(#data)
end
end
With these routes in place (under a "user" scope):
resources(:events, :only => [:index, :show]) do
collection do
get ':year/:month', :to => 'events#index', :format => :json
end
end
The problem persists when adding the do |format| block and explicitly making it render as JSON.
Tried this on both Rails 3.1.1 and on 3.2 and got the same issue.
It looks like a server-side issue since accessing with ".json" doesn't work. What am I missing?
After a bit more tinkering I found out what was the actual cause of this problem.
At some point in the controller I had the following code block:
#array.map { |a| return a['id'] }
The return keyword was incorrectly used and caused the entire action to return ahead of time, causing the issue.
We encountered a similar issue with a custom Devise controller when issues a password reset request via JSON (be sure to use CSRF correctly also).
Problematic code
responds_to :json => [:create, :our_custom_method1, :our_custom_method2]
Working code
responds_to :json
Not happy with the security aspect of allowing more routes to accept JSON, but we'll lock it down further later.

Spree 1.1 missing templates when inheriting from Spree::BaseController

I'm trying to load a customized spree page by inheriting from Spree::BaseController.
class PagesController < Spree::BaseController
layout 'spree_application'
def home
end
end
But I get a whole bunch of missing template errors
Template is missing
Missing template pages/home, spree/base/home, application/home with
{:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder,
:coffee, :rabl]}. Searched in: *
"/Users/mm/StoreOnline/app/views"...
This doesn't seem right. If I have to replace all those templates I might as well just use regular rails controllers/actions/views. So my question is - is this no longer supported in Spree version 1.1+?
Turns out I just had the controller defined in the wrong place. Really wish Spree had better documentation on this stuff.
Anyway, move it into app/controllers/spree/pages_controller.rb and it worked fine.

render default template when requested template is missing in Rails

For a plugin I want to hack the following feature into Rails:
When a (partial) template does not exist (regardless of the format) I want to render a default template.
So say I call an action 'users/index' if users/index.html.erb does not (or other format) exist, 'default/index.html.erb' should be rendered.
Similarly, If I call an action 'locations/edit' and 'locations/edit.html.erb' does not exist, 'default/edit.html.erb' should be rendered
For partials, If I call an action 'locations/index' and the template 'locations/index.html.erb' calls the partial 'locations/_location' which does not exist, it should render 'default/_object'
The solution is seek gives me access to the templates variables (e.g. #users, #locations) and information on the requested path (e.g. users/index, locations/edit). And it should also work with partials.
I have thought of some options which I'll post below. None of them are completely satisfactory.
Solution 2:
Use 'rescue_from' in ApplicationController
class ApplicationController > ActionController::Base
rescue_from ActionView::MissingTemplate do |exception|
# use exception.path to extract the path information
# This does not work for partials
end
end
Drawback: does not work for partials.
Rails 3.1 automatically looks for files in application/template.html.erb after looking in controller/template.html.erb you can see this in the Exception like so:
Missing template [controller name]/index, application/index with {:locale=>[:en, :en], :formats=>[:html], :handlers=>[:erb, :coffee, :builder]}. Searched in: * "/path/to/rails_project/app/views"
so, just put your default templates in app/views/application
I found a patch that is relatively clean, it only patches the lookup of the template which is exactly what was required in the question.
module ActionView
class PathSet
def find_template_with_exception_handling(original_template_path, format = nil, html_fallback = true)
begin
find_template_without_exception_handling(original_template_path, format, html_fallback)
rescue ActionView::MissingTemplate => e
# Do something with original_template_path, format, html_fallback
raise e
end
end
alias_method_chain :find_template, :exception_handling
end
end
Solution 1:
Monkey patch ActionView::Base#render
module ActionView
class Base
def render_with_template_missing(*args, &block)
# do something if template does not exist
render_without_template_missing(*args, &block)
end
alias_method_chain :render, :template_missing
end
end
This monkey patch requires to look into the (changing) internals of rails and results in ugly code, but probably works.

Resources