Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Full REST Implementation for Sinatra based systems, pretty handy for some Ruby Server implementations
Ruby
Tree: e9addbfe7a

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
example
lib/sinatra
spec
.gitignore
.rspec
Changelist
Gemfile
README.rdoc
Rakefile
ananke.gemspec

README.rdoc

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

Something went wrong with that request. Please try again.