How to Create a Rest API for a Ruby Application

How to create a REST API for a Ruby application?

You can use Sinatra to write tiny, focused web applications and lightweight REST services very quickly.

In the documentation section they highlight a couple of videos on that matter:

  • Adam Wiggins and Blake Mizerany present Sinatra and RestClient at RubyConf 2008. The talk details Sinatra’s underlying philosophy and reflects on using Sinatra to build real world applications.

  • Adam Keys and The Pragmatic Programmers have started a series of screencasts on Sinatra. The first two episodes cover creating a tiny web app and creating a REST service. $5 a pop.

You can also use rails as well, but that's a little overkill...

I would like to create some kind of API to run a ruby program via a unique key

Here is a VERY basic example of how easy this is to do using Sinatra which is good for such simple type of web applications / APIs.

If we assume your current program already renders the json to a static file, for example.

sample.json

[
{
"item1": {
"foo": "bar"
},
"item2": {
"baz": "qux"
}
}
]

On your linux system you should have some secure random key set. You can do that also with one liner assuming ruby is installed.

ruby -e 'require "SecureRandom"; puts SecureRandom.hex(32)'

Or in pure linux

date +%s | sha256sum | base64 | head -c 64 ; echo

Then in your server's startup scripts you'll need to make sure to export the key.

export API_KEY=ODAzN2EzMmI2YTc2ZDIzZjA5NzRmYmJiNjJjYmE4OGUyYjVjMDM0ZWJkZWU4NmMz

Then in same path as your json file, write a file called api.rb

# api.rb
require 'sinatra'

get '/api' do
if params['key'] == ENV['API_KEY']
return File.read 'sample.json'
else
status 401
end
end

By default Sinatra runs on port 4567 so you'll need to expose it on your server which seems outside the scope of your Ruby question.

Depending on how and where you host this, you'll want to configure your server to run the application at startup. For your local development you can just run this from terminal.

ruby app.rb

To see it working just visit

http://localhost:4567/api?key= # <<-- paste your key here.

Also, keep in mind, there is no security besides the key here and this will be subject to brute force attacks, but again, that's also outside the scope of this question.

UPDATE

If you need to support multiple users with their own keys, you'll need more complex logic and likely use a database to store the user information. API keys alone may not provide enough security if your api is serving sensitive information. So you'll probably want to add more layers of security. You still could build this using Sinatra, but you might want to go with Ruby on Rails to build your API instead.

adding a small API to a web application

The difference between a "classical" or API only application are pretty small. The API only app scales away some of the middleware and components that are not needed in an API.

Otherwise the steps of building the actual API components are pretty much identical.

You will want to start by choosing a different superclass for your API controllers. Your API controllers don't need all the junk on ApplicationController and you will be treating quite a few aspects such as authentication differently.

Rails 5 has ActionController::API, In previous versions you would use ActionController::Metal and include the modules needed.

# app/controllers/api_controller.rb
class ApiController < ActionController::API
# Do whatever you would do in ApplicationController
end

You then setup your routes:

namespace :api, defaults: { format: :json } do
resources :things
end

And controllers:

module API
class ThingsController < ApiController

before_action :set_thing, except: [:create, :index]

def show
render json: @thing
end

def index
render json: @things = Thing.all
end

def create
@thing = Thing.create(thing_params)

if @thing.save
head :created, location: [:api, @thing]
else
render json: @thing.errors, status: :bad_entity
end
end
# ...
end
end

There are quite a few aspects to building an API such as versioning and JSON serialization strategies and you'll find plenty of tutorials on the subject - just don't get hung up on the API only part.

Creating RestApi without using rails only using Rack

Grape is great for REST APIs. It does not build models for you.

Are you using a database, such as sqlite, mysql, postgres, etc.?

I really like the "sequel" gem for database connections.

This is good info from the sequel page:

require "rubygems"
require "sequel"

# connect to an in-memory database
DB = Sequel.sqlite

# create an items table
DB.create_table :items do
primary_key :id
String :name
Float :price
end

# create a dataset from the items table
items = DB[:items]

# populate the table
items.insert(:name => 'abc', :price => 100)
items.insert(:name => 'def', :price => 120)
items.insert(:name => 'ghi', :price => 150)

# print out the number of records
puts "Item count: #{items.count}"

# print out the average price
puts "The average price is: #{items.avg(:price)}"

For more on sequel see http://sequel.rubyforge.org/

How to create API in rails 5?

You can create a new rails project as usual:

$ rails new my_project
$ cd my_project
$ bundle

And then you can use scaffold to generate some code:

$ rails g scaffold Product name:string price:float

And migrate your database:

$ rails db:migrate # => update the database

You can now have a look at app/controllers/products_controller.rb

class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]

# GET /products
# GET /products.json
def index
@products = Product.all
end

# GET /products/1
# GET /products/1.json
def show
end

# GET /products/new
def new
@product = Product.new
end

# GET /products/1/edit
def edit
end

# POST /products
# POST /products.json
def create
@product = Product.new(product_params)

respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end

# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: @product }
else
format.html { render :edit }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end

# DELETE /products/1
# DELETE /products/1.json
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end

private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end

# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:name, :price)
end
end

As you can see there's respond_to in the create action. This is how you can respond to different request types.

Read more about it: http://edgeapi.rubyonrails.org/classes/ActionController/MimeResponds.html#method-i-respond_to

Consuming REST API from Rails Application

ActiveResource is no longer being included in Rails 4.0. Word is that it is barely maintained these days, and is difficult to customize for REST API endpoints that are not formulated according to the "Rails way".

After some research, I am heavily favoring using Faraday. It includes support for utilizing different HTTP request adapters. It can use EventMachine directly, or libraries like Typhoeus for when you decide to get concurrent. It also supports Rack-like middleware for seamlessly including, say, authentication.

For a REST ORM in Rails that is easily configurable, the relatively new (about a year old) Her looks very promising, and utilizes Faraday.

Update

I completely <3 RestClient. So simple. If you need ORM-style functionality, then you'll need a higher-level abstraction, but for simply consuming an API, you can't beat its simplicity. It just does exactly what it's supposed to do without fuss, has sensible defaults, and has the ability to set advanced options such as auth headers.

Rails 3. How to add an API to a rails app

a good starting point might be reading up on REST and responders

Then to interact with the API from another rails app, you can use ActiveResource. There's a Railscast on it.

An example:

#API side
class ProductsController < ApplicationController
respond_to :json

def index
@products = Product.all
respond_with(@products)
end
end

#Client
# models/product.rb
class Product < ActiveResource::Base
self.site = "http://your-api-app.com"
end

AzureRM Application Gateway Rest API

Now I want to create it using Rest APIs so that I can use/call them in
my code (ruby). My question is: Is there any Rest API exist to create
AzureRM Application Gateway? Because I am not able to find any

There's a REST API but at this moment it is not documented and hence you are not able to find it. As a workaround, what you could do is run PowerShell Cmdlets with -Debug switch. Then you will see the request URL as well as request body sent to create an Application Gateway. You can use that in your ruby code.

Rails devise app to create a REST api for mobile application

Add skip_before_filter :verify_authenticity_token to your API controller.
But true way for this case it's https://github.com/doorkeeper-gem/doorkeeper

Simplest way to consume Rails REST API

You can use rest-client gem to make your calls easier (though simple net/http would work just as well)

RestClient.post("https://api.teamsnap.com/v2/teams", 
'{"team": {"team_name": "West Nile Mosquitos", "sport_id": 1, "timezone": "Mountain Time (US & Canada)", "country": "United States", "zipcode": 80302}}',
content_type: :json, x_teamsnap_token: my_token)


Related Topics



Leave a reply



Submit