cathode 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +346 -125
- data/Rakefile +1 -0
- data/app/controllers/cathode/base_controller.rb +28 -45
- data/app/models/cathode/token.rb +21 -0
- data/config/routes.rb +16 -0
- data/db/migrate/20140425164100_create_cathode_tokens.rb +11 -0
- data/lib/cathode.rb +0 -13
- data/lib/cathode/_version.rb +2 -1
- data/lib/cathode/action.rb +197 -39
- data/lib/cathode/action_dsl.rb +60 -0
- data/lib/cathode/base.rb +81 -12
- data/lib/cathode/create_request.rb +21 -0
- data/lib/cathode/custom_request.rb +5 -0
- data/lib/cathode/debug.rb +25 -0
- data/lib/cathode/destroy_request.rb +13 -0
- data/lib/cathode/engine.rb +9 -0
- data/lib/cathode/exceptions.rb +20 -0
- data/lib/cathode/index_request.rb +40 -0
- data/lib/cathode/object_collection.rb +49 -0
- data/lib/cathode/query.rb +24 -0
- data/lib/cathode/railtie.rb +21 -0
- data/lib/cathode/request.rb +139 -7
- data/lib/cathode/resource.rb +50 -19
- data/lib/cathode/resource_dsl.rb +46 -0
- data/lib/cathode/show_request.rb +13 -0
- data/lib/cathode/update_request.rb +26 -0
- data/lib/cathode/version.rb +112 -23
- data/lib/tasks/cathode_tasks.rake +5 -4
- data/spec/dummy/app/api/api.rb +0 -0
- data/spec/dummy/app/models/payment.rb +3 -0
- data/spec/dummy/app/models/product.rb +1 -0
- data/spec/dummy/app/models/sale.rb +5 -0
- data/spec/dummy/app/models/salesperson.rb +3 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20140409183635_create_sales.rb +11 -0
- data/spec/dummy/db/migrate/20140423172419_create_salespeople.rb +11 -0
- data/spec/dummy/db/migrate/20140424181343_create_payments.rb +10 -0
- data/spec/dummy/db/schema.rb +31 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +1167 -0
- data/spec/dummy/log/test.log +180602 -0
- data/spec/dummy/spec/factories/payments.rb +8 -0
- data/spec/dummy/spec/factories/products.rb +1 -1
- data/spec/dummy/spec/factories/sales.rb +9 -0
- data/spec/dummy/spec/factories/salespeople.rb +7 -0
- data/spec/dummy/spec/requests/requests_spec.rb +434 -0
- data/spec/lib/cathode/action_spec.rb +136 -0
- data/spec/lib/cathode/base_spec.rb +34 -0
- data/spec/lib/cathode/create_request_spec.rb +40 -0
- data/spec/lib/cathode/custom_request_spec.rb +31 -0
- data/spec/lib/cathode/debug_spec.rb +25 -0
- data/spec/lib/cathode/destroy_request_spec.rb +28 -0
- data/spec/lib/cathode/index_request_spec.rb +62 -0
- data/spec/lib/cathode/object_collection_spec.rb +66 -0
- data/spec/lib/cathode/query_spec.rb +28 -0
- data/spec/lib/cathode/request_spec.rb +58 -0
- data/spec/lib/cathode/resource_spec.rb +482 -0
- data/spec/lib/cathode/show_request_spec.rb +23 -0
- data/spec/lib/cathode/update_request_spec.rb +41 -0
- data/spec/lib/cathode/version_spec.rb +416 -0
- data/spec/models/cathode/token_spec.rb +62 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/support/factories/payments.rb +3 -0
- data/spec/support/factories/sale.rb +3 -0
- data/spec/support/factories/salespeople.rb +3 -0
- data/spec/support/factories/token.rb +3 -0
- data/spec/support/helpers.rb +13 -2
- metadata +192 -47
- data/app/helpers/cathode/application_helper.rb +0 -4
- data/spec/dummy/app/api/dummy_api.rb +0 -4
- data/spec/integration/api_spec.rb +0 -88
- data/spec/lib/action_spec.rb +0 -140
- data/spec/lib/base_spec.rb +0 -28
- data/spec/lib/request_spec.rb +0 -5
- data/spec/lib/resources_spec.rb +0 -78
- data/spec/lib/versioning_spec.rb +0 -104
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a888fbaa2ee9784c6cf75d17b1958e631037a408
|
4
|
+
data.tar.gz: b2043c2f5fe8104f559c8aaf355bb65241d31aab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fd0da2467fc558b0d8515cf077d41751544bb60aa880552f132b01eacc00b36b14063f835475b10c60fb9fe4ec6a8ba92e074076efdef551074643fc5660670
|
7
|
+
data.tar.gz: 02fb36f863034d3829f538d115bb05b6fe6d2c7f71b8a5fd679513caf735c5f7145f12bf1845cf76167df88d4ef21dd3df22a5b7eaac103cb5536788cbf9b5f7
|
data/README.md
CHANGED
@@ -1,81 +1,123 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Warning
|
2
|
+
This gem is undergoing heavy development and is using [Semantic
|
3
|
+
Versioning](http://semver.org/), which means that **nothing in version 0.1.x is
|
4
|
+
stable**. Things are changing rapidly; the API will be stabilized in version
|
5
|
+
1.0.0. In the meantime, any feedback and testing is welcome.
|
3
6
|
|
4
7
|
# Cathode
|
5
|
-
|
6
|
-
|
8
|
+
[](http://badge.fury.io/rb/cathode)
|
9
|
+
[](https://travis-ci.org/mobyinc/Cathode)
|
10
|
+
[](http://rubydoc.info/github/mobyinc/Cathode/master/frames)
|
11
|
+
[](https://coveralls.io/r/mobyinc/Cathode)
|
12
|
+
[](https://codeclimate.com/github/mobyinc/Cathode)
|
13
|
+
[](https://gemnasium.com/mobyinc/Cathode)
|
14
|
+
|
15
|
+
Cathode is a gem for Rails projects that provides a DSL for generating dynamic
|
16
|
+
API boilerplate (created at runtime, no generated files) for resourceful
|
17
|
+
applications. It comes with default behavior for CRUD operations and support for
|
18
|
+
ActiveModel associations, allowing you to greatly reduce the amount of
|
19
|
+
boilerplate you write. Cathode also supports custom actions and token
|
20
|
+
authorization. It has first-class support for versioning, so that nothing in
|
21
|
+
your API exists outside the context of a version.
|
7
22
|
|
8
23
|
## Features
|
9
|
-
*
|
10
|
-
|
11
|
-
* Listing resources, optionally
|
24
|
+
* Versioning of resources and actions
|
25
|
+
* Default behavior for CRUD operations
|
26
|
+
* Listing resources, optionally paginated
|
12
27
|
* Finding a single resource
|
13
28
|
* Creating a new resource
|
14
29
|
* Updating a resource
|
15
30
|
* Deleting a resource
|
16
|
-
* Endpoints respond to JSON and output JSON
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
31
|
+
* Endpoints respond to JSON and output JSON
|
32
|
+
* Custom (non-resourceful) actions on versions and resources
|
33
|
+
* Nested resources
|
34
|
+
* Singular resources
|
35
|
+
* Strong parameters
|
36
|
+
* API tokens
|
37
|
+
|
38
|
+
## Roadmap
|
39
|
+
See [roadmap.md](https://github.com/mobyinc/Cathode/blob/master/roadmap.md).
|
40
|
+
|
41
|
+
## Documentation
|
42
|
+
The full documentation is [here](http://rubydoc.info/github/mobyinc/Cathode/master/frames).
|
20
43
|
|
21
44
|
## Getting Started
|
22
|
-
|
45
|
+
### Requirements
|
46
|
+
Cathode currently requires Rails 4.0 or higher. (We hope to support 3.2 in the
|
47
|
+
future.) Since ActiveSupport requires Ruby 1.9.3 or higher, so does Cathode. So
|
48
|
+
you need:
|
49
|
+
|
50
|
+
* Ruby >= 1.9.3
|
51
|
+
* Rails >= 4.0
|
52
|
+
* ActiveRecord (more ORMs will be supported in the future)
|
53
|
+
|
54
|
+
### Installation
|
55
|
+
Install the gem:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
gem install cathode
|
59
|
+
```
|
60
|
+
|
61
|
+
Mount the engine in your `config/routes.rb` file:
|
23
62
|
```ruby
|
24
|
-
|
63
|
+
mount Cathode::Engine => '/api' # use a namespace of your choice
|
25
64
|
```
|
26
65
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
66
|
+
### Defining Your API
|
67
|
+
Cathode’s DSL provides an easy way to define your API’s versions and the
|
68
|
+
resources inside of them. Place your API files in `app/api` for Cathode to load
|
69
|
+
them automatically; alternatively, place them anywhere you wish and `require`
|
70
|
+
them manually. See [Files & Naming Conventions](#files_naming) for some different ideas for
|
71
|
+
organizing your files.
|
32
72
|
|
33
|
-
In the simplest case, you can use only default actions:
|
34
73
|
```ruby
|
35
|
-
|
74
|
+
Cathode::Base.define do
|
75
|
+
# version 1.0.0 is implied if no version block is given
|
76
|
+
resources :products, actions: [:index, :show, :search]
|
77
|
+
|
78
|
+
version '1.0.1' do
|
79
|
+
resources :sales, actions: [:index, :show]
|
80
|
+
end
|
81
|
+
end
|
36
82
|
```
|
37
83
|
|
38
84
|
Contrary to Rails’s `routes.rb` file–in which the default actions are included
|
39
85
|
unless explicitly excluded–only actions that you specify are defined. Out of
|
40
|
-
the box, the actions available are: `:index, :show, :create, :update, :delete
|
86
|
+
the box, the actions available are: `:index, :show, :create, :update, :delete`.
|
41
87
|
|
42
|
-
In
|
88
|
+
In version 1, the following endpoints are created: `get api/products/`, `get
|
43
89
|
api/products/{id}`, and `get api/products/search`. By default, all products will
|
44
90
|
be returned in the `index` call, and no permissions will be enforced on the
|
45
91
|
`show` call. By default, the `search` call will take a `query` parameter and
|
46
92
|
search for it using the `Product.title` field.
|
47
93
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
defined them.
|
94
|
+
In version 1.0.1, endpoints are added for the `sales` endpoint: `get api/sales/`
|
95
|
+
and `get api/sales/{id}`. Those endpoints are not accessible in version 1.
|
96
|
+
However, because versions cascade, the actions on the `products` resource are all
|
97
|
+
accessible in version 1.0.1.
|
53
98
|
|
54
99
|
## Versioning
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
time.
|
100
|
+
Cathode has first-class support for API versioning and aims to make extending
|
101
|
+
versions and deprecating old functionality an easy process. You’re encouraged to
|
102
|
+
use [Semantic Versioning](http://semver.org/), and all Cathode version numbers
|
103
|
+
must be SemVer-compliant.
|
60
104
|
|
61
|
-
If you define
|
105
|
+
If you define resources without a version, Cathode assumes it’s version
|
62
106
|
`1.0.0` of your API. When you’re ready to introduce changes, you can
|
63
107
|
easily provision a new version:
|
64
108
|
|
65
109
|
```ruby
|
66
|
-
|
110
|
+
resources :products, actions: [:index, :show, :search]
|
67
111
|
|
68
112
|
version 1.1 do
|
69
|
-
|
113
|
+
resources :sales, actions: [:index]
|
70
114
|
# the products resource is inherited from version 1
|
71
115
|
end
|
72
116
|
|
73
117
|
version 2 do
|
74
118
|
# the products resource is inherited from version 1.1, except we explicitly
|
75
119
|
# remove the `search` action
|
76
|
-
|
77
|
-
remove_action :search
|
78
|
-
end
|
120
|
+
remove_action :products, :search
|
79
121
|
end
|
80
122
|
```
|
81
123
|
|
@@ -94,140 +136,319 @@ still be able to access the endpoint, but users of version `2` will not.
|
|
94
136
|
Usually, changes like these would require the addition of new route namespaces
|
95
137
|
and groups of controllers. With Cathode, these are all taken care of for you.
|
96
138
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
139
|
+
Note that, while these examples are using minor- and patch-level versions, you
|
140
|
+
are not required to do so. You can use only major versions (x.0.0), major and
|
141
|
+
minor versions (x.y.0), or all three (x.y.z).
|
142
|
+
|
143
|
+
## Attributes Block (Strong Parameters)
|
144
|
+
Using Cathode’s `attribute` method, you can pass a block to any action that will
|
145
|
+
be evaluated by Rails’s [Strong Parameters](https://github.com/rails/strong_parameters).
|
146
|
+
The request params are available in the block’s context, so you can use the
|
147
|
+
strong params API just as you would in a controller.
|
148
|
+
|
149
|
+
The `create` and `update` actions require an attributes block be present if
|
150
|
+
you’re using the default action behavior. If you call `attributes` at the
|
151
|
+
resource level, Cathode uses it for both the `create` and `update` actions. Call
|
152
|
+
it at the action level to limit the strong params to just that action.
|
102
153
|
|
103
154
|
```ruby
|
104
|
-
|
155
|
+
# use the same attribute whitelist for `create` and `update`
|
156
|
+
resources :products, actions: [:create, :update] do
|
157
|
+
attributes do
|
158
|
+
params.require(:product).permit(:title, :description, :cost)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# use different attribute whitelists for `create` and `update`
|
163
|
+
resources :products do
|
164
|
+
action :create do
|
165
|
+
attributes do
|
166
|
+
params.require(:product).permit(:title, :description, :cost)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
action :update do
|
171
|
+
attributes do
|
172
|
+
params.require(:product).permit(:description, :cost)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# use strong params on a custom action
|
178
|
+
resources :products do
|
179
|
+
get :custom do
|
180
|
+
attributes do
|
181
|
+
params.require(:secret)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
105
185
|
```
|
106
186
|
|
107
|
-
|
108
|
-
|
187
|
+
Requests that raise a params exception (e.g., `ActionController::ParameterMissing`)
|
188
|
+
respond with `400 Bad Request`.
|
189
|
+
|
190
|
+
## Serialization
|
191
|
+
Cathode doesn’t do any explicit serialization of resources when responding to
|
192
|
+
requests. However, it does use `render: json`, which will invoke [ActiveModel
|
193
|
+
serializers](https://github.com/rails-api/active_model_serializers) if you’ve
|
194
|
+
defined them.
|
195
|
+
|
196
|
+
## API Tokens
|
197
|
+
Cathode comes with a token manager for controlling access to your API. By
|
198
|
+
default, tokens aren’t required to access any APIs you define. To require tokens
|
199
|
+
to access an API, use the `require_tokens` method:
|
109
200
|
|
110
201
|
```ruby
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
202
|
+
Cathode::Base.define do
|
203
|
+
require_tokens
|
204
|
+
|
205
|
+
resources :products, actions: [:index]
|
115
206
|
end
|
116
207
|
```
|
117
208
|
|
118
|
-
|
119
|
-
|
209
|
+
Cathode doesn’t currently have a way to associate tokens with a particular user,
|
210
|
+
nor does it generate tokens automatically. Use Cathode’s `Token` model to generate
|
211
|
+
a new token:
|
120
212
|
|
121
|
-
|
122
|
-
|
213
|
+
```ruby
|
214
|
+
Cathode::Token.new
|
215
|
+
```
|
216
|
+
|
217
|
+
Rails’s [`authenticate_or_request_with_http_token`](http://apidock.com/rails/ActionController/HttpAuthentication/Token/ControllerMethods/authenticate_or_request_with_http_token) scheme is used to validate tokens, so API consumers
|
218
|
+
must pass a valid `Authorization` header in the following form:
|
219
|
+
|
220
|
+
```
|
221
|
+
Authorization: Token token={consumer’s token}
|
222
|
+
```
|
223
|
+
|
224
|
+
## CORS
|
225
|
+
Because Cathode is meant to be paired with a client-side Anode library,
|
226
|
+
cross-origin resource sharing (CORS) is enabled by adding
|
227
|
+
[Rack::Cors](https://github.com/cyu/rack-cors) to the application’s middleware
|
228
|
+
stack.
|
229
|
+
|
230
|
+
## Singular Resources
|
231
|
+
Singular resources can be defined as well. If the resource is independent (i.e.,
|
232
|
+
not nested inside another resource), there is no defined default behavior for
|
233
|
+
the default actions; you must provide the behavior yourself. Nested singular
|
234
|
+
resources do have default behavior, however, which is described in the “Nested
|
235
|
+
Resources” section.
|
123
236
|
|
124
237
|
```ruby
|
125
|
-
|
126
|
-
resource :
|
127
|
-
|
128
|
-
|
129
|
-
access_filter do |current_user|
|
130
|
-
resource.user == current_user
|
131
|
-
end
|
238
|
+
Cathode::Base.define do
|
239
|
+
resource :product do
|
240
|
+
override_action :create do
|
241
|
+
# custom creation logic…
|
132
242
|
end
|
133
243
|
end
|
134
244
|
end
|
135
245
|
```
|
136
246
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
247
|
+
## Nested Resources
|
248
|
+
Resources can be nested arbitrarily deep inside other resources. When resources
|
249
|
+
are nested, Cathode uses your models’ associations to determine the default action
|
250
|
+
behavior. For example, with the following setup, all of a product’s sales would
|
251
|
+
be returned by the `api/products/{product_id}/sales` endpoint.
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
# app/api/api.rb
|
255
|
+
resources :products do
|
256
|
+
resources :sales, actions: [:index]
|
257
|
+
end
|
258
|
+
|
259
|
+
# app/models/product.rb
|
260
|
+
class Product < ActiveRecord::Base
|
261
|
+
has_many :sales
|
262
|
+
end
|
263
|
+
|
264
|
+
# app/models/sale.rb
|
265
|
+
class Sale < ActiveRecord::Base
|
266
|
+
belongs_to :product
|
267
|
+
end
|
268
|
+
```
|
269
|
+
|
270
|
+
Here’s how ActiveModel associations map to resourceful endpoints on your API:
|
271
|
+
|
272
|
+
Product | Sale | Endpoints
|
273
|
+
----------- | ------------ | --------------------
|
274
|
+
`has_many` | `belongs_to` | `products/{id}/sales`, `sales/{id}/product`
|
275
|
+
`has_one` | `belongs_to` | `products/{id}/sale`, `sales/{id}/product`
|
276
|
+
`habtm` | `habtm` | `products/{id}/sales`, `sales/{id}/products`
|
277
|
+
|
278
|
+
When there is exactly one model attached to the first resource (i.e., a
|
279
|
+
`has_one` association), you can use all the default actions except `:index`, so
|
280
|
+
`:show` will return the sale associated with the product, `:create` will create
|
281
|
+
a new sale and associate it with the product, `:update` will modify the sale,
|
282
|
+
and `:destroy` will delete it.
|
283
|
+
|
284
|
+
When there are many models attached to the resource (i.e., a `has_many` or
|
285
|
+
`has_and_belongs_to_many` association), you can use the `:index` and `:create`
|
286
|
+
actions. With a `has_many` on `Product` and a `belongs_to` on `Sale`, `:index`
|
287
|
+
returns all the sales associated with a product, and `:create` adds a new sale
|
288
|
+
associated with the product.
|
142
289
|
|
143
|
-
|
144
|
-
|
290
|
+
For `belongs_to` associations, the `:show` action can be used to return the
|
291
|
+
associated parent model.
|
292
|
+
|
293
|
+
## Replacing & Overriding Default Actions
|
294
|
+
Of course, you won’t want to use Cathode’s default actions in every scenario.
|
295
|
+
There are two ways to supply your own behavior:
|
296
|
+
|
297
|
+
* *Replacing* the action allows you to override what the action does but still
|
298
|
+
go through the normal Cathode request pipeline, so you’ll still be able to
|
299
|
+
use request helpers like `body` and `status`. Use the `replace` method at
|
300
|
+
the action level or the `replace_action` method at the resource level.
|
301
|
+
* *Overriding* the action allows you to remove the action from Cathode’s
|
302
|
+
request pipeline and requires you to do all the processing and rendering
|
303
|
+
logic yourself. Overriding an action causes it to be run in the context of
|
304
|
+
the *Rails request*, as if you were in a normal controller. You won’t have
|
305
|
+
access to any Cathode helpers like `body` and `status`, but you will have
|
306
|
+
access to anything a controller would, like `request` and `render`. Use the
|
307
|
+
`override` method at the action level or the `override_action` method at the
|
308
|
+
resource level. Prefer `replace` over `override`.
|
145
309
|
|
146
310
|
```ruby
|
147
|
-
|
148
|
-
# show a random sale instead
|
311
|
+
resources :sales, actions: :all do
|
149
312
|
override_action :show do
|
150
313
|
render json: Sale.sample
|
151
314
|
end
|
152
315
|
end
|
153
316
|
```
|
154
317
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
318
|
+
```ruby
|
319
|
+
resources :sales, actions: :all do
|
320
|
+
replace_action :show do
|
321
|
+
body Sale.sample
|
322
|
+
end
|
323
|
+
end
|
324
|
+
```
|
325
|
+
|
326
|
+
## Custom Actions & Non-Resourceful Endpoints
|
327
|
+
Your API is bound to need actions that don’t map to standard CRUD operations,
|
328
|
+
and Cathode makes this easy to do. You can define your own actions at both the
|
329
|
+
version level and the resource level by using the `get`, `post`, `put`, and
|
330
|
+
`destroy` methods.
|
331
|
+
|
332
|
+
Use the `body` and `status` methods to set the response body and HTTP status.
|
333
|
+
Both of these methods take either a single argument, or a block that will be
|
334
|
+
evaluated to determine the value. Choose whichever works best in your situation.
|
335
|
+
|
336
|
+
```ruby
|
337
|
+
Cathode::Base.version 1 do
|
338
|
+
# sending a different body but the same status
|
339
|
+
get :status do
|
340
|
+
body { API.alive? ? 'Everything running smoothly' : 'Something has gone wrong' }
|
341
|
+
status :ok # not really necessary, since `:ok` is the default
|
342
|
+
end
|
162
343
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
344
|
+
# sending different body/status depending on the result of a condition
|
345
|
+
resources :users do
|
346
|
+
get :password_reset_code do
|
347
|
+
user = User.find(params[:id])
|
348
|
+
if user.present?
|
349
|
+
body user.password_reset_code
|
350
|
+
status :ok
|
351
|
+
else
|
352
|
+
body "No user exists with id #{params[:id]}"
|
353
|
+
status :bad_request
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
170
358
|
```
|
171
359
|
|
360
|
+
Note that custom actions use the `replace` functionality described above by
|
361
|
+
default. You can use the override functionality instead by using the `override`
|
362
|
+
and `override_action` methods.
|
363
|
+
|
364
|
+
<a name="files_naming"></a>
|
172
365
|
## Files & Naming Conventions
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
366
|
+
Cathode is agnostic to the way you organize your API files. Since you can either
|
367
|
+
define an API all at once using `Cathode::Base.define`, or each version
|
368
|
+
separately using `Cathode::Base.version`, you have many organization options.
|
369
|
+
Following are some examples.
|
370
|
+
|
371
|
+
### Single file for API
|
372
|
+
If your API is tiny and you only have a handful of versions, you could place
|
373
|
+
them all in a single file:
|
177
374
|
|
178
375
|
```ruby
|
179
|
-
#
|
376
|
+
# api/api.rb
|
180
377
|
|
181
|
-
|
182
|
-
|
378
|
+
Cathode::Base.define do
|
379
|
+
version 1 do
|
380
|
+
resources :products, actions: :all
|
381
|
+
end
|
183
382
|
|
184
383
|
version 2 do
|
185
|
-
|
384
|
+
resources :products do
|
385
|
+
remove_action :delete
|
386
|
+
end
|
387
|
+
|
388
|
+
resources :sales, actions: [:index]
|
186
389
|
end
|
187
390
|
end
|
188
391
|
```
|
189
392
|
|
190
|
-
|
191
|
-
|
192
|
-
|
393
|
+
### Files for each version
|
394
|
+
To break things apart a bit more, you can use a single file for each version.
|
395
|
+
|
396
|
+
```
|
397
|
+
api/
|
398
|
+
v1.rb
|
399
|
+
v2.rb
|
400
|
+
```
|
401
|
+
```ruby
|
402
|
+
# api/v1.rb
|
403
|
+
Cathode::Base.version 1 do
|
404
|
+
resources :products, actions: [:index, :show, :delete]
|
405
|
+
end
|
193
406
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
`docs/api/2.0.0`, and `docs/api/2.1.0`. It will also automatically add a
|
200
|
-
`Changelog`:
|
407
|
+
# api/v2.rb
|
408
|
+
Cathode::Base.version 2 do
|
409
|
+
resources :products do
|
410
|
+
remove_action :delete
|
411
|
+
end
|
201
412
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
Checks user permission in `sales#show`.
|
413
|
+
resources :sales, actions: [:index]
|
414
|
+
end
|
415
|
+
```
|
206
416
|
|
207
|
-
|
208
|
-
|
417
|
+
### Folders for each version, files for each resource
|
418
|
+
Another method would be to have a folder for each version of your API, and files
|
419
|
+
for each resource:
|
209
420
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
421
|
+
```
|
422
|
+
api/
|
423
|
+
v1/
|
424
|
+
products.rb
|
425
|
+
v2/
|
426
|
+
products.rb
|
427
|
+
sales.rb
|
428
|
+
```
|
429
|
+
```ruby
|
430
|
+
# api/v1/products.rb
|
431
|
+
Cathode::Base.version 1 do
|
432
|
+
resources :products, actions: [:index, :show, :delete]
|
433
|
+
end
|
218
434
|
|
219
|
-
|
220
|
-
|
435
|
+
# api/v2/products.rb
|
436
|
+
Cathode::Base.version 2 do
|
437
|
+
resources :products do
|
438
|
+
remove_action :delete
|
439
|
+
end
|
440
|
+
end
|
221
441
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
- `POST /api/products`
|
227
|
-
- `PUT /api/products/{id}`
|
228
|
-
- `DELETE /api/products/{id}`
|
442
|
+
# api/v2/sales.rb
|
443
|
+
Cathode::Base.version 2 do
|
444
|
+
resources :sales, actions: [:index]
|
445
|
+
end
|
229
446
|
```
|
230
447
|
|
448
|
+
## License
|
449
|
+
Cathode is licensed under the MIT license. See
|
450
|
+
[LICENSE](https://github.com/mobyinc/Cathode/blob/master/LICENSE).
|
451
|
+
|
231
452
|
## Related Reading & Projects
|
232
453
|
* [Versionist](https://github.com/bploetz/versionist)
|
233
454
|
* [Existing Rails API Solutions Suck](http://joshsymonds.com/blog/2013/02/22/existing-rails-api-solutions-suck/])
|