Render a partial layout in rails - ruby-on-rails

I am trying to build a demo app like square space. I have a preview page where an iframe loads the template that was selected. So I decided that I wont be needing the default layout (application.html.erb). I created a new folder called Design1 in views and inside it created another folder called partials. I made _header.html.erb inside of it. I created another file called home.blade.php inside the Design1 folder and tried to include the 'layouts/header' in it and it gives me this err
Missing partial Design1/_header with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in: * "/usr/share/nginx/html/fuitter-test/app/views"
this is how I am rendering the header file in home.html.erb
<%= render 'layouts/header' %>
my forlder structuer
views
-Design1
-layouts
- _header.html.erb
-home.html.erb
-other folders
And I have also done
layout false
in the controller

First of all - always downcase on file names! Never use Design or MyCoolStory, in rails we use convention over configuration and that means snake_case which is everything downcased and separated with _under_scores
To your render issues:
There is a great documentation where you'll find anything you need: http://guides.rubyonrails.org/layouts_and_rendering.html
Let me help you a little.
Rails is looking for a Layout. By default it will be expected in /app/views/layouts/application.html.erb (there is nothing wrong with keeping it named as application). A Layout is the whole HTML Frame you will need. Within the Layout there (should) always be a yieldblock.
A YieldBlock in rails is where your templates are rendered into.
so basically a layout-file can look like this (i use haml for easier reading)
%html
%head
=render "shared/head"
%body
.wrapper
%nav.navigation=render "shared/navigation"
.main_content
=yield
%footer.foot=render "shared/footer"
This means you are having 3 partial-templates in /app/views/shared named _head.html.erb, _navigation.html.erb and _footer.html.erb
That's the rails way.
Further informations
If you are planning to have a multi-design app, you should structure your views in total like
/app/views/design1
/app/views/design2
/app/views/design3
/app/views/shared
and set the lookup path in your controller like this
prepend_view_path "#{Rails.root}/app/views/#{design_path}"
def design_path
current_page.design_name
end
By then, all views will be looked up into their specified folder (Spree multi_store engine, is doing like this, for an example)

You put your layouts folder in Design1 folder, thus you should use following path to render your layout:
<%= render 'Design1/layouts/header' %>

The render structure should be starting from the /views folder.
<%= render 'Design1/layouts/header' %>

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 possible to convert a string into a partial?

I have a string that stored in my database that is used as a custom layout.
I would like to parse their custom layout inside of my app layout, by using :
render_to_string(partial: custom_template, layout: "pdf_template", locals: locals)
Where custom_template is the string from the DB. However, when I try to do this I get :
NoMethodError: undefined method `to_sym' for nil:NilClass
Is it possible to do what I'm doing? If so, what can I do to complete this?
I've noted that I can try things like this :
render_to_string(text: template, locals: locals, template: "pdf_template")
And
render_to_string(inline: template, locals: locals, template: "pdf_template")
But doing so, it suddenly can't find the template and returns :
ActionView::MissingTemplate: Missing template layouts/pdf_template with {:handlers=>[:erb, :builder, :coffee, :haml], :formats=>[:pdf], :locale=>[:en, :en]}. Searched in:
* "/Users/elephanttrip/Sites/shasta/app/views"
Which is strange because it worked fine in its current location and definition.
If you want to store your views in the database, you should use another rendering engine rather than in Rails by default. Check liquid gem (http://railscasts.com/episodes/118-liquid, http://rubygems.org/gems/liquid).
For example, we use this gem to render emails for our maillists (their templates are stored in the DB).

Rails is Looking for a Partial in the Wrong Directory

I have a polymorphic Review model. The namespaced model User::Library::Publication is reviewable. The reviews are created properly, but when I try to display them through a partial, Rails looks up the wrong directory.
In my view:
<%= render #review %>
I get this error:
Missing partial user/library/reviews/review with {:locale=>[:en], :formats=>[:js, :html], :handlers=>[:erb, :builder]}
Rails is apparently looking for the review partial within the namespace's directory views/user/library instead of the /views/reviews. Any idea why this is happening?
If you want to remove namespacing from the partial template path, you can set the prefix_partial_path_with_controller_namespace variable in your config/application.rb:
# config/application.rb
config.action_view.prefix_partial_path_with_controller_namespace = false
This will load partial paths as you define them (without the namespace).
You can see the original Pull Request here.
If you use name spaces you have to create folders/sub folders so Rails is not looking at the wrong place.
If you want to force the partial path just use:
render :partial => "review"
And create rename the review.html.erb file to _review.html.erb

Missing partial when using devise 2.0 w Rails 3.1.3

I have a rails app (rails 3.1.3) that has a shopping cart model. I wanted to show a summary of the shopping cart in the layout so I created the partial views/carts/_cart.html.haml. My app was working fine and rendering the cart partial in every view. But when I installed devise 2.0, the partial could no longer be found for devise views. Instead, I would see the following error code when I tried to call a devise view:
ActionView::Template::Error (Missing partial views/carts/cart with {:handlers=>[:erb, :builder, :coffee, :haml], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
* "/Users/cameronnorgate/Web Development/Practice Apps/1-Camerons Tea/pgktea/app/views"
* "/Users/cameronnorgate/.rvm/gems/ruby-1.9.2-p290#pgktea/gems/devise-2.0.4/app/views"
As you can see, it searches for the partial in app/views, but doesn't go all the way into the 'carts' folder in order to find the 'cart' partial. This is weird, because the code I had in the layout view specified the exact path (see below):
%body{:class => params[:controller]}
.master_container
.master_header
.inner_header
.cart
= render :partial => 'views/carts/cart', :object => #cart
Can anyone help me understand why my call to render the partial is not being found when inside a devise view?
The short term fix I've made for this is to bring the partial code back into the full layout file - so now devise doesn't have to go searching and everything works... but that's not ideal and it's cluttering up my code.
Thanks!
You should be able to specify the partial with just:
= render :partial => 'carts/cart', :object => #cart
The views/ part of your definition is probably throwing it off. app/views is implied, so when you specify views/carts/cart, it's probably not finding a views directory under app/views.
If this page can be access from other pages . then
= render :partial => '/carts/cart', :object => #cart
Is the correct way , because if this page open in other models then 'carts/cart' will not be available like if url is ex. 'localhost:3000/products' this page will give missing partial error so / will solve the issue and as other answers, 'views' is not needed

rails 3 rendering a partial from a collection

I am trying to render a partial on a collection with <%= render #posts %> which returns the error:
Missing partial posts/post with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}
However it works if i use <%= render :partial => 'post', :collection => #posts %>
I have _post.html.erb in the same folder which uses post variable (from posts)
Why would the former example way of rendering a partial on a collection not work, but the latter example does work?
EDIT: I should specify I'm using Rails 3.2.1
The default of to_partial_path for your objects is always scoped under a view folder for the class, so your partial must be in the posts view folder.
When you use the form render :partial => 'post' it looks in the folder of the controller you are currently under.
I suspect that you are not working in the PostsController view folder, which would explain the behavior you are seeing. If you are working in the posts view folder, then something else must be going on so if you could provide more detail that would help diagnose it further

Resources