restless_router 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +100 -0
- data/Rakefile +1 -0
- data/lib/restless_router/route.rb +89 -0
- data/lib/restless_router/routes.rb +103 -0
- data/lib/restless_router/version.rb +3 -0
- data/lib/restless_router.rb +5 -0
- data/restless_router.gemspec +27 -0
- data/spec/unit/route_spec.rb +35 -0
- data/spec/unit/routes_spec.rb +116 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c6e52a3b8548ac48bdc13f601d9a83b1d61ecd4d
|
4
|
+
data.tar.gz: feaafcf86072c33421c0b69778e594be7c98cba4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6499767d0da1d50c4224d3ac1908ab37750da49fa26c44c33a8085e6e2a24a32944490903e168040f02881163e9a415f6429720442f7ae1bfd12ef254cbbeee3
|
7
|
+
data.tar.gz: 595d490b7212e0d5ce5b774b6c790d2dcb2c278ab34c24faa980b4f9d24b01d4666d299c8897ed4dfd9a4eaa65167ae837fffdfa0f9ef802a725c529c57a837a
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Nate Klaiber
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# RestlessRouter
|
2
|
+
|
3
|
+
This helps fill the gap where web services only provide their routing
|
4
|
+
via external documentation. In order to prevent URL building scattered
|
5
|
+
throughout your client, you can define the routes up-front via fully
|
6
|
+
qualified URIs or [URI Templates](http://tools.ietf.org/html/rfc6570).
|
7
|
+
|
8
|
+
You can then reference a URL by looking it up by it's _link
|
9
|
+
relationship_.
|
10
|
+
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'restless_router'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install restless_router
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
The first step is to **define the possible routes that a service may
|
29
|
+
utilize**. In most cases they can be found in their online documentation
|
30
|
+
of the service.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require 'restless_router'
|
34
|
+
|
35
|
+
routes = RestlessRouter::Routes.new
|
36
|
+
|
37
|
+
# Add a fully qualified URI
|
38
|
+
routes.add_route(RestlessRouter::Route.new('directory', 'https://example.com/directory')
|
39
|
+
|
40
|
+
# Add a URI Templated
|
41
|
+
routes.add_route(RestlessRouter::Route.new('http://example.com/rels/user-detail', 'https://example.com/users/{id}', templated: true)
|
42
|
+
```
|
43
|
+
|
44
|
+
> You may also use the `<<` operator to add routes to the collection.
|
45
|
+
|
46
|
+
Once the routes have been defined, you may **lookup the routes** by their
|
47
|
+
[IANA Link
|
48
|
+
Relationship](http://www.iana.org/assignments/link-relations/link-relations.xhtml)
|
49
|
+
or _Custom Link Relationships_.
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
|
53
|
+
# Look up the Directory route
|
54
|
+
directory_route = routes.route_for('directory')
|
55
|
+
directory_url = directory_route.url_for
|
56
|
+
# => 'https://example.com/directory'
|
57
|
+
|
58
|
+
# Look up the User Detail route
|
59
|
+
user_detail_route = routes.route_for('http://example.com/rels/user-detail')
|
60
|
+
user_defail_url = user_detail_route.url_for(id: '1234')
|
61
|
+
# => 'https://example.com/users/1234'
|
62
|
+
```
|
63
|
+
|
64
|
+
This can then be utilized as you see fit with your `HTTP` adapter.
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
require 'faraday'
|
68
|
+
require 'restless_router'
|
69
|
+
|
70
|
+
# Routes are defined in the core application
|
71
|
+
class Application
|
72
|
+
def self.routes
|
73
|
+
# Include route definitions here
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# We can then reference the routes
|
78
|
+
directory_route = Application.routes.route_for('directory')
|
79
|
+
directory_url = directory_route.url_for
|
80
|
+
|
81
|
+
# And make a request
|
82
|
+
directory_request = Faraday.get(directory_url)
|
83
|
+
```
|
84
|
+
|
85
|
+
## Approach
|
86
|
+
|
87
|
+
* There is a `Routes` collection that holds the route definitions.
|
88
|
+
* There is a `Route` object that holds the details of the route definition.
|
89
|
+
* There are mechanisms to _find_ the route, and _expand_ the route if necessary.
|
90
|
+
|
91
|
+
Some APIs may provide hypermedia envelopes and you should use those where
|
92
|
+
available.
|
93
|
+
|
94
|
+
## Contributing
|
95
|
+
|
96
|
+
1. Fork it ( http://github.com/<my-github-username>/restless_router/fork )
|
97
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
99
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
100
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'addressable/template'
|
2
|
+
|
3
|
+
module RestlessRouter
|
4
|
+
class Route
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
# Create a new Route that can be used
|
8
|
+
# to issue requests against.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # With a fully qualified URI
|
12
|
+
# route = RestlessRouter::Route.new('home', 'http://example.com')
|
13
|
+
#
|
14
|
+
# route.name
|
15
|
+
# # => 'home'
|
16
|
+
#
|
17
|
+
# route.url_for
|
18
|
+
# # => 'http://example.com'
|
19
|
+
#
|
20
|
+
# # With a templated route
|
21
|
+
# route = RestlessRouter::Route.new('search', 'http://example.com/search{?q}', templated: true)
|
22
|
+
#
|
23
|
+
# route.name
|
24
|
+
# # => 'search'
|
25
|
+
#
|
26
|
+
# route.url_for(q: 'search-term')
|
27
|
+
# # => 'http://example.com/search?q=search-term'
|
28
|
+
#
|
29
|
+
def initialize(name, path, options={})
|
30
|
+
@name = name
|
31
|
+
@path = path
|
32
|
+
|
33
|
+
@options = default_options.merge(options)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Define the spaceship operator for use with Comparable
|
37
|
+
#
|
38
|
+
def <=>(other)
|
39
|
+
self.name <=> other.name
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the name of the Route. This is either
|
43
|
+
# the IANA or custom link relationship.
|
44
|
+
#
|
45
|
+
# @return [String] Name of the route
|
46
|
+
def name
|
47
|
+
@name
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the URL for the route. If it's templated,
|
51
|
+
# then we utilize the provided options hash to expand
|
52
|
+
# the route. Otherwise we return the `path`
|
53
|
+
#
|
54
|
+
# @return [String] The templated or base URI
|
55
|
+
def url_for(options={})
|
56
|
+
if templated?
|
57
|
+
template = Addressable::Template.new(base_path)
|
58
|
+
template = template.expand(options)
|
59
|
+
template.to_s
|
60
|
+
else
|
61
|
+
base_path
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
# Provide a set of default options. Currently
|
67
|
+
# this is used to set `templated` to false.
|
68
|
+
def default_options
|
69
|
+
{
|
70
|
+
:templated => false
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Query method to see if the URI path provided
|
75
|
+
# is templated
|
76
|
+
#
|
77
|
+
# @return [Boolean] True if the path is templated
|
78
|
+
def templated?
|
79
|
+
@options.fetch(:templated)
|
80
|
+
end
|
81
|
+
|
82
|
+
# The base path provided for the route
|
83
|
+
#
|
84
|
+
# @return [String] The base path
|
85
|
+
def base_path
|
86
|
+
@path
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path('../route', __FILE__)
|
2
|
+
|
3
|
+
module RestlessRouter
|
4
|
+
class Routes
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
# Error Definitions
|
8
|
+
InvalidRouteError = Class.new(StandardError)
|
9
|
+
ExistingRouteError = Class.new(StandardError)
|
10
|
+
RouteNotFoundError = Class.new(StandardError)
|
11
|
+
|
12
|
+
# Creates a new instance of a Route collection. This allows
|
13
|
+
# us to keep all definitions in a single object and then
|
14
|
+
# later retrieve them by their link relationship name.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# routes = RestlessRouter::Routers.new
|
18
|
+
# routes.add_route(RestlessRouter::Route.new('home', 'https://example.com/home')
|
19
|
+
#
|
20
|
+
# routes.route_for('home').url_for
|
21
|
+
# # => 'https://example.com/home'
|
22
|
+
#
|
23
|
+
def initialize
|
24
|
+
@routes = []
|
25
|
+
end
|
26
|
+
|
27
|
+
# Define each for use with Enumerable
|
28
|
+
#
|
29
|
+
def each(&block)
|
30
|
+
@routes.each(&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Add a new route to the Routes collection
|
34
|
+
#
|
35
|
+
# @return [Array] Routes collection
|
36
|
+
def add_route(route)
|
37
|
+
raise InvalidRouteError.new('Route must respond to #url_for') unless valid_route?(route)
|
38
|
+
@routes << route unless route_exists?(route)
|
39
|
+
end
|
40
|
+
alias :<< :add_route
|
41
|
+
|
42
|
+
# Raise an exception if the route is invalid or already exists
|
43
|
+
#
|
44
|
+
def add_route!(route)
|
45
|
+
# Raise exception if the route is existing, too
|
46
|
+
raise InvalidRouteError.new('Route must respond to #url_for') unless valid_route?(route)
|
47
|
+
raise ExistingRouteError.new(("Route already exists for %s" % [route.name])) if route_exists?(route)
|
48
|
+
|
49
|
+
@routes << route
|
50
|
+
end
|
51
|
+
|
52
|
+
# Retrieve a route by it's link relationship name
|
53
|
+
#
|
54
|
+
# @return [Route, nil] Instance of the route by name or nil
|
55
|
+
def route_for(name)
|
56
|
+
name = name.to_s
|
57
|
+
@routes.select { |entry| entry.name == name }.first
|
58
|
+
end
|
59
|
+
|
60
|
+
# Raise an exception of the route's not found
|
61
|
+
#
|
62
|
+
#
|
63
|
+
def route_for!(name)
|
64
|
+
route = route_for(name)
|
65
|
+
raise RouteNotFoundError.new(("Route not found for %s" % [name])) if route.nil?
|
66
|
+
route
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the collection of Route definitions
|
70
|
+
#
|
71
|
+
# @return [Array] Routes
|
72
|
+
def routes
|
73
|
+
@routes
|
74
|
+
end
|
75
|
+
|
76
|
+
# Query method to check if any routes have been defined.
|
77
|
+
#
|
78
|
+
# @return [Boolean] True if there are definitions in the collection
|
79
|
+
def routes?
|
80
|
+
@routes.any?
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
# Query method to see if the specified route already exists.
|
85
|
+
#
|
86
|
+
# @return [Boolean] True if we already have an existing route
|
87
|
+
def route_exists?(route)
|
88
|
+
!!self.route_for(route.name)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Query method to see if the route definition being added is valid.
|
92
|
+
#
|
93
|
+
# It must respond to:
|
94
|
+
#
|
95
|
+
# * `name`
|
96
|
+
# * `url_for`
|
97
|
+
#
|
98
|
+
# @return [Boolean] True if the route definition is valid
|
99
|
+
def valid_route?(route)
|
100
|
+
route.respond_to?(:url_for) && route.respond_to?(:name)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'restless_router/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "restless_router"
|
8
|
+
spec.version = RestlessRouter::VERSION
|
9
|
+
spec.authors = ["Nate Klaiber"]
|
10
|
+
spec.email = ["nate@theklaibers.com"]
|
11
|
+
spec.summary = %q{Enable simple route definitions for external resources.}
|
12
|
+
spec.description = %q{Many web services lack hypermedia or consistent routing. This gives a single place to house routes using URI Templates instead of building URLs throughout the client.}
|
13
|
+
spec.homepage = "https://github.com/nateklaiber/restless_router"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency("bundler", "~> 1.5")
|
22
|
+
spec.add_development_dependency("rake")
|
23
|
+
spec.add_development_dependency("rspec")
|
24
|
+
spec.add_development_dependency("yard")
|
25
|
+
|
26
|
+
spec.add_dependency("addressable")
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path('../../../lib/restless_router/route', __FILE__)
|
2
|
+
|
3
|
+
describe RestlessRouter::Route do
|
4
|
+
let(:name) { 'home' }
|
5
|
+
let(:path) { 'http://www.example.com' }
|
6
|
+
let(:options) { {} }
|
7
|
+
|
8
|
+
subject { described_class.new(name, path, options) }
|
9
|
+
|
10
|
+
# TODO: Validations on empty `name` or `path`
|
11
|
+
|
12
|
+
context "with URI" do
|
13
|
+
it "returns the #name" do
|
14
|
+
expect(subject.name).to eq('home')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns the #url_for" do
|
18
|
+
expect(subject.url_for).to eq('http://www.example.com')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with URI Template" do
|
23
|
+
let(:name) { 'search' }
|
24
|
+
let(:path) { 'http://www.example.com/search{?q}' }
|
25
|
+
let(:options) { { templated: true } }
|
26
|
+
|
27
|
+
it "returns the expanded #url_for" do
|
28
|
+
expect(subject.url_for(q: 'search-term')).to eq('http://www.example.com/search?q=search-term')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns the expanded #url_for with no expansions" do
|
32
|
+
expect(subject.url_for).to eq('http://www.example.com/search')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require File.expand_path('../../../lib/restless_router/routes', __FILE__)
|
3
|
+
|
4
|
+
describe RestlessRouter::Routes do
|
5
|
+
let(:home_route) { RestlessRouter::Route.new('home', 'https://example.com/home') }
|
6
|
+
let(:search_route) { RestlessRouter::Route.new('search', 'https://example.com/search{?q}', templated: true) }
|
7
|
+
let(:route_definitions) { [home_route, search_route] }
|
8
|
+
|
9
|
+
subject { described_class.new }
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
route_definitions.each { |route| subject.add_route(route) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "without routes" do
|
16
|
+
let(:route_definitions) { [] }
|
17
|
+
|
18
|
+
it "returns false for #any?" do
|
19
|
+
expect(subject.any?).to be_false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns 0 for the count" do
|
23
|
+
expect(subject.count).to eq(0)
|
24
|
+
end
|
25
|
+
|
26
|
+
context "retrieving a route definition" do
|
27
|
+
describe "#route_for" do
|
28
|
+
it "returns nil when searching for 'home'" do
|
29
|
+
expect(subject.route_for('home')).to be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#route_for!" do
|
34
|
+
it "raises an exception with searching for 'home'" do
|
35
|
+
lambda { subject.route_for!('home') }.should raise_error(RestlessRouter::Routes::RouteNotFoundError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with routes" do
|
42
|
+
it "returns true for #any?" do
|
43
|
+
expect(subject.any?).to be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns 2 for the count" do
|
47
|
+
expect(subject.count).to eq(2)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
context "retrieving a route definition" do
|
52
|
+
describe "#route_for" do
|
53
|
+
it "returns the route specified for 'home'" do
|
54
|
+
expect(subject.route_for('home')).to eq(home_route)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "returns the route specified for 'search'" do
|
58
|
+
expect(subject.route_for('search')).to eq(search_route)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns nil when route specified for 'not-defined'" do
|
62
|
+
expect(subject.route_for('not-defined')).to be_nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#route_for!" do
|
67
|
+
it "raises an exception with searching for 'not-defined'" do
|
68
|
+
lambda { subject.route_for!('not-defined') }.should raise_error(RestlessRouter::Routes::RouteNotFoundError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "ensure uniqueness by link relationship name" do
|
75
|
+
let(:route_definitions) { [] }
|
76
|
+
|
77
|
+
describe "#add_route" do
|
78
|
+
it "does not add a route with the same name" do
|
79
|
+
subject.add_route(home_route)
|
80
|
+
subject.add_route(home_route)
|
81
|
+
expect(subject.count).to eq(1)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#add_route!" do
|
86
|
+
it "raises an exception if route is specified with the same name" do
|
87
|
+
subject.add_route!(home_route)
|
88
|
+
|
89
|
+
lambda { subject.add_route!(home_route) }.should raise_error(RestlessRouter::Routes::ExistingRouteError)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "adding a new route definition" do
|
95
|
+
it "raises an exception if nil is added" do
|
96
|
+
lambda { subject.add_route(nil) }.should raise_error(RestlessRouter::Routes::InvalidRouteError)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "raises an error if route definition does not respond to #name" do
|
100
|
+
route_definition = OpenStruct.new(url_for: 'http://example.com')
|
101
|
+
lambda { subject.add_route(route_definition) }.should raise_error(RestlessRouter::Routes::InvalidRouteError)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "raises an error if route definition does not respond to #url_for" do
|
105
|
+
route_definition = OpenStruct.new(name: 'home')
|
106
|
+
lambda { subject.add_route(route_definition) }.should raise_error(RestlessRouter::Routes::InvalidRouteError)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "pushes the valid route onto the stack" do
|
110
|
+
route_definition = OpenStruct.new(name: 'custom-name', url_for: 'http://example.com')
|
111
|
+
subject.add_route(route_definition)
|
112
|
+
|
113
|
+
expect(subject).to include(route_definition)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: restless_router
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nate Klaiber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-05-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: addressable
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Many web services lack hypermedia or consistent routing. This gives a
|
84
|
+
single place to house routes using URI Templates instead of building URLs throughout
|
85
|
+
the client.
|
86
|
+
email:
|
87
|
+
- nate@theklaibers.com
|
88
|
+
executables: []
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- .gitignore
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- lib/restless_router.rb
|
98
|
+
- lib/restless_router/route.rb
|
99
|
+
- lib/restless_router/routes.rb
|
100
|
+
- lib/restless_router/version.rb
|
101
|
+
- restless_router.gemspec
|
102
|
+
- spec/unit/route_spec.rb
|
103
|
+
- spec/unit/routes_spec.rb
|
104
|
+
homepage: https://github.com/nateklaiber/restless_router
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.2.0
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Enable simple route definitions for external resources.
|
128
|
+
test_files:
|
129
|
+
- spec/unit/route_spec.rb
|
130
|
+
- spec/unit/routes_spec.rb
|
131
|
+
has_rdoc:
|