Reputation: 868
I have a single-page application written in React with Ruby on Rails back-end (API mode). Rails is also serving static files. I'm pointing Rails router to public/index.html
, so my SPA could manage his own routing with react-router
. This is common practice in order to make direct links and refresh to work.
routes.rb
match '*all', to: 'application#index', via: [:get]
application_controller.rb
class ApplicationController < ActionController::API
def index
render file: 'public/index.html'
end
end
The problem is this doesn't work in API mode. It's just an empty response. If I change the parent class to ActionController::Base
everything works as expected. But I don't want to inherit the bloat of full class, I need slim API version.
I've tried adding modules like ActionController::Renderers::All
and AbstractController::Rendering
without success.
Upvotes: 13
Views: 12985
Reputation: 591
I usually just redirect_to 'file path'.
def export
# When the route coming to get 'some_report/export', to: 'greate_controller#export'
# The file where you write or preparing, then you can redirect some path like : http://localhost:3000/public/tmpfile/report20210507.xlsx
# And it will just redirect the file for you
file_path = "public/tmpfile/report20210507.xlsx"
redirect_to "#{root_url}#{file_path}"
end
For this example
root_url = "http://localhost:3000/"
Upvotes: 0
Reputation: 667
This should work, and allow you to keep inheriting from ActionController::API--
class ApplicationController < ActionController::API
def index
respond_to do |format|
format.html { render body: Rails.root.join('public/index.html').read }
end
end
end
The render logic changed for ActionController::API with Rails 5.
Upvotes: -1
Reputation: 230336
If I change the parent class to ActionController::Base everything works as expected. But I don't want to inherit the bloat of full class, I need slim API version.
Yes, if you serve index from ApplicationController, changing its base class would affect all other controllers. This is not good. But what if you had a specialized controller to serve this page?
class StaticPagesController < ActionController::Base
def index
render file: 'public/index.html'
end
end
This way, you have only one "bloated" controller and the others remain slim and fast.
Upvotes: 29
Reputation: 19948
You could do
render text: File.read(Rails.root.join('public', 'index.html')), layout: false
Upvotes: 1