Relative Paths From Partials Referencing Other Partials
Asked Answered
D

3

25

I am using a (primary) partial:

<%= render partial: 'shared/page/head' %>

Which makes use of other (secondary) partials:

<head>
  <%= render partial: 'shared/page/head/title' %>
  <%= render partial: 'shared/page/head/meta' %>
  ...
  <%= render partial: 'shared/page/head/fonts' %>
  ...
  <%= render partial: 'shared/page/head/google_analytics' %>
</head>

As you can see I'm currently using paths relative to app/view for these secondary partials even though they are sitting in the same directory as the primary partial.

I've tried using relative paths:

<%= render partial: 'title' %>

Or

<%= render partial: './title' %>

But neither work.

Is there a way to have a partial resolve partials it uses using a relative path?

Dennard answered 9/10, 2013 at 10:19 Comment(2)
Please list the actual paths to your partialsOliveolivegreen
If you think about your first partial inclusion, that inclusion doesn't 'reset' the working folder of the view being built. If the view being rendered is app/views/projects/show.erb, the "render partial: 'shared/page/head'" is just "go grab the contents of that file, then render it here" - you're still in the app/views/projects folder.Improper
B
3

This might be one solution to your problem: http://apidock.com/rails/ActionController/Base/prepend_view_path

Bluebell answered 19/3, 2014 at 13:22 Comment(1)
github.com/rails/rails/issues/12973 here is some more explanation on how to use it.Reducer
P
1

I wrote a helper method for this which works perfectly:

def render_relative_partial(relative_path, option={})
    caller_path = caller[0].split(".")[0].split("/")[0..-2].join("/")
  path = caller_path.gsub("#{Rails.root.to_s}/app/views/","") + "/#{relative_path}"

  option[:partial] = path
  render option
end 
Pollinize answered 26/5, 2019 at 3:28 Comment(1)
Nice solution! Very frustrating its not built in. For me I made a little adjustment and changed the last two lines with render partial: path, locals: option Loyola
S
1

As mentioned by another poster, prepend_view_path can be used to achieve this.

Here is how to implement it:

controllers/shared_page_controller.rb

class SharedPageController < ActionController::Base
  before_action :set_view_paths

  # ... 

  private

  def set_view_paths
    prepend_view_path 'app/views/shared/page/head'
  end
end

views/shared/page/head.html.erb

<head>
  <%# This will try to find the partial `views/shared/page/head/title.html.erb` %>
  <%= render partial: 'title' %>
  <%= render partial: 'meta' %>
  <%# ... %>
  <%= render partial: 'fonts' %>
  <%# ... %>
  <%= render partial: 'google_analytics' %>
</head>

Now Rails will not only look for partials in app/views, but also app/views/shared/page/head.

Saltatorial answered 20/12, 2019 at 8:50 Comment(1)
If you're here in 2023, this one worked for me. However I had to use an '/' at the beginning of the partial name in the view. Instead of render partial: 'title' I had to use render partial: '/title'Whitening

© 2022 - 2024 — McMap. All rights reserved.