Why I am getting missing template from a subdirectory? - ruby-on-rails

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').

Related

How to use a partial in a rails nested routing simple form?

I have a nested route specifically around properties and downtowns. Downtowns have many properties.
The problem i'm having is that the edit form ended up getting quite large and I really would like to split it up in to a few partials for ease.
I've basically tried something similar to this here.
= simple_form_for([#downtown, #property]) do |f|
= render partial: "/properties/partial_test", locals: {resource: f }
The error I get when I do this is
ActionView::MissingTemplate in Properties#edit
Missing partial properties/_partial_test with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder, :haml]}
Right now all I have in the partial is filler text, but reading the error messaging, I'm assuming that the error is around how i'm trying to render the actual partial in my locals.
Would anyone have any thoughts or ideas on how to get this to work here?
Much thanks in advance! (also happy to share more code like my routes file or controller)

Rails can't find view template even though it exists

This is the error I'm getting whenever I'm accessing localhost:3000/cats:
Missing template cats/index, application/index with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}. Searched in:
* "/home/mikael/RubyOnRailsLearning/NinetyNineCats/app/views"
* "/home/mikael/.rvm/gems/ruby-2.6.3/gems/actiontext-6.0.2.1/app/views"
* "/home/mikael/.rvm/gems/ruby-2.6.3/gems/actionmailbox-6.0.2.1/app/views"
My view templates are located like so:
app/views-layouts/cats/index.html.erb, show.html.erb
I have also tried removing them from cats and into the views folder.
My index controller action is this:
def index
#cats = Cat.all
render :index
end
The routes.rb file has only this inside:
resources :cats
This project worked fine yesterday. It could find the templates and render them just fine. But I wanted to restart it so I deleted the rails app folder without dropping the database and I remade it today. The database schema got uploaded into the rails app.
I can't think of anything that might be causing this problem besides me not dropping yesterday's database and not remaking it. (it's the only difference)
You wrote that your view is in
app/views-layouts/cats/index.html.erb
but Ruby on Rails conventions expect it in
app/views/cats/index.html.erb

How to add a custom view partial path to Rails 4.2 lookup?

I have a demonstration partial in app/views/app1/users similar to this this solution. I've already tried using the prepend_view_path as in the aforementioned solution, to no avail.
haml:
#demonstration
= f.semantic_fields_for :demonstration do |ud|
= render 'demonstration_fields', :f => ud
But I get this error:
Missing partial app1/_demonstration_fields, application/_demonstration_fields with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml]}. Searched in:
The only way to make it work is to pass the full path to render as follows:
= render 'app1/users/demonstration_fields', :f => ud
But this defeats the purpose of trying to avoid redundant code (e.g., specifying a full path) via prepend_view_path. Is there a way to avoid passing in the full path?
You could override the ActionView::ViewPaths.local_prefixes private class method that every controller in Rails gets mixed in. The comment above the method even says:
Override this method in your controller if you want to change paths prefixes for finding views
"Views", in this context, would also mean partials. So, you could add the following to your App1Controller:
class App1Controller < ApplicationController
def self.local_prefixes
[controller_path, "#{controller_path}/users"]
end
private_class_method :local_prefixes
end
Then, when you render 'demonstration_fields', :f => ud, your lookup path should look like (in order):
app1/_demonstration_fields,
app1/users/_demonstration_fields,
application/_demonstration_fields`

Rendering a view from my Ruby on Rails Gem

I created a simple Gem for Ruby on Rails; the idea is that it provides some code/views for common actions (index/show/etc.) that I use in several of my applications. I would like to "DRY it up" in a Gem.
Creating the Concern went without problems, however, I can't quite seem to manage to render a view in my application.
For example, in my lib/rails_default_actions/rails_default_actions.rb I do:
module RailsDefaultActions
module DefaultActions
extend ActiveSupport::Concern
respond_to do |format|
format.html { render 'default/index' }
end
end
end
end
But an error is raised:
Missing template default/index with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :slim, :haml]}. Searched in:
* "/home/martin/myapp/app/views"
* "/home/martin/myapp/vendor/bundle/ruby/2.1.0/gems/devise-3.2.4/app/views"
* "/home/martin/myapp"
I eventually sort of managed to hack my way around this error, but it feels very kludgey and doesn't work in some scenarios. What is the correct way to include views in a gem?
I looked at creating an Engine, but that seems like overkill, since I just have a concern and a few views.
The "correct" way to do this since Rails 3 is to create an Engine; there's also a Rails guide for this, but creating a basic engine is as easy as:
module MyGemName
class Engine < Rails::Engine
end
end
When Rails looks for a view to render, it will first look in the app/views directory of the application. If it cannot find the view there, it will check in the app/views directories of all engines that have this directory.

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.

Resources