1

I have an app that I've built with ruby on rails in the backend with the front end being simple rails views. I'd like to add react to the front end to make it look nicer. I have read about using the react-rails gem, or creating a new react app and using the rails app as API only, so I'm wondering what the best approach is. I also used the devise ruby gem for handling user auth-- but I have seen some things that suggest I need to use the devise_token_auth gem if I want to go the rails API route... How would you approach adding a react front end to a fully built rails app?

greg
  • 11
  • 3

1 Answers1

1

Ive done both styles that you mentioned, in my own experience i liked more having a separated react project and using a rails api maybe because i use docker for my builds and had several problems when i used the rails-react gem and webpacker but the advantage is that you wont have to do 2 deploys, in both approaches you would have to setup APIs.

ps : webpacker precompiles in rails can get pretty heavy sometimes

For both you will need a devise JWT token for the authentication tho, here is a nice tutorial on how to set it up

if you want to have both auth methods (html & json) you can use something like this in your sessions controller

    class Users::SessionsController < Devise::SessionsController
  respond_to :json, :html
  # before_action :configure_sign_in_params, only: [:create]

  def create
    if request.format.html?
      super
      # super {
      #   cookies[:token] = current_token || ""
      # }
    else
      resource = User.find_for_database_authentication(email: params[:email])
      return invalid_login_attempt unless resource

      if resource.valid_password?(params[:password])
        sign_in(resource, store: false)
        @payload = [resource, current_token]
        render(status: 200, success: true, json: @payload)
      else
        invalid_login_attempt
      end
    end
  end

  def invalid_login_attempt
    warden.custom_failure!
    render json: {
      success: false,
      message: 'Error with your email or password'
    }, status: 401, status: :unauthorized
  end

  def current_token
    request.env['warden-jwt_auth.token']
  end

  private

  def respond_with(resource, _opts = {})
    if request.format.html?
      super
    else
      render status: 401, success: false, json: { error: 'No autorizado' }
    end
  end

  def respond_to_on_destroy
    if request.format.html?
      super
    else
      head :ok
    end
  end
end

there is probably a best way to do this but works for me lol