The Rails 5 release is almost upon us, and it’s jammed packed with upgrades and new features. The one I’m most excited about is the Rails::API gem integration.
Rails::API and Rails 5
As a newcomer to Rails, I’m very excited for the soon-to-be released Rails 5. The main reason is that this might be the version I’ll be working with the most to develop my skills. Wanting to get a head start and have a deeper understanding of Rails, I cloned the current version and have had lots of fun exploring all the new features.
One of the features that excite me the most is the Rails::API integration. Using it has been tons of fun, not to mention super easy. So back in April a decision was made to integrate Rails::API gem into Rails core for the release for Rails 5. This new addition allows for an API-only Rails project that comes with a reduced middleware stack, lightweight controllers, and customised generators.
I’ve had a chance to play and have plenty of fun with the up-and-coming feature, so I’m going to share with you how I went about it and the pitfalls to avoid.
Setting up
First thing to do is make sure you have Ruby 2.2.2+ as Rails 5 will require Ruby 2.2.2 or newer.
App generation
According to the Rails guide, you will be able to generate an API app using the following command:
$ rails new my_api --api
However this feature of Rails isn’t released yet so we have to generate our Rails API app using the latest version. Simply clone the master branch from the Rails repo.
To generate the project using rails new
I used the following command from the cloned Rails repo.
$ bundle exec railties/exe/rails new ~/repos/note-taking-api --api --edge
Sweet! Just like that we have a new API-only Rails 5 project. All we need to do now is run bundle and rake to install the gems and set up the database.
We need to make sure that we are running these commands using Rails 5 and not a previous version installed on our system. So run the executables from the bin folder
bin/rake
bin/rails
Scaffold the resource
$ bin/rails g scaffold note title note:text
When scaffolding or generating resources you don’t need any special arguments. If the app is built with the --api
flag, the generators should be customised to create the relevant files.
invoke active_record
create db/migrate/20151002101900_create_notes.rb
create app/modelels/note.rb
invoke rspec
create spec/models/note_spec.rb
invoke factory_girl
create spec/factories/notes.rb
invoke resource_route
route resources :notes
create app/serializers/note_serializer.rb
invoke scaffold_controller
create app/controllers/notes_controller.rb
invoke rspec
create spec/controllers/notes_controller_spec.rb
create spec/routing/notes_routing_spec.rb
invoke rspec
create spec/requests/notes_spec.rb
If the Active Model Serializers file didn’t get generated, you can use the command bin/rails g serializer note title note
to generate it.
All that is left now is to migrate and you can run the app so we can test the endpoints.
$ bin/rake db:migrate
Test endpoints
With very little we have a simple CRUD API endpoint, which we can fire up and test these endpoints. I use the POSTMAN Chrome extension. However, you can use curl
from the terminal to be able to test it.
Post Request
When you make get request after scaffolding the app you should get a blank response like so:
If you are following along and have tried to post, you may have ran into this NoMethodError (undefined method `permit!). In the notes_controller simply change:
def note_params
params.require(:note).permit(:title, :note)
end
to
def note_params
params.permit(:title, :note)
end
The last answer in this stackoverflow thread should explain it well.
I filled out the post request and sent through the raw data to the API path:
Get Request
Change back to a get request to see the newly created notes:
Get a single note:
Put / Patch Request
An example of a put request:
An example of a patch request:
Keep in mind that both PUT and PATCH are routed to update. You can read this article which has a really good explanation of the difference between the two.
# PATCH/PUT /notes/1
def update
if @note.update(note_params)
render json: @note
else
render json: @note.errors, status: :unprocessable_entity
end
end
Delete Request
By default after deleting a note nothing is returned:
# DELETE /notes/1
def destroy
@note.destroy
end
This is fine but we need a way to let our app know that something happened. To keep this as simple as possible for now lets just return something after the deletion. We can pass no content(204) status code, which means that the server successfully processed the request, but is not returning any content. We can render nothing: true
, although when you use this, Rails still uses the status 200 by default so we need to pass through the status code of 204.
# DELETE /notes/1
def destroy
@note.destroy
render nothing: true, status: 204
end
That’s all folks!
Conclusion
As you can see, creating an API app with rails just got a lot easier. Keep in mind that it isn’t production ready and they still need to iron out a few bugs. Find out more below and see other example of the new feature.
More reading
The original pull request for the integration of the Rails::Api gem in to rails core.
Caching and throttling are useful aspects of an application. It is important to help serve API requests faster and also limit the amount of request that can be made.
The two links below give an in-depth description of how to integrate the API endpoint with front-end Javascript apps.