How to render file in Rails 5 API?
Asked Answered
R

4

13

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.

Religiose answered 11/5, 2017 at 9:47 Comment(8)
try render_to_string file: 'public/index'Lettielettish
@Md.FarhanMemon empty responseReligiose
add extension and see, .htmlLettielettish
@Md.FarhanMemon still emptyReligiose
did you try render html: 'file_name'?Lettielettish
also try calling from base, ActionController::Base.helpers.render file: 'public/index.html'Lettielettish
Yes, it literally renders the argument as html page. I even tried render html: File.open('public/index.hml') with no luck.Religiose
calling render from base should work I think..Lettielettish
F
29

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.

Fredricfredrick answered 11/5, 2017 at 10:20 Comment(0)
S
1

You could do

render text: File.read(Rails.root.join('public', 'index.html')), layout: false
Stephi answered 11/5, 2017 at 10:9 Comment(4)
This renders the content of the file as text on webpage. Also tried the same with html: option.Religiose
Sorry, I do not understand the question then, but it seems you have an answer now :)Stephi
text is deprecated in Rails 5.Lunge
@pj.martorell I think it is now plain.Stephi
F
0

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/"

Folks answered 7/5, 2021 at 4:6 Comment(0)
T
-1

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.

Thorwald answered 22/10, 2017 at 0:38 Comment(1)
It doesn't work undefined method respond_to' for #`Actinozoan

© 2022 - 2024 — McMap. All rights reserved.