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 CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.4.0 2009-05-13
2
+
3
+ * Partial template expansion
4
+
1
5
  == 0.3.6 2009-05-12
2
6
 
3
7
  * add ResourceTemplate#positional_params
data/README.rdoc CHANGED
@@ -1,13 +1,9 @@
1
1
  = described_routes README
2
2
 
3
- Framework-neutral descriptions of Rails routes in JSON, YAML, XML and plain text formats. Also the home (for now at least) of the ResourceTemplate class.
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 (one of which may be a list of child resources); the top level structure is an array of the resources that don't have parents.
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
@@ -2,5 +2,5 @@ require 'described_routes/resource_template'
2
2
 
3
3
  module DescribedRoutes
4
4
  # rubygem version
5
- VERSION = "0.3.6"
5
+ VERSION = "0.4.0"
6
6
  end
@@ -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.to_json
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.3.6
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 00:00:00 +01:00
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: 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]).
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: Outputs hierarchical, framework-neutral descriptions of Rails routes in JSON, YAML, XML and plain text formats for potential consumption by client applications (e.g
126
+ summary: ""
127
127
  test_files:
128
128
  - test/test_described_routes.rb
129
129
  - test/test_helper.rb