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