Api only App –Rails–5 Hurray….

on

Rails5 Rc1 released. Here I will show to implement a simple app using the  rails 5 .

install 2.2.2+ or 2.3.0 ruby

if you have rvm . then using the following command.

rvm install 2.3.0

 

Install Rails 5

gem install rails --pre

Create Api only APP:

by using the command

rails new rails_5_user_api –api

–api created only the files needed for the api and rails does not created the other files like views when we scaffolding the model.

api_creation2_api_created

 Install CORS gem:

The need for the cors gem is to  Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible. uncomment the gem ‘rack-cors’

cors.png

do

bundle install

install Rspec:

group :test do
gem ‘rspec’
gem ‘rspec-rails’
gem ‘factory_girl_rails’
gem ‘shoulda-matchers’, ‘~> 3.0’, require: false
gem ‘database_cleaner’, ‘~> 1.5’
gem ‘faker’, ‘~> 1.6.1’
end

to your gem file  also

add   gem ‘rspec-rails’ to group development, test part

then bundle

rspec_gem.png

do the

rails generate rspec:install

will create the spec_helper and rails_helper, .spec etc..

rspec_install.png

create a controller via scaffold generator:

remove the test folder and associated contents in that.

rails generate scaffold user name:string email:string

 

scaffold.png

will create the controller, also specs and controllers etc.

add some User validations in model

validates :email, presence: true, uniqueness: true

user_validations.png

do the

rails db:migrate

migration_.png

serialization :

Serializer is the important part in API, when we request for data, only serialized output  comes as response.

gem active_model_serializers will helpful to do that.

 

active_model.png

do bundle install

generate the serializer:

rails generate serializer user

serializer_helper.png

user_serializer

by default only the id is there , we can add the attributes to be serialized, in this case; we have used all the attributes.new_serializer.png

now when we call Api , will return id, name,email.

Controller updation to Post the data:

normally after rails4 , we allow only trusted parameter to update. It is fine for App, but for the Api , we have some complications Api we can use other mechanisms. for Details look in this post in Stack Overflow.

before_updation.png

modify above to this

   def user_params
params.permit(:name, :email)
end

How to Test API:???

That is the important question in mind when we read this. Dont worry there is always a solution for everything.In this context; we have POSTMAN :D. It is a chrome app free downloable from chrome webstore.

postman.png

postman2.png

launch the app:

start the rails server.

rails server

postman_empty_json

there is no data, hence the empty braces look at the status 200. all ok. So we need to post an information, We put the email validation and presence should be true and unique.

select the post and sent the value as json.

post_value_json.png

to view the  json data.

http://localhost:3000/users

get_index.png

all done, API is working fine . if you like you can test the put,delete actions if you like.

Api Versioning:

The next task is to update the Api Versioning .Versioning breaks your API up into multiple version name spaces, such as v1 and v2, so that you can maintain backwards compatibility for existing clients whenever you introduce breaking changes into your API, simply by incrementing your API version.

update your controller:

we can follow /controllers/api/vi/users_controller.rb

controller_new_path.png

update your controller file:

controller_file_change.png

update config/routes.rb

routes_old

You need to update the file with new versioning mechanism type

Rails.application.routes.draw do
namespace :api, defaults: { format: ‘json’ } do
namespace :v1 do
resources :users
end
end
end

version_new.png

Rack Attack:

is meachanism which prohibits the unauthorised and spam attacks to the Apis.
gem ‘rack-attack’ add to your gemfile.
there are blacklist and white list and number of responses in a minute, we can set in the rack_attack initializers.
create a file called rack_attack.rb in config/initializers.rb/

and paste below codes:

class Rack::Attack

# `Rack::Attack` is configured to use the `Rails.cache` value by default,
# but you can override that by setting the `Rack::Attack.cache.store` value
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new

# Allow all local traffic
whitelist(‘allow-localhost’) do |req|
‘127.0.0.1’ == req.ip || ‘::1’ == req.ip
end

# if you want to block particular ip then you need to enable and check the current ip
# in the below blacklist
# Rack::Attack.blacklist(‘block local-host’) do |req|
# # Requests are blocked if the return value is truthy
# ‘127.0.0.1’ == req.ip
# end

# Allow an IP address to make 5 requests every 5 seconds
throttle(‘req/ip’, limit: 5, period: 5) do |req|
req.ip
end

# Send the following response to throttled clients
self.throttled_response = ->(env) {
retry_after = (env[‘rack.attack.match_data’] || {})[:period]
[
429,
{‘Content-Type’ => ‘application/json’, ‘Retry-After’ => retry_after.to_s},
[{error: “Throttle limit reached. Retry later.”}.to_json]
]
}
end

we can set which ip is to be whitelisted and which ip is to be blacklisted and Allow an IP address to make 5 requests every 5 seconds

block the local requests via Rack::Attack gem

bundle the gemfile.

add the below line to application.rb and restart your server.

config.middleware.use Rack::Attack

then uncomment the thses lines.

Rack::Attack.blacklist(‘block local-host’) do |req|
# Requests are blocked if the return value is truthy
‘127.0.0.1’ == req.ip
end

then tries to access the  url

http://localhost:3000/api/v1/users

rack_attack.png

it shows the forbidden message.

Create a User with no Error Message:

When user is created it is redirected to show page. currently it is redirected as per the scaffolding path. What we need to do is to redirected to original path in api/v1/users

as per the scaffolding it is

old_controller_route.png

After versioning the controller route is :

new_routes_via_rake_routes.png

new users_controller.rb is

post_value_json.png

 

post_success_console.png

users_controller_new_code.png

Destroy a user :

delete_no_messagedelete_console_old

upon delete a user , if there is a mechanism delete if success then pass as json

user_code_old.png

update the  users_controller destroy action with

def destroy
@user.destroy
render json: { “status”: “student #{@user.id} deleted” }
end

Now when we delete a user,  it return a json status saying that you are successfully destroyed the user with id.

Showing a User if no user Present??

suppose you tried to display user with id = 333, but that user may not available, then it might throw an error. check the below example.

show_error.png

show_error_console

So we need to create a json response if no user with particular id is found.

users_controller.rb

 def show
if @user.nil?
render json: {‘Bad Data’: ‘No User found’}
else
render json: @user
end
end

also updated  the set_user action(private method) replace find with find_by_id as a safe meachanism.

def set_user
@user = User.find_by_id (params[:id])
end

show_invalid_user.png

All done in the Next tutorial I will explain how  to implement the basic mechanism to authorize the Apis.

Thanks All

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s