Skip to content

Full REST Implementation for Sinatra based systems, pretty handy for some Ruby Server implementations

Notifications You must be signed in to change notification settings

HasAndries/ananke

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ananke

Ananke is a DSL that extends the functionality of Sinatra for easy creation of Restful Services and Resources:

#myapp.rb
require 'sinatra/base'
require 'sinatra/ananke'

resource :user do
  all do
    [{:id => ]
  end
end

Install the gem and run with:

gem install ananke
ruby myapp.rb

All Users

http://localhost:4567/user

One User

http://localhost:4567/user/1

REST Resources

‘route` defines a complete Resource, and constructs Sinatra Routes based on what’s available in it’s respective Repository. Routes are:

get     '/name/?'   -> Repository::Capitalize(name).all
get     '/name/id'  -> Repository::Capitalize(name).one(id)
post    '/name'     -> Repository::Capitalize(name).new(data)
put     '/name/id'  -> Repository::Capitalize(name).edit(id, data)
delete  '/name/id'  -> Repository::Capitalize(name).delete(id)

Repositories

The Default Repository can be changed:

ananke.default_repository = 'MyRepository'

HyperMedia

Linked

route :user do
  id :id
  linked :computer
 end

 module Repository
  module User
    def self.one(id)
      [Return User for User Id]
    end
    def self.computer_id_list(id)
      [Return an array of single value id's]
    end
  end
 end

Repository Method:

[ResourceRepository].[linked name]_id_list

Routes Available/Registered:

/user/:id

Output:

{
  user: {
          user_id: "1"
          name: "One"
        }
  links:  [
            {
              rel: "self"
              uri: "/user/1"
            },
            {
              rel: "computer"
              uri: "/computer/2"
            }
          ]
}

The Respository for User needs to have a method that returns an array of id’s for use in the HyperMedia links. The link to Self uses this method. The output will be something like this:

Link To and Route For

route :user do
  id :id
  link_to :car
end
route :car do
  id :id
  route_for :user
end

module Repository
  module User
    def self.one(id)
      [Return User for User Id]
    end
  end
  module Car
    def self.user(id)
      [Return List of Cars for User Id]
    end
  end
end

Routes Available/Registered:

/user/:id
/car/user/:id

Output:

{
  user: {
          user_id: "1"
          name: "One"
        }
  links:  [
            {
              rel: "self"
              uri: "/user/1"
            },
            {
              rel: "computer"
              uri: "/computer/user/1"
            }
          ]
}

This way of linking solves a lot of problems, and can also be used for searching support. route_for supports an optional 2nd parameter to specify the type of request it must register for:

route :car do
  id :id
  route_for :user, :post
end

The Called Repository can also have multiple input paramaters:

def some_method(id, name, email)
  ...
end

will need an incoming Request with these paramaters:

id, name, email

Media Type

The REST media type can be built up:

required :name
optional :country

Exposing the Media Type is on the cards.

Validation

Validation can be added on any field by providing arguments after a field declaration:

required :name, :length => 4

This will cause the paramater to be validated against the method defined in Ananke::Rules. Custom Rules can be added to the module and provided as arguments. Current Default included rules are:

length(min)

Validation Methods are Invoked in the Ananke::Rules context, and has access to a class variable named value, which holds the value for the currently valuated Parameter.

To Add a Custom Rule:

rule :name, do
  value == [expected] ? nil : 'Not Expected Value'
end

required :name, :name

or

module Ananke
  module Rules
    def validate_name
      value == [expected] ? nil : 'Not Expected Value'
    end
  end
end

required :name, :name

or Advanced

module Ananke
  module Rules
    def validate_name(extra)
      value == [expected using extra] ? nil : 'Not Expected Value'
    end
  end
end

required :name, :name => extra

Future

A short list of future development:

- Refactor!
- Return Value Strategy
- Resource Exposes Media Type
- Lots more `bullet-proofing`
- ETag Support

More

About

Full REST Implementation for Sinatra based systems, pretty handy for some Ruby Server implementations

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages