described_routes 0.3.6 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/README.rdoc +76 -6
- data/lib/described_routes.rb +1 -1
- data/lib/described_routes/rails_controller.rb +3 -1
- data/lib/described_routes/resource_template.rb +28 -1
- data/test/test_resource_template.rb +9 -0
- data/test_rails_app/test/integration/described_routes_run_time_test.rb +5 -0
- metadata +4 -4
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
= described_routes README
|
2
2
|
|
3
|
-
Framework-neutral
|
3
|
+
Framework-neutral metadata, describing Rails routes in JSON, YAML, XML and plain text formats. Also the home (for now at least) of the ResourceTemplate class.
|
4
4
|
|
5
5
|
Note to reader: you are invited to comment on the roadmap at http://positiveincline.com/?p=213
|
6
6
|
|
7
|
-
== DESCRIPTION:
|
8
|
-
|
9
|
-
Outputs hierarchical, framework-neutral descriptions of Rails routes in JSON, YAML, XML and plain text formats for potential consumption by client applications (e.g. those based on path-to[http://github.com/asplake/path-to/tree]).
|
10
|
-
|
11
7
|
== SYNOPSIS:
|
12
8
|
|
13
9
|
=== Build time
|
@@ -105,11 +101,77 @@ Example:
|
|
105
101
|
edit edit_user_profile GET http://localhost:3000/users/{user_id}/profile/edit{-prefix|.|format}
|
106
102
|
new new_user_profile GET http://localhost:3000/users/{user_id}/profile/new{-prefix|.|format}
|
107
103
|
|
104
|
+
==== Partial template expansion
|
105
|
+
|
106
|
+
Any query parameters passed to the controller will be used to pre-populate the templates. In this example, the
|
107
|
+
<code>article_id</code> and <code>format</code> parameters have been replaced, leaving <code>article_id</code>:
|
108
|
+
|
109
|
+
$ curl "http://localhost:3000/described_routes/user.text?format=json&user_id=dojo"
|
110
|
+
user user GET, PUT, DELETE http://localhost:3000/users/dojo.json
|
111
|
+
edit edit_user GET http://localhost:3000/users/dojo/edit.json
|
112
|
+
articles user_articles GET, POST http://localhost:3000/users/dojo/articles.json
|
113
|
+
new_user_article new_user_article GET http://localhost:3000/users/dojo/articles/new.json
|
114
|
+
recent recent_user_articles GET http://localhost:3000/users/dojo/articles/recent.json
|
115
|
+
{article_id} user_article GET, PUT, DELETE http://localhost:3000/users/dojo/articles/{article_id}.json
|
116
|
+
edit edit_user_article GET http://localhost:3000/users/dojo/articles/{article_id}/edit.json
|
117
|
+
profile user_profile GET, PUT, DELETE, POST http://localhost:3000/users/dojo/profile.json
|
118
|
+
edit edit_user_profile GET http://localhost:3000/users/dojo/profile/edit.json
|
119
|
+
new new_user_profile GET http://localhost:3000/users/dojo/profile/new.json
|
120
|
+
|
121
|
+
More typically, JSON, YAML or XML format would be requested. Their addresses can be referenced in <code><link></code> elements in the
|
122
|
+
<code><head></code> section of an HTML page or (better) in HTTP headers, so any resource - regardless of format - can easily link to its
|
123
|
+
own instance-specific metadata.
|
124
|
+
|
125
|
+
JSON example (after pretty printing):
|
126
|
+
|
127
|
+
$ curl "http://localhost:3000/described_routes/user_articles.yaml?user_id=dojo&format=json"
|
128
|
+
{
|
129
|
+
"name":"user_articles",
|
130
|
+
"rel":"articles",
|
131
|
+
"path_template":"\/users\/dojo\/articles.json",
|
132
|
+
"uri_template":"http:\/\/localhost:3000\/users\/dojo\/articles.json",
|
133
|
+
"options":["GET", "POST"],
|
134
|
+
"resource_templates":[
|
135
|
+
{
|
136
|
+
"name":"new_user_article",
|
137
|
+
"options":["GET"],
|
138
|
+
"path_template":"\/users\/dojo\/articles\/new.json",
|
139
|
+
"uri_template":"http:\/\/localhost:3000\/users\/dojo\/articles\/new.json",
|
140
|
+
"rel":"new_user_article"
|
141
|
+
},
|
142
|
+
{
|
143
|
+
"name":"recent_user_articles",
|
144
|
+
"options":["GET"],
|
145
|
+
"path_template":"\/users\/dojo\/articles\/recent.json",
|
146
|
+
"uri_template":"http:\/\/localhost:3000\/users\/dojo\/articles\/recent.json",
|
147
|
+
"rel":"recent"
|
148
|
+
},
|
149
|
+
{
|
150
|
+
"name":"user_article",
|
151
|
+
"resource_templates":[
|
152
|
+
{
|
153
|
+
"name":"edit_user_article",
|
154
|
+
"options":["GET"],
|
155
|
+
"path_template":"\/users\/dojo\/articles\/{article_id}\/edit.json",
|
156
|
+
"uri_template":"http:\/\/localhost:3000\/users\/dojo\/articles\/{article_id}\/edit.json",
|
157
|
+
"rel":"edit",
|
158
|
+
"params":["article_id"]
|
159
|
+
}
|
160
|
+
],
|
161
|
+
"options":["GET", "PUT", "DELETE"],
|
162
|
+
"path_template":"\/users\/dojo\/articles\/{article_id}.json",
|
163
|
+
"uri_template":"http:\/\/localhost:3000\/users\/dojo\/articles\/{article_id}.json",
|
164
|
+
"params":["article_id"]
|
165
|
+
}
|
166
|
+
]
|
167
|
+
}
|
168
|
+
|
108
169
|
== DATA STRUCTURES and FORMATS
|
109
170
|
|
110
171
|
=== Natural structure
|
111
172
|
|
112
|
-
The YAML and JSON representations appear as simple array and hash structures. Each resource is represented by a hash of attributes
|
173
|
+
The YAML and JSON representations appear as simple array and hash structures. Each resource is represented by a hash of attributes
|
174
|
+
(one of which may be a list of child resources); the top level structure is an array of parentless resources.
|
113
175
|
|
114
176
|
Attributes:
|
115
177
|
|
@@ -136,6 +198,10 @@ This follows the natural structure but with the following modifications:
|
|
136
198
|
|
137
199
|
Calls to parse_xml will at present result in NoMethodError exceptions being raised.
|
138
200
|
|
201
|
+
=== Samples
|
202
|
+
|
203
|
+
See <code>test_rails_app/test/fixtures</code> for sample outputs in each of the supported formats.
|
204
|
+
|
139
205
|
== CUSTOMISATION
|
140
206
|
|
141
207
|
It is possible to customise the data collected from Rails, for example to hide sensitive routes:
|
@@ -148,6 +214,10 @@ This hook operates on the raw "parsed" (Array/Hash) data before conversion to Re
|
|
148
214
|
|
149
215
|
Rails, for the Rake tasks and Rails controller. The ResourceTemplate class and its formats are however Rails-independent.
|
150
216
|
|
217
|
+
The addressable[http://github.com/sporkmonger/addressable/tree/master] gem, used by the Rails controller for partial template
|
218
|
+
expansion. You will need to grab the latest from github as (at the time of writing) the latest gem package hasn't been released
|
219
|
+
to Rubyforge.
|
220
|
+
|
151
221
|
== INSTALL:
|
152
222
|
|
153
223
|
sudo gem install described_routes
|
data/lib/described_routes.rb
CHANGED
@@ -5,7 +5,7 @@ module DescribedRoutes
|
|
5
5
|
class RailsController < ActionController::Base
|
6
6
|
def index
|
7
7
|
base_url = root_url rescue nil
|
8
|
-
resource_templates = RailsRoutes.get_resource_templates(base_url)
|
8
|
+
resource_templates = ResourceTemplate.partial_expand(RailsRoutes.get_resource_templates(base_url), request.query_parameters)
|
9
9
|
|
10
10
|
respond_to do |format|
|
11
11
|
format.html # index.html.erb
|
@@ -28,6 +28,8 @@ module DescribedRoutes
|
|
28
28
|
base_url = root_url rescue nil
|
29
29
|
resources = RailsRoutes.get_resource_templates(base_url)
|
30
30
|
resource_template = ResourceTemplate.all_by_name(resources)[params[:id]]
|
31
|
+
# TODO 404 if nil
|
32
|
+
resource_template = resource_template.partial_expand(request.query_parameters)
|
31
33
|
|
32
34
|
respond_to do |format|
|
33
35
|
format.html # show.html.erb
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "json"
|
2
|
+
require "addressable/template"
|
2
3
|
|
3
4
|
module DescribedRoutes
|
4
5
|
class ResourceTemplate
|
@@ -76,7 +77,7 @@ module DescribedRoutes
|
|
76
77
|
|
77
78
|
# Convert to YAML
|
78
79
|
def to_yaml
|
79
|
-
to_hash.
|
80
|
+
to_hash.to_yaml
|
80
81
|
end
|
81
82
|
|
82
83
|
#
|
@@ -216,6 +217,32 @@ module DescribedRoutes
|
|
216
217
|
all_params
|
217
218
|
end
|
218
219
|
end
|
220
|
+
|
221
|
+
# Partially expand the path_template or uri_template of the given resource templates with the given params,
|
222
|
+
# returning new resource templates
|
223
|
+
def self.partial_expand(resource_templates, actual_params)
|
224
|
+
resource_templates.map do |resource_template|
|
225
|
+
resource_template.partial_expand(actual_params)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
# Return a new resource template with the path_template or uri_template partially expanded with the given params
|
230
|
+
def partial_expand(actual_params)
|
231
|
+
self.class.new(
|
232
|
+
name,
|
233
|
+
rel,
|
234
|
+
partial_expand_uri_template(uri_template, actual_params),
|
235
|
+
partial_expand_uri_template(path_template, actual_params),
|
236
|
+
params - actual_params.keys,
|
237
|
+
optional_params - actual_params.keys,
|
238
|
+
options,
|
239
|
+
self.class.partial_expand(resource_templates, actual_params))
|
240
|
+
end
|
241
|
+
|
242
|
+
# Partially expand a URI template
|
243
|
+
def partial_expand_uri_template(template, params)#:nodoc:
|
244
|
+
template && Addressable::Template.new(template).partial_expand(params).pattern
|
245
|
+
end
|
219
246
|
end
|
220
247
|
end
|
221
248
|
|
@@ -49,4 +49,13 @@ class TestResourceTemplate < Test::Unit::TestCase
|
|
49
49
|
assert_equal(["user_id", "article_id", "format"], user_article.positional_params(nil))
|
50
50
|
assert_equal(["article_id", "format"], user_article.positional_params(user_articles))
|
51
51
|
end
|
52
|
+
|
53
|
+
def test_partial_expand
|
54
|
+
expanded = DescribedRoutes::ResourceTemplate.all_by_name([user_articles.partial_expand("user_id" => "dojo", "format" => "json")])
|
55
|
+
expanded_edit_user_article = expanded["edit_user_article"]
|
56
|
+
|
57
|
+
assert_equal(["article_id"], expanded_edit_user_article.params)
|
58
|
+
assert(expanded_edit_user_article.optional_params.empty?)
|
59
|
+
assert_equal("/users/dojo/articles/{article_id}/edit.json", expanded_edit_user_article.path_template)
|
60
|
+
end
|
52
61
|
end
|
@@ -34,4 +34,9 @@ class DescribedRoutesRunTimeTest < ActionController::IntegrationTest
|
|
34
34
|
assert_response :success
|
35
35
|
assert_equal(read_fixture("yaml_short"), body)
|
36
36
|
end
|
37
|
+
|
38
|
+
def test_partial_expand
|
39
|
+
get "/described_routes/new_user_profile.text?user_id=dojo&format=json"
|
40
|
+
assert_equal("new_user_profile new_user_profile GET http://www.example.com/users/dojo/profile/new.json", body.chomp)
|
41
|
+
end
|
37
42
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: described_routes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Burrows
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-13 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 1.8.0
|
34
34
|
version:
|
35
|
-
description:
|
35
|
+
description: ""
|
36
36
|
email:
|
37
37
|
- mjb@asplake.co.uk
|
38
38
|
executables: []
|
@@ -123,7 +123,7 @@ rubyforge_project: describedroutes
|
|
123
123
|
rubygems_version: 1.3.3
|
124
124
|
signing_key:
|
125
125
|
specification_version: 3
|
126
|
-
summary:
|
126
|
+
summary: ""
|
127
127
|
test_files:
|
128
128
|
- test/test_described_routes.rb
|
129
129
|
- test/test_helper.rb
|