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 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