Rails: Use of absolute path in Rails 6
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
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')