described_routes 0.3.6 → 0.4.0
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.
- 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
|