Sharing partials among layouts - ruby-on-rails

I have a couple of layouts main.html.haml and alternative.html.haml, which share some elements. I would like to have a partial to share between them.
Using render ='my_partial' doesn't seem to work. How should I go about it?

If you have created partial inside layouts folder then
try this
<%= render :partial => 'layouts/partial' %>
Hope this will help you

Related

The render class did not render the file at rails?

I am newbie with rails and here is my problem
I tried to write a very simple program with rails, and when I wrote an application.html.erb, it worked well.
Here is what I got
But, when I created a folder named "shared" and a file named _navbar.html.erb in that folder, I thought that I could render my code from that file navbar.html.erb to the file application.html.erb by this code
<body>
<%= render "shared/navbar" %>
<%= yield %>
</body>
The folder shared/_navbar.html.erb is in the folder views, which means it in the same folder with the folder layouts/application.html.erb
I am setting rails -v 7.0.4 and ruby -v 3.1.2
Here is all of my code, if you need
https://github.com/nguyencuc2586/freelancer
Could you please give me some advices ? Thank you very much for your time.
Quote from the Rails Guides about Layouts and Rendering:
This makes app/views/application/ a great place for your shared partials, [...]
Following that advice from the official Rails guides, I would place the shared partial with the navigation into app/views/appplication/_navbar.html.erb and would call it from the layout view like this:
<%= render "navbar" %>
Alternatively, place the shared partial at app/views/shared/_navbar.html.erb and call it from the layout like this:
<%= render "shared/navbar" %>
Or, place the shared partial at app/views/layouts/shared/_navbar.html.erb and call it from the layout like this:
<%= render "layouts/shared/navbar" %>

Rails 5: Rendering a partial to the application layout

Within views/layouts/application.html I have the line <%= yield %>. This line is ultimately replaced by views directly corresponding to controller actions without any problems.
In one of my controllers, I am trying to render a partial instead of the default behaviour:
def show
#service_groups = ServiceGroup.where(deleted_at: nil)
render partial: 'table', locals: {rows: #service_groups, headers: service_group_headers}
end
I'm using a partial in this way so that I can use the same basic table structure for various different database tables (across different controllers).
This render partial code doesn't seem to work with the <%= yield %> line in the application layout. The partial code is just rendered on its own without the surrounding layout.
Why is this?
How do I rectify the problem?
Please let me know if I should be handling this a different way.
Thanks.
(migrating from comments)
What if you created a show.html.erb for that controller and placed render :partial there? It should work.
Explanation: Partials are to be used from "big" views. So, they are not wrapped in the layout on purpose!

How do I use different partials and layouts in subfolders?

I need to use a single partial for anything inside my views/admin folder. My setup:
/app/views/
+ admin
+ accounts
+ users
+ layouts
- application.html.slim
+ application
- _header.html.slim
+ users
+ accounts
I have a partial called _header.html.slim in /views/application/. The partial is rendered from /views/layouts/application.html.slim.
I want to render a different _header.html.slim partial for anything under the /views/admin dir. I can create a new _header.html.slim and add it to /views/admin/accounts and /views/admin/users, but I don't want to repeat my self. I want a single partial for everything under admin.
How can I so this? I tried adding /views/admin/application and /views/admin/layouts folders hoping they would override the ones in the /view dir, but no luck.
layouts/application.html.slim:
- if controller.controller_name == "admin"
== render :partial => "admin/header"
- else
== render :partial => "application/header"
The structure of the folders themselves don't control which ones get run or applied - the folder structure is really just to help you organize it in a way that makes sense.
You could accomplish what you're looking for in a couple of ways, depending on your needs:
One way is to specify the layout (which includes the desired partials) in the controller, using the render :layout => 'some_layout_name' option as outlined here (skip to the heading "2.2.11.2 The :layout Option" for the specifics).
Another way is to set a variable in your action that contains, say, the name of the layout(s) or partial(s) you want to render, and in your view do something like:
<% if #custom_partial == "slim" %>
<%= render :partial => 'header.html.slim' %>
<% end %>
So, either specify a custom layout (if you want the whole layout including partials to be custom), or set a flag variable that controls which partials get rendered at which time, and use that variable to control the flow of rendering in your view. Which of those options is right for you depends really on which is cleaner, most reliable, and makes sense for your project; that is, it's up to you to decide.

Universal partial?

I made a partial for a site and my client loved it. It was basically just a sidebar that helps browse the database. Now he wants the sidebar all throughout the site on various pages. So, how can I call a partial from any controller without having to copy and paste the file into each directory.
Thanks in advance!
You could try placing your partial in a folder call shared inside app/views and doing something like:
render :partial => 'shared/sidebar'
where you want to render the partial.
Yes you can:
<%= render "partial_folder/partial_name" %>
Example:
<%= render "layouts/sidebar" %>

Where to put partials shared by the whole application in Rails?

Where would I go about placing partial files shared by more than one model?
I have a page called crop.html.erb that is used for one model - Photo.
Now I would like to use it for another model called User as well.
I could copy and paste the code but that's not very DRY, so I figured I would move it into a partial.
Since it's shared between two models - where would I place that partial?
Thanks!
The Rails convention is to put shared partials in /app/views/shared.
Update
Layout inheritance is now in the guides under layout and rendering
Template inheritance works similarly.
Rails 3.1 and following versions implement template inheritance, so I think the correct place for shared partials is now /app/views/application/, say you are in products#index you can do the following:
-# products#index
= render #products.presence || 'empty'
-# /app/views/application/_empty.html.haml
There are no items
btw it's application because the connection is the controller inheritance, so this assumes ProductsController < ApplicationController
This way if you implement /app/views/products/_empty.html.haml that will be taken, the above is a fallback for all the missing partials, and I can't check right now, but I think even for the template itself...
Railscast: template inheritance!
TL;DR
Rails 3.1, Rails 4, Rails 5 and whatever comes next
app/views/application
The engine searches this path automatically if the view is not found in the controller path.
Rails 3 and prior
app/views/shared
The engine does NOT search this path automatically.
Long story
Rails 3 (and prior version) have no default location for storing shared views.
The unofficial convention is to store shared views in app/views/shared. Wherever you'd end up storing them though, you have to specify the path
# render app/views/shared/menu.html.erb
<%= render :partial => "shared/menu" %>
This suggestion was popularized by Agile Web Development with Rails.
Rails 3.1 introduces an official standard for where to store shared views:
app/views/application
Thanks to this standard, the engine now automatically looks for templates in app/views/application. As a result, you don't have to use the full path anymore.
Those curious can follow here the thought process behind this decision.
Old syntax
# render app/views/application/menu.html.erb
# unless menu.html.erb is found in appp/views/my_controller
<%= render :partial => "menu" %>
New syntax
# render app/views/application/menu.html.erb
# unless menu.html.erb is found in appp/views/my_controller
<%= render partial: "menu" %>
Of course, you can still place your shared views wherever you want and reference them by path
<%= render :partial => "my_own_special_shared_folder/menu" %>
Unless you have a very good reason to do this though, please stick to the new standard and store your shared views in app/views/application.
The Rails View uses app/views/layouts for shared partials like header and footer, but the Ruby on Rails Guide uses app/views/shared in an example. I guess it comes down to personal preference. I would use layouts for high-level stuff like a main nav or a footer, but shared for more narrow controller-level stuff like a form.
I general have a shared folder in my views that contains commonly used partials.
I arrived here in 2021 (rails 6) and got confused by the answers (many different ways).
I asked some senior rails developers what they'd do and they also gave me 2 different answers.
But TL;DR
Create a folder called 'shared' or 'application' inside your views folder (e.g. app/views/shared or app/views/application.
Then simply move the partial there, and access it with either
<%= render partial: 'shared/socials' %>
# or
<%= render partial: 'application/socials' %>
or even simpler
<%= render 'shared/socials' %>
# or
<%= render 'application/socials' %>
It doesn't matter where you put them. You can render any partial at any arbitrary location by providing the file's path to render - it doesn't need to be associated with the controller that's rendering it. I use a directory simply called partials under the view directory, and call partials in it like this:
render :partial => 'partials/mypartial'

Resources