Outline

Rails comes with a router in config/routes.rb. This file contains all the the urls your application will respond to. This Rails guide is a good reference to using Rails' router. Let's create some routes that our Angular application will eventually interface with. Rails' router comes with a useful resources function which we can use to specify RESTful routes, which we can also nest in blocks to create nested routes.

Add routes to routes.rb for :posts and :comments using resources. We only need some of the routes that resources provides us with by default, so we'll use the only: option specify the actions we want. We'll need to create our own put routes for upvoting. Putting it in a member blocks makes it so our url parameters map to :id instead of :post_id.
  root to: 'application#angular'

  resources :posts, only: [:create, :index, :show] do
    resources :comments, only: [:show, :create] do
      member do
        put '/upvote' => 'comments#upvote'
      end
    end

    member do
      put '/upvote' => 'posts#upvote'
    end
  end
Run rake routes to see all the routes you created.

Once you've seen the routes we've configured, let's generate our controllers for posts and comments. We'll need to use the --skip-assets and --skip-template-engine flags since we'll be creating our own javascript files and templates.

rails generate controller Posts --skip-assets --skip-template-engine
rails generate controller Comments --skip-assets --skip-template-engine
In order for our controllers to respond in the json format, we need to add the following respond_to statement in ApplicationController:
  protect_from_forgery with: :exception

  respond_to :json

Let's start adding actions to our controllers. We'll be using the respond_with method in our actions to return json to our endpoints. Don't forget to permit the data coming from the user with strong parameters. We'll need an index, create, show, and upvote action to correspond with the routes we just created. Since we're using Rails 4, we'll need to also specify which parameters we want permitted in our controllers

Add a method to permit the :link and :title attributes in PostsController:
  def post_params
    params.require(:post).permit(:link, :title)
  end
end
Create the index, create, show, and upvote action PostsController:
  def index
    respond_with Post.all
  end

  def create
    respond_with Post.create(post_params)
  end

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

  def upvote
    post = Post.find(params[:id])
    post.increment!(:upvotes)

    respond_with post
  end

  private
  def post_params
    params.require(:post).permit(:link, :title)
  end
end
Add a method to permit the :body attribute for comments in CommentsController:
  def comment_params
    params.require(:comment).permit(:body)
  end
end
Create the create and upvote actions in CommentsController:
  def create
    post = Post.find(params[:post_id])
    comment = post.comments.create(comment_params)
    respond_with post, comment
  end

  def upvote
    post = Post.find(params[:post_id])
    comment = post.comments.find(params[:id])
    comment.increment!(:upvotes)

    respond_with post, comment
  end

  private
  def comment_params
    params.require(:comment).permit(:body)
  end

We respond with both post and comments in CommentsController because we are using a nested resource, although only the last object is returned when responding to json.

Our Rails backend is now ready to be wired up to our angular app!

 

I finished! On to the next chapter