Project

hart

0.01
No commit activity in last 3 years
No release in over 3 years
Hash routing
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

>= 0
 Project Readme

Hart

Hash router

Description

Hart is a generic routing library that walks a hash and detects matches according to a given pair of verb and path arguments.

Usage

A basic example would look like this:

words = {
  "c" => {
    "o" => {
      "d" => {
        define: "A husk; a pod; as, a peascod.",

        "a" => {
          define: "Concluding passage of a piece or movement."
        },

        "e" => {
          define: "System of rules relating to one subject.",

          "c" => {
            define: "Device that compresses and decompresses data."
          },

          "x" => {
            define: "A book; a manuscript."
          }
        }
      }
    }
  }
}

h = Hart.new(words)
h.call(:define, "/c/o/d")     #=> "A husk; a pod; as, a peascod."
h.call(:define, "/c/o/d/e")   #=> "System of rules relating to one subject."
h.call(:define, "/c/o/d/e/r") #=> nil

The call method accepts two arguments: a verb, which must be a symbol, and a path, which must be a string in the form "/a/b/c".

It is possible to define more than one verb per element:

countries = {
  "argentina" => {
    population: 43_417_000,
    area: 2_780_400,
  },

  "france" => {
    population: 66_200_000,
    area: 640_679,
  }
}

h = Hart.new(countries)
h.call(:population, "/argentina") #=> 43417000
h.call(:population, "/france")    #=> 66200000
h.call(:area,       "/argentina") #=>  2780400
h.call(:area,       "/france")    #=>   640679

The default value for a miss can be configured as follows:

countries[:default] = "Country not found."

After adding that key to the previous example, any miss will return the string "Country not found.".

h.call(:population, "/foobar") #=> "Country not found."

The value of each entry can be anything that responds to [](key). For instance, a proc could be used:

countries["peru"] = proc { |key|
  case key
  when :population
    30_400_000
  when :area
    1_285_216
  else
    nil
  end
}

h.call(:population, "/peru") #=> 30400000

If the special symbol :id is present as an element, it will match any path segment in that position, given that no other matches occurred.

countries[:id] = proc { |key|
  "No information about #{key}"
}

h.call(:area, "/foobar") #=> "No information about foobar"

The next example combines all the concepts explained so far, and shows how to match HTTP requests based on REQUEST_METHOD and PATH_INFO.

routes = {
  default: [404, {}, ["Not Found"]],

  GET: [200, {}, ["GET /"]],

  "foo" => {
    "bar" => {
      GET: [200, {}, ["GET /foo/bar"]],
      PUT: [200, {}, ["PUT /foo/bar"]],
    }
  },

  "users" => {
    GET: [200, {}, ["GET /users"]],

    id: proc { |id|
      {
        GET: [200, {}, ["GET /users/#{id}"]],
      }
    }
  }
}

h = Hart.new(routes)
h.call(:GET, "/foo/bar")  #=> [200, {}, ["GET /foo/bar"]]
h.call(:PUT, "/foo/bar")  #=> [200, {}, ["PUT /foo/bar"]]
h.call(:GET, "/users/42") #=> [200, {}, ["GET /users/42"]]
h.call(:GET, "/baz")      #=> [404, {}, ["Not Found"]]

API

call: Accepts two arguments: a verb, which must be a symbol, and a path, which must be a string in the form "/a/b/c".

Installation

$ gem install hart