Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 303 lines (205 sloc) 11.703 kb
048d31c Initial draft of documentation
Brian Ploetz authored
1 # versionist
2
3 [![Build Status](https://secure.travis-ci.org/bploetz/versionist.png?branch=master)](http://travis-ci.org/bploetz/versionist)
4
5 A plugin for versioning Rails 3 based RESTful APIs. Versionist supports three versioning strategies out of the box:
6
7 - Specifying version via an HTTP header
8 - Specifying version by prepending paths with a version slug
9 - Specifying version via a request parameter
10
11 A version of your API consists of:
e5b8c63 Documentation formatting fixes
Brian Ploetz authored
12
048d31c Initial draft of documentation
Brian Ploetz authored
13 - Namespaced controllers/routes
14 - Namespaced presenters
15 - Namespaced tests
16 - Documentation
17
18 Versionist includes Rails generators for generating new versions of your API as well as new components within an existing version.
19
20
21 ## Installation
22
23 Add the following dependency to your Rails 3 application's `Gemfile` file and run `bundle install`:
24
25 gem 'versionist'
26
27
28 ## Configuration
29
30 Versionist provides the method `api_version` that you use in your Rails 3 application's `config/routes.rb` file to constrain a collection of routes to a specific version of your API.
31 The versioning strategy used by the collection of routes constrained by `api_version` is set by specifying either `:header`, `:path`, or `:parameter` (and their supporting values)
e5b8c63 Documentation formatting fixes
Brian Ploetz authored
32 in the configuration Hash passed to `api_version`. You configure the module namespace for your API version by specifying `:module` in the configuration Hash passed to `api_version`.
048d31c Initial draft of documentation
Brian Ploetz authored
33
34
35 ## Versioning Strategies
36
37 ### HTTP Header
38
39 This strategy uses an HTTP header to request a specific version of your API.
40
41 Accept: application/vnd.mycompany.com-v1,application/json
42 GET /foos
43
e5b8c63 Documentation formatting fixes
Brian Ploetz authored
44 You configure the header to be inspected and the header value specifying the version in the configuration Hash passed to `api_version`.
048d31c Initial draft of documentation
Brian Ploetz authored
45
46 Examples:
47
da6d82d Upping subheader size [ci skip]
Brian Ploetz authored
48 ##### Content negotiation via the `Accept` header:
048d31c Initial draft of documentation
Brian Ploetz authored
49
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
50 ```ruby
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
51 MyApi::Application.routes.draw do
52 api_version(:module => "V1", :header => "Accept", :value => "application/vnd.mycompany.com-v1") do
c273851 Formatting fix [ci skip]
Brian Ploetz authored
53 match '/foos.(:format)' => 'foos#index', :via => :get
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
54 match '/foos_no_format' => 'foos#index', :via => :get
55 resources :bars
56 end
57 end
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
58 ```
048d31c Initial draft of documentation
Brian Ploetz authored
59
7b1b4df Clearer formatting for the header section
Brian Ploetz authored
60 `Accept` Header Gotcha
048d31c Initial draft of documentation
Brian Ploetz authored
61
62 Please note: when your routes do not include an explicit format in the URL (i.e. `match 'foos.(:format)' => foos#index`), Rails inspects the `Accept` header to determine the requested format. Since
63 an `Accept` header can have multiple values, Rails uses the *first* one present to determine the format. If your custom version header happens to be the first value in the `Accept` header, Rails would
64 incorrectly try to interpret it as the format. If you use the `Accept` header, Versionist will move your custom version header (if found) to the end of the `Accept` header so as to not interfere with
65 Rails' format resolution logic. This is the only case where Versionist will alter the incoming request.
66
67
da6d82d Upping subheader size [ci skip]
Brian Ploetz authored
68 ##### Custom header:
048d31c Initial draft of documentation
Brian Ploetz authored
69
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
70 ```ruby
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
71 MyApi::Application.routes.draw do
0659449 Adding missing quote in README [ci skip]
Brian Ploetz authored
72 api_version(:module => "V20120317", :header => "API-VERSION", :value => "v20120317") do
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
73 match '/foos.(:format)' => 'foos#index', :via => :get
74 match '/foos_no_format' => 'foos#index', :via => :get
75 resources :bars
76 end
77 end
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
78 ```
7b1b4df Clearer formatting for the header section
Brian Ploetz authored
79
048d31c Initial draft of documentation
Brian Ploetz authored
80 ### Path
81
82 This strategy uses a URL path prefix to request a specific version of your API.
83
84 GET /v3.5.1/foos
85
86 You configure the path version prefix to be applied to the routes.
87
88 Example:
89
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
90 ```ruby
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
91 MyApi::Application.routes.draw do
92 api_version(:module => "V3__5__1", :path => "/v3.5.1") do
93 match '/foos.(:format)' => 'foos#index', :via => :get
94 match '/foos_no_format' => 'foos#index', :via => :get
95 resources :bars
96 end
97 end
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
98 ```
048d31c Initial draft of documentation
Brian Ploetz authored
99
100 ### Request Parameter
101
102 This strategy uses a request parameter to request a specific version of your API.
103
104 GET /foos?version=v1.1.3
105
106 You configure the parameter name and value to be applied to the routes.
107
108 Example:
109
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
110 ```ruby
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
111 MyApi::Application.routes.draw do
112 api_version(:module => "V1__1__3", :parameter => "version", :value => "v1.1.3") do
113 match '/foos.(:format)' => 'foos#index', :via => :get
114 match '/foos_no_format' => 'foos#index', :via => :get
115 resources :bars
116 end
117 end
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
118 ```
048d31c Initial draft of documentation
Brian Ploetz authored
119
120 ### Default Version
121
122 If a request is made to your API without specifying a specific version, by default a RoutingError (i.e. 404) will occur. You can optionally configure Versionist to
123 return a specific version by default when none is specified. To specify that a version should be used as the default, include `:default => true` in the config hash
124 passed to the `api_version` method.
125
126 Example.
127
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
128 ```ruby
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
129 MyApi::Application.routes.draw do
74117f3 Pull Request #1: Missed a reference [ci skip]
Brian Ploetz authored
130 api_version(:module => "V20120317", :header => "API-VERSION", :value => "v20120317", :default => true) do
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
131 match '/foos.(:format)' => 'foos#index', :via => :get
132 match '/foos_no_format' => 'foos#index', :via => :get
133 resources :bars
134 end
135 end
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
136 ```
048d31c Initial draft of documentation
Brian Ploetz authored
137
138 If you attempt to specify more than one default version, an error will be thrown at startup.
139
140
a66773a Issue #5: Support for Rails' :defaults hash
Brian Ploetz authored
141 ### Rails Route :defaults Hash
142
143 The `api_version` method also supports Rails' [`:defaults`](http://guides.rubyonrails.org/routing.html#defining-defaults) hash (note that this is different than
144 the `:default` key which controls the default API version described above). If a `:defaults` hash is passed to `api_version`, it will be applied to the collection
145 of routes constrainted by `api_version`.
146
147 Example.
148
149 ```ruby
150 MyApi::Application.routes.draw do
151 api_version(:module => "V20120317", :header => "API-VERSION", :value => "v20120317", :defaults => {:format => :json}, :default => true) do
152 match '/foos.(:format)' => 'foos#index', :via => :get
153 match '/foos_no_format' => 'foos#index', :via => :get
154 resources :bars
155 end
156 end
157 ```
158
159
ba65293 Moving numbering gotcha section below strategy section
Brian Ploetz authored
160 ## Version/Module Naming Convention Gotcha
161
162 Note that if your public facing version naming convention uses dots (i.e. v1.2.3), your module names cannot use dots, as you obviously cannot use dots in module names in Ruby.
163 If you wish to simply replace dots with underscores, you'll need to use *two* underscores (i.e. `__`) in the module name passed to `api_version` to work around a quirk in Rails' inflector.
164
165 For example, if your public facing version is v2.0.0 and you want to map this to the module `V2_0_0`, you would do the following in `api_routes`:
166
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
167 ```ruby
9dda214 removing indentation for ruby block [ci skip]
Brian Ploetz authored
168 api_version(:module => "V2__0__0", :header => "Accept", :value => "application/vnd.mycompany.com-v2.0.0") do
169 ...
170 end
68d5c3d Ruby block syntax highlighting [ci skip]
Brian Ploetz authored
171 ```
ba65293 Moving numbering gotcha section below strategy section
Brian Ploetz authored
172
173 If you use the generators provided Versionist (more below) simply pass the module name as is (without this double underscore hack) and Versionist will take care of this detail for you.
174
175 rails generate versionist:new_api_version v2.0.0 V2_0_0 header:Accept value:application/vnd.mycompany.com-v2.0.0
176 route api_version(:module => "V2__0__0", :header=>"Accept", :value=>"application/vnd.mycompany.com-v2.0.0") do
177 end
178 create app/controllers/v2_0_0
179 create app/controllers/v2_0_0/base_controller.rb
180 create spec/controllers/v2_0_0
181 create spec/controllers/v2_0_0/base_controller_spec.rb
182 create app/presenters/v2_0_0
183 create app/presenters/v2_0_0/base_presenter.rb
184 create spec/presenters/v2_0_0
185 create spec/presenters/v2_0_0/base_presenter_spec.rb
186 create public/docs/v2.0.0
187 create public/docs/v2.0.0/index.html
188 create public/docs/v2.0.0/style.css
189
190
191 rails generate versionist:new_controller foos V2_0_0
192 create app/controllers/v2_0_0/foos_controller.rb
193 create spec/controllers/v2_0_0/foos_controller_spec.rb
194
195
196 rails generate versionist:new_presenter foos V2_0_0
197 create app/presenters/v2_0_0/foos_presenter.rb
198 create spec/presenters/v2_0_0/foos_presenter_spec.rb
199
200
a33e9ea Issue #4
Brian Ploetz authored
201 Unfortunately this work around currently only works in Rails 3.0 and 3.1. Rails 3.2 doesn't seem to honor underscores in module names at all (see [https://github.com/rails/rails/issues/5849](https://github.com/rails/rails/issues/5849)).
202
ba65293 Moving numbering gotcha section below strategy section
Brian Ploetz authored
203 Don't shoot the messenger. :-)
204
205
048d31c Initial draft of documentation
Brian Ploetz authored
206 ## Generators
207
208 Versionist comes with generators to facilitate creating new versions of your APIs and new components with an existing version.
209 To see the available generators, simply run `rails generate`, and you will see the versionist generators under the `versionist` namespace.
210
211 The following generators are available:
212
b90d53a More formatting changes [ci skip]
Brian Ploetz authored
213 ### `versionist:new_api_version`
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
214
4a1647a Formatting tweaks [ci skip]
Brian Ploetz authored
215 creates the infrastructure for a new API version. This will create:
048d31c Initial draft of documentation
Brian Ploetz authored
216
217 - A new controller namespace, base controller and test
218 - A new presenters namespace, base presenter and test
219 - A new documentation directory and base files
220
221 Usage
222
223 rails generate versionist:new_api_version <version> <module namespace> <versioning strategy options>
224
225 Example:
226
227 rails generate versionist:new_api_version v2.0.0 V2_0_0 header:Accept value:application/vnd.mycompany.com-v2.0.0
228 route api_version(:module => "V2__0__0", :header=>"Accept", :value=>"application/vnd.mycompany.com-v2.0.0") do
e5b8c63 Documentation formatting fixes
Brian Ploetz authored
229 end
048d31c Initial draft of documentation
Brian Ploetz authored
230 create app/controllers/v2_0_0
231 create app/controllers/v2_0_0/base_controller.rb
232 create spec/controllers/v2_0_0
233 create spec/controllers/v2_0_0/base_controller_spec.rb
93177eb Issue #11: Integration tests/request specs for controllers created by ne...
Brian Ploetz authored
234 create spec/requests/v2_0_0
235 create spec/requests/v2_0_0/base_controller_spec.rb
048d31c Initial draft of documentation
Brian Ploetz authored
236 create app/presenters/v2_0_0
237 create app/presenters/v2_0_0/base_presenter.rb
238 create spec/presenters/v2_0_0
239 create spec/presenters/v2_0_0/base_presenter_spec.rb
240 create public/docs/v2.0.0
241 create public/docs/v2.0.0/index.html
242 create public/docs/v2.0.0/style.css
243
244
b90d53a More formatting changes [ci skip]
Brian Ploetz authored
245 ### `versionist:new_controller`
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
246
4a1647a Formatting tweaks [ci skip]
Brian Ploetz authored
247 creates a new controller class with the given name under the given version module.
048d31c Initial draft of documentation
Brian Ploetz authored
248
249 Usage
250
251 rails generate versionist:new_controller <name> <module namespace>
252
253 Example:
254
255 rails generate versionist:new_controller foos V2_0_0
256 create app/controllers/v2_0_0/foos_controller.rb
257 create spec/controllers/v2_0_0/foos_controller_spec.rb
93177eb Issue #11: Integration tests/request specs for controllers created by ne...
Brian Ploetz authored
258 create spec/requests/v2_0_0/foos_controller_spec.rb
048d31c Initial draft of documentation
Brian Ploetz authored
259
260
b90d53a More formatting changes [ci skip]
Brian Ploetz authored
261 ### `versionist:new_presenter`
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
262
4a1647a Formatting tweaks [ci skip]
Brian Ploetz authored
263 creates a new presenter class with the given name under the given version module.
048d31c Initial draft of documentation
Brian Ploetz authored
264
265 Usage
266
267 rails generate versionist:new_presenter <name> <module namespace>
268
269 Example:
270
271 rails generate versionist:new_presenter foos V2_0_0
272 create app/presenters/v2_0_0/foos_presenter.rb
273 create spec/presenters/v2_0_0/foos_presenter_spec.rb
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
274
275
b90d53a More formatting changes [ci skip]
Brian Ploetz authored
276 ### `versionist:copy_api_version`
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
277
4a1647a Formatting tweaks [ci skip]
Brian Ploetz authored
278 copies an existing API version to a new API version. This will do the following:
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
279
4a1647a Formatting tweaks [ci skip]
Brian Ploetz authored
280 - Copy all existing routes in config/routes.rb from the old API version to routes for the new API version in config/routes.rb (**see note below**)
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
281 - Copy all existing controllers and tests from the old API version to the new API version
282 - Copy all existing presenters and tests from the old API version to the new API version
283 - Copy all documentation from the old API version to the new API version
284
4a1647a Formatting tweaks [ci skip]
Brian Ploetz authored
285 **Note**: routes can only be copied with MRI Ruby 1.9 and above, as this feature relies on Ripper which is only available
286 in stdlib in MRI Ruby 1.9 and above. Outside of routes copying, the other copy steps will work just fine in Ruby 1.8 and other
287 non-MRI Ruby implementations.
0661751 Disabling copy route step for Ruby 1.8 and updating docs to note this on...
Brian Ploetz authored
288
c952cf6 Issue #6: Copy API Generator
Brian Ploetz authored
289 Usage
290
291 rails generate versionist:copy_api_version <old version> <old module namespace> <new version> <new module namespace>
292
293 Example:
294
295 rails generate versionist:copy_api_version v2.0.0 V2_0_0 v3.0.0 V3_0_0
296 route api_version(:module => "V3__0__0", :header=>"Accept", :value=>"application/vnd.mycompany.com-v3.0.0") do
297 end
298 Copying all files from app/controllers/v2_0_0 to app/controllers/v3_0_0
299 Copying all files from spec/controllers/v2_0_0 to spec/controllers/v3_0_0
300 Copying all files from app/presenters/v2_0_0 to app/presenters/v3_0_0
301 Copying all files from spec/presenters/v2_0_0 to spec/presenters/v3_0_0
302 Copying all files from public/docs/v2.0.0 to public/docs/v3.0.0
Something went wrong with that request. Please try again.