1

I'm trying to build a little todo app with rails 4 and react. Nothing really hard, it's just a beginning to learn how to use react with rails, but I have difficulties on how to code my rails controllers.

  • The two urls reachable at the moment are "mysite.local" to display all the todos, and to "mysite.local/todos/1" to display a specific todo with more details.

  • I have a Todos controller that I use to respond to the AJAX calls related to the todos.

  • The view that contains the react app is not a "Todos" view because I will add more than just todos in the futur and the react app will have to handle everything.

What I want to do is simple: I want rails to always render the view with the react app regardless of the url used to reach the website. All the controllers in my app (like the Todos controller) are just used to retrieve JSON datas that will be manipulated by react.

The solution I found is to put the react app in the application layout. That way, it will always be present when someone go on the website for the first time. Since it's in the layout it will not be rendered again, the react app can do its job.

My controllers then looks like this:

class TodosController < ApplicationController

def index
    respond_to do |format|
        format.html
        format.json { Todo.all }
    end
end

def create
    respond_to do |format|
        format.html
        format.json { Todo.create(todo_params) }
    end
end

def show
    respond_to do |format|
        format.html
        format.json { Todo.find(params[:id]) }
    end
end

private
    def todo_params
        params.require(:todo).permit(:content)
    end
end

With a controller like this, I can make my AJAX calls and get a JSON, which is the only datas my controller will send, and at the same time I can still reach "mysite.local/todos/1" and rails will do nothing except rendering an empty view.

This method works, but I don't like it because the controller render a view for each action. When someone reach the website for the first time, an empty view will be rendered. Even if the view is empty and it will not display anything on the browser, rails still have to do all the process to render the view. I don't know if this process really cost something, but I don't like the fact that my application is doing something useless.

Is there any way to tell rails to literally do nothing if the format action is html? (= not rendering the "index", or "show" view?)

Or is there a better way to do what I want to do?

Thanks


EDIT

Thanks to gobluego, I modified my application a little. I created a Front controller to handle the client part. Then I moved my Todos controller in an api folder.

Here is my routes.rb file now:

root "front#index"

namespace :api, constaints: { format: 'json' } do
  resources :todos, only: [:index, :create, :delete, :show]
end

get '*path' => "front#index", via: :all

and my new Todos controller:

class Api::TodosController < ApplicationController
respond_to :json
before_action :ensure_json_request 

def index
    respond_with Todo.all 
end

def create
    respond_with Todo.create(todo_params)
end

def show
    respond_with Todo.find(params[:id])
end

private
def todo_params
    params.require(:todo).permit(:content)
end

def ensure_json_request  
  return if request.format == :json
  render :nothing => true, :status => 406  
end 
end

That way, any url is handled by front#index, except all the apis urls, which is what I want. To ensure that nothing is rendered if, for example, someone tries to reach mysite.local/api/todos in the browser, a before_action is used and it render nothing if the format is not json.

1 Answers1

0

Why not use pages#index instead as the root path? That way, TodosController is only responsible for being the back end service for your app.

As an additional measure you can enforce that both requests and responses are only of JSON format. As for the implementation of that, this is a a good starting point.

jemonsanto
  • 513
  • 8
  • 19