Project

ananke

0.0
No commit activity in last 3 years
No release in over 3 years
Ananke enables a new kind of ReST implementation
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 0.6.1
~> 0.9.2
~> 2.6.0
~> 0.5.2

Runtime

~> 1.2
~> 1.6.0
~> 1.2.6
 Project Readme

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¶ ↑