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.
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
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
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
:link
and :title
attributes in PostsController
:
def post_params
params.require(:post).permit(:link, :title)
end
end
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
:body
attribute for comments in CommentsController
:
def comment_params
params.require(:comment).permit(:body)
end
end
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!