Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Use of absolute path in Rails 6

Recently, I've upgraded a Rails app that I'm maintaining to Rails 6 RC2 (coming from 5.2.3). So, right after upgrading, I ran the automated tests (RSpec) and the test output gave me lots of deprecation warnings. One of those warnings was:

DEPRECATION WARNING: render file: should be given the absolute path to a file

So I went to the view file that triggered the warning, and made the changes as follows,

Before: render file: 'devise/sessions/new'

After: render file: Rails.root.join('app', 'views', 'devise', 'sessions', 'new.html.slim')

I ran the tests again, no output of deprecation warnings was seen. However, after switching to absolute paths, the view is now only rendering plain HTML code but if I remove the .slim extension, i.e.

render file: Rails.root.join('app', 'views', 'devise', 'sessions', 'new.html')

The corresponding view is rendered properly but now the test will complain about not using absolute paths. Is there a way to fix this or is this a Rails/Slim bug?

like image 282
DJenuil Avatar asked Aug 03 '19 02:08

DJenuil


2 Answers

In your case it looks like you want to render a normal view, i.e. a template.

In that case using the file option is not the recommended way. Instead you should be using the template option.

render template: 'devise/sessions/new'

Or even better, you can use this shortcut:

render 'devise/sessions/new'

Background

The file option is intended to render a view which is outside your Rails application, where you can't rely on Rails' view lookup logic. Consequently Rails wants to have an absolute path. Demanding an absolute path also forces the developer to think about relative path segments (/../).

Omitting the .slim extension and then having the file processed by the template engine is a feature intended for templates. Using file seems to provide the very same functionality, but my guess is that this is just a side effect of the internal workings of the view path lookup. It looks like the Rails developers want to improve the distrinction between files and templates in the future and deprecating relative files is an intermediate step to not break too many existing applications which rely on using file and still expect the features of a template.

PS: It is not necessary to manually split your path. So if you for some reason still want to use file with an absolute path, instead of

render file: Rails.root.join('app', 'views', 'devise', 'sessions', 'new.html.slim')

use this

render file: Rails.root.join('app/views/devise/sessions/new.html.slim')
like image 75
Daniel Rikowski Avatar answered Sep 29 '22 01:09

Daniel Rikowski


I had this same challenge when working on Rails 6 API-only application.

I wanted to render a static page from a controller called home_controller.rb

Here's my code:

require 'rails/application_controller'

class HomeController < Rails::ApplicationController
  def index
    render file: Rails.root.join('public/index.html')
  end
end

But when I try accessing the page I get the error:

Started GET "/favicon.ico" for ::1 at 2021-02-23 16:25:41 +0100
Processing by HomeController#index as */*
  Parameters: {"other"=>"favicon"}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms | Allocations: 301)
 
ArgumentError (`render file:` should be given the absolute path to a file. '/home/my-computer/Projects/MyWebsite/public/index.html' was given instead):

Here's how I solved it:

The issue was that I was missing the file index.html in the directory public, so Rails could not locate it.

All I had to do was to add the file index.html in the directory public. This time when I tested it was fine.

That's all.

I hope this helps

like image 39
Promise Preston Avatar answered Sep 29 '22 01:09

Promise Preston