Start writing API’s in Rails
With the popularity of Javascript frameworks and the move to cross platform development, Now is a good time to start writing your green-field applications with an API first mindset.
Rails 5 has been announce to have a new --api
flag included for your
disposal, but this functionality has been around for over a year in
the rails-api gem.
The idea of building a Rails API is to remove the unneeded magic that is not needed when rendering just JSON. You also gain the ability to be flexible in choose which how you want to render your front-end and whether or not you want to build an iOS and/or Android app with the same database.
Getting Started
Setting up the rails-api globally requires you to use the gem
command instead of the bundle
command you would normally use in a project.
$ gem install rails-api
$ rails-api new my-api
Create your model
$ rails g scaffold movie title:string rating:string
$ bundle exec rake db:migrate
$ rails s
$ open https://localhost:3000/movies
# You should see an empty array.
Add the data using Faker
Gemfile
# ...
gem 'faker'
#...
$ bundle install
# db/seeds.rb
20.times do
Movie.create(
title: Faker::Lorem.words.join(' '),
rating: ['NC17', 'R', 'PG13', 'PG', 'G'].sample
)
end
$ bundle exec rake db:seed
Now revisit https://localhost:3000/movies
and you will see you movies.
Create your serializer
Now that is out of the way you can began creating all your models and serializers using the rails generators provided. These generators give you a quick way to get you test, controllers, and serializers. To take advantage of serializers you will need to install ActiveModelSerializers.
Gemfile
# ...
gem 'faker'
gem 'active_model_serializers', '~> 0.8.3'
#...
$ bundle install
A specific version number needs to be specified in the Gemfile due to some release candidates not being backwards compatible (more on that issue).
Serializers are separate from your models, think of them similar to how
you whitelist attributes in the attr
reader and writer of your model or strong params in your controllers.
Only the models and attributes that have been serialized will be render publicly to JSON. I recommend installing the JSONView plugin to view JSON with more readability in the browser.
$ rails g serializer Movie title rating
You will now notice when you refresh the page the created_at
and updated_at
are no longer
there. This is because they were not white listed in the serializer. You
will also notice the table is now serialized with the name movies
as
well. This is part of the new json-api conventions.
You can add or delete white listed attributes in the
serializers/movie_seriliazer.rb
.
Add the director method to the serializer and white list the attribute director.
# serializer/movie_serializer.rb
class MovieSerializer < ActiveModel::Serializer
attributes :id, :title, :rating, :director
def director
Faker::Name.name
end
end
If you notice every time you refresh your api, the director’s name changes. It is more ideal to add this new attribute and method to your model to persist to the database, but some methods that require live and changing data on refresh can more realistically store in the serializer.
Enabling CORS
Enabling CORS is a way to grant access to your API to other sources, without opening up this access, your rails app will prevent any JS frameworks or clients from seeing any portion of your API.
This was a step that I had to learn the hard way, but am giving to you for free. Please take to the time study up on securing your REST API the right way and making your api RESTful. Rails has built security to prevent other malicious access, so only enable CORS when necessary.
I recommend the rack-cors gem for accomplishing this.
Gemfile
# ...
gem 'faker'
gem 'active_model_serializers', '~> 0.8.3'
gem 'rack-cors'
#...
$ bundle install
# config/application.rb
module MyApi
class Application < Rails::Application
# ...
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
end
end
Bonus
Your api is ready to be consumed by your mobile and client apps. It is also worth taking a look at Web Tokens in a JS Frontend if you plan on adding authentication to your application.
The knock gem handles a lot of that for you.