rest_framework 0.9.5 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +130 -0
- data/VERSION +1 -1
- data/app/views/layouts/rest_framework.html.erb +9 -183
- data/app/views/rest_framework/_breadcrumbs.html.erb +27 -0
- data/app/views/rest_framework/_head.html.erb +348 -190
- data/app/views/rest_framework/_header.html.erb +15 -0
- data/app/views/rest_framework/_heading.html.erb +10 -0
- data/app/views/rest_framework/_payloads.html.erb +36 -0
- data/app/views/rest_framework/_request_metadata.html.erb +16 -0
- data/app/views/rest_framework/_routes_and_forms.html.erb +52 -0
- data/app/views/rest_framework/head/_external.html.erb +7 -2
- data/app/views/rest_framework/header/_mode.html.erb +14 -0
- data/app/views/rest_framework/heading/_actions.html.erb +9 -0
- data/app/views/rest_framework/{_routes.html.erb → routes_and_forms/_routes.html.erb} +2 -2
- data/lib/rest_framework/controller_mixins/base.rb +11 -12
- data/lib/rest_framework/engine.rb +5 -3
- data/lib/rest_framework/filters/ransack.rb +6 -6
- data/lib/rest_framework/version.rb +0 -6
- data/lib/rest_framework.rb +11 -2
- data/vendor/assets/javascripts/rest_framework/external.min.js +1256 -0
- data/vendor/assets/stylesheets/rest_framework/{bootstrap-icons.min.css → external.min.css} +415 -0
- data/vendor/assets/stylesheets/rest_framework/highlight-a11y-dark.min.css +1 -1
- data/vendor/assets/stylesheets/rest_framework/highlight-a11y-light.min.css +1 -1
- metadata +16 -33
- data/README.md +0 -1
- data/app/views/rest_framework/head/_shared.html +0 -164
- data/docs/CNAME +0 -1
- data/docs/Gemfile +0 -5
- data/docs/Gemfile.lock +0 -264
- data/docs/_config.yml +0 -19
- data/docs/_guide/1_routers.md +0 -110
- data/docs/_guide/2_controllers.md +0 -342
- data/docs/_guide/3_serializers.md +0 -60
- data/docs/_guide/4_filtering_and_ordering.md +0 -41
- data/docs/_guide/5_pagination.md +0 -21
- data/docs/_includes/anchor_headings.html +0 -144
- data/docs/_includes/external.html +0 -9
- data/docs/_includes/head.html +0 -155
- data/docs/_includes/header.html +0 -58
- data/docs/_includes/shared.html +0 -164
- data/docs/_layouts/default.html +0 -11
- data/docs/assets/images/favicon.ico +0 -0
- data/docs/index.md +0 -133
- data/vendor/assets/javascripts/rest_framework/bootstrap.min.js +0 -6
- data/vendor/assets/javascripts/rest_framework/highlight-json.min.js +0 -7
- data/vendor/assets/javascripts/rest_framework/highlight-xml.min.js +0 -29
- data/vendor/assets/javascripts/rest_framework/highlight.min.js +0 -1202
- data/vendor/assets/javascripts/rest_framework/neatjson.min.js +0 -7
- data/vendor/assets/javascripts/rest_framework/trix.min.js +0 -6
- data/vendor/assets/stylesheets/rest_framework/bootstrap.min.css +0 -5
- data/vendor/assets/stylesheets/rest_framework/trix.min.css +0 -410
- /data/app/views/rest_framework/{_html_form.html.erb → routes_and_forms/_html_form.html.erb} +0 -0
- /data/app/views/rest_framework/{_raw_form.html.erb → routes_and_forms/_raw_form.html.erb} +0 -0
- /data/app/views/rest_framework/{_route.html.erb → routes_and_forms/routes/_route.html.erb} +0 -0
@@ -1,342 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: default
|
3
|
-
title: Controllers
|
4
|
-
position: 2
|
5
|
-
slug: controllers
|
6
|
-
---
|
7
|
-
# Controllers
|
8
|
-
|
9
|
-
This is the core of the REST Framework. Generally speaking, projects already have an existing
|
10
|
-
controller inheritance hierarchy, so we want developers to be able to maintain that project
|
11
|
-
structure while leveraging the power of the REST Framework. Also, different controllers which
|
12
|
-
inherit from the same parent often need different REST Framework functionality and behavior. For
|
13
|
-
these reasons, REST Framework provides the controller functionality as modules that you mix into
|
14
|
-
your controllers.
|
15
|
-
|
16
|
-
Here is a graph of the controller mixins (all exist within the `RESTFramework` namespace), with
|
17
|
-
supplementary mixins shown as well:
|
18
|
-
|
19
|
-
```shell
|
20
|
-
BaseControllerMixin
|
21
|
-
BaseModelControllerMixin (includes BaseControllerMixin)
|
22
|
-
ModelControllerMixin (includes BaseModelControllerMixin)
|
23
|
-
├── ListModelMixin
|
24
|
-
├── ShowModelMixin
|
25
|
-
├── CreateModelMixin
|
26
|
-
├── UpdateModelMixin
|
27
|
-
└── DestroyModelMixin
|
28
|
-
ReadOnlyModelControllerMixin (includes BaseModelControllerMixin)
|
29
|
-
├── ListModelMixin
|
30
|
-
└── ShowModelMixin
|
31
|
-
BulkModelControllerMixin (includes ModelControllerMixin)
|
32
|
-
├── BulkCreateModelMixin
|
33
|
-
├── BulkUpdateModelMixin
|
34
|
-
└── BulkDestroyModelMixin
|
35
|
-
```
|
36
|
-
|
37
|
-
All API controllers should include at least one of these top-level controller mixins, and can
|
38
|
-
include any of the supplementary mixins to add additional functionality. For example, if you want to
|
39
|
-
permit create but not update or destroy, then you could do this:
|
40
|
-
|
41
|
-
```ruby
|
42
|
-
class Api::MoviesController < ApiController
|
43
|
-
include RESTFramework::BaseModelControllerMixin
|
44
|
-
include RESTFramework::CreateModelMixin
|
45
|
-
end
|
46
|
-
```
|
47
|
-
|
48
|
-
## BaseControllerMixin
|
49
|
-
|
50
|
-
To transform a controller into the simplest possible RESTful controller, you can include
|
51
|
-
`BaseControllerMixin`, which provides a simple `root` action so it can be used at the API root.
|
52
|
-
|
53
|
-
```ruby
|
54
|
-
class ApiController < ApplicationController
|
55
|
-
include RESTFramework::BaseControllerMixin
|
56
|
-
end
|
57
|
-
```
|
58
|
-
|
59
|
-
### Response Rendering
|
60
|
-
|
61
|
-
A fundamental feature that REST Framework provides is the ability to render a browsable API. This
|
62
|
-
allows developers to discover and interact with the API's functionality, while also providing faster
|
63
|
-
and more lightweight JSON/XML formats for consumption by the systems these developers create.
|
64
|
-
|
65
|
-
The `api_response` method is how this is accomplished. The first argument is the data to be
|
66
|
-
rendered (often an array or hash), and keyword arguments can be provided to customize the response
|
67
|
-
(e.g., setting the HTTP status code). Using this method instead of the classic Rails helpers, such
|
68
|
-
as `render`, will automatically provide the browsable API as well as JSON/XML rendering.
|
69
|
-
|
70
|
-
Here is a simple example of rendering a hash with a `message` key:
|
71
|
-
|
72
|
-
```ruby
|
73
|
-
class ApiController < ApplicationController
|
74
|
-
include RESTFramework::BaseControllerMixin
|
75
|
-
self.extra_actions = {test: :get}
|
76
|
-
|
77
|
-
def test
|
78
|
-
api_response({message: "Test successful!"})
|
79
|
-
end
|
80
|
-
end
|
81
|
-
```
|
82
|
-
|
83
|
-
### Routing Extra Actions
|
84
|
-
|
85
|
-
The `extra_actions` property defines extra actions on the controller to be routed. It is a hash of
|
86
|
-
`endpoint -> method(s)` (where `method(s)` can be a method symbol or an array of method symbols).
|
87
|
-
|
88
|
-
```ruby
|
89
|
-
class ApiController < ApplicationController
|
90
|
-
include RESTFramework::BaseControllerMixin
|
91
|
-
self.extra_actions = {test: :get}
|
92
|
-
|
93
|
-
def test
|
94
|
-
api_response({message: "Test successful!"})
|
95
|
-
end
|
96
|
-
end
|
97
|
-
```
|
98
|
-
|
99
|
-
Or with multiple methods:
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
class ApiController < ApplicationController
|
103
|
-
include RESTFramework::BaseControllerMixin
|
104
|
-
self.extra_actions = {test: [:get, :post]}
|
105
|
-
|
106
|
-
def test
|
107
|
-
api_response({message: "Test successful!"})
|
108
|
-
end
|
109
|
-
end
|
110
|
-
```
|
111
|
-
|
112
|
-
If your action conflicts with a builtin method, then you can also override the path:
|
113
|
-
|
114
|
-
```ruby
|
115
|
-
class ApiController < ApplicationController
|
116
|
-
include RESTFramework::BaseControllerMixin
|
117
|
-
|
118
|
-
# This will route `test_action` to `/test`, in case there is already a `test` method that cannot
|
119
|
-
# be overridden.
|
120
|
-
self.extra_actions = {test_action: {path: :test, methods: :get}}
|
121
|
-
|
122
|
-
def test_action
|
123
|
-
api_response({message: "Test successful!"})
|
124
|
-
end
|
125
|
-
end
|
126
|
-
```
|
127
|
-
|
128
|
-
## ModelControllerMixin
|
129
|
-
|
130
|
-
`ModelControllerMixin` assists with providing the standard model CRUD (create, read, update,
|
131
|
-
destroy) for your controller. This is the most commonly used mixin since it provides default
|
132
|
-
behavior for models which matches Rails' resourceful routing.
|
133
|
-
|
134
|
-
```ruby
|
135
|
-
class Api::MoviesController < ApiController
|
136
|
-
include RESTFramework::ModelControllerMixin
|
137
|
-
end
|
138
|
-
```
|
139
|
-
|
140
|
-
By default, all columns and associations are included in the controller's `fields`, which can be
|
141
|
-
helpful when developing an administrative API. For most APIs, however, `fields` should be explicitly
|
142
|
-
defined. See [Specifying the Fields](#specifying-the-fields) for more information.
|
143
|
-
|
144
|
-
### Defining the Model
|
145
|
-
|
146
|
-
The `model` property allows you to define the model if it is not derivable from the controller name.
|
147
|
-
|
148
|
-
```ruby
|
149
|
-
class Api::CoolMoviesController < ApiController
|
150
|
-
include RESTFramework::ModelControllerMixin
|
151
|
-
|
152
|
-
self.model = Movie
|
153
|
-
end
|
154
|
-
```
|
155
|
-
|
156
|
-
### Specifying the Recordset
|
157
|
-
|
158
|
-
The `recordset` property allows you to define the set of records this API should be limited to. If
|
159
|
-
you need to change the recordset based on properties of the request, then you can override the
|
160
|
-
`get_recordset` method.
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
class Api::CoolMoviesController < ApiController
|
164
|
-
include RESTFramework::ModelControllerMixin
|
165
|
-
|
166
|
-
self.recordset = Movie.where(cool: true).order({id: :asc})
|
167
|
-
end
|
168
|
-
```
|
169
|
-
|
170
|
-
If you override `get_recordset`, you should ensure you also set the `model` property if it's not
|
171
|
-
derivable from the controller name.
|
172
|
-
|
173
|
-
```ruby
|
174
|
-
class Api::CoolMoviesController < ApiController
|
175
|
-
include RESTFramework::ModelControllerMixin
|
176
|
-
|
177
|
-
self.model = Movie
|
178
|
-
|
179
|
-
def get_recordset
|
180
|
-
return Movie.where(cool: true).order({id: :asc})
|
181
|
-
end
|
182
|
-
end
|
183
|
-
```
|
184
|
-
|
185
|
-
### Specifying Extra Member Actions
|
186
|
-
|
187
|
-
While `extra_actions` (and the synonym `extra_collection_actions`) allows you to define additional
|
188
|
-
actions on the controller, `extra_member_actions` allows you to define additional member actions on
|
189
|
-
the controller, which require a record ID to be provided as a path param.
|
190
|
-
|
191
|
-
```ruby
|
192
|
-
class Api::MoviesController < ApiController
|
193
|
-
include RESTFramework::ModelControllerMixin
|
194
|
-
|
195
|
-
self.extra_member_actions = {disable: :patch}
|
196
|
-
|
197
|
-
def disable
|
198
|
-
# REST Framework will rescue ActiveRecord::RecordNotFound.
|
199
|
-
@record = self.get_record
|
200
|
-
|
201
|
-
# REST Framework will rescue ActiveRecord::RecordInvalid or ActiveRecord::RecordNotSaved.
|
202
|
-
@record.update!(enabled: false)
|
203
|
-
|
204
|
-
return api_response(@record)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
```
|
208
|
-
|
209
|
-
### Specifying the Fields
|
210
|
-
|
211
|
-
The `fields` property defines the fields available for things like serialization and allowed
|
212
|
-
parameters in body or query params. If `fields` is not set, then it will default to all columns and
|
213
|
-
associations, which is helpful when developing an administrative API. For most APIs, however,
|
214
|
-
`fields` should be explicitly defined.
|
215
|
-
|
216
|
-
While you can also define per-request fields by overriding `get_fields`, you should also define a
|
217
|
-
set of fields on the controller which is used for things like the `OPTIONS` metadata.
|
218
|
-
|
219
|
-
```ruby
|
220
|
-
class Api::MoviesController < ApiController
|
221
|
-
include RESTFramework::ModelControllerMixin
|
222
|
-
|
223
|
-
self.fields = [:id, :name]
|
224
|
-
end
|
225
|
-
```
|
226
|
-
|
227
|
-
You can also mutate the default set of fields by removing existing columns/associations, and even
|
228
|
-
adding methods. The framework will automatically detect if the given field is a column, association,
|
229
|
-
or method, and will handle it appropriately.
|
230
|
-
|
231
|
-
```ruby
|
232
|
-
class Api::MoviesController < ApiController
|
233
|
-
include RESTFramework::ModelControllerMixin
|
234
|
-
|
235
|
-
# This will include all columns, all associations except `owners`, and the `is_featured` method.
|
236
|
-
self.fields = {
|
237
|
-
exclude: [:owners],
|
238
|
-
include: [:is_featured],
|
239
|
-
}
|
240
|
-
end
|
241
|
-
```
|
242
|
-
|
243
|
-
### Specifying the Serializer Configuration
|
244
|
-
|
245
|
-
For most cases, the default serializer configuration is sufficient, and can be modified by adjusting
|
246
|
-
the `fields` property on the controller. However, there are cases where you may want to define a
|
247
|
-
serializer configuation, such as when you want to customize nested associations, or if you want to
|
248
|
-
remove certain fields (like methods) when serializing multiple records.
|
249
|
-
|
250
|
-
The property `native_serializer_config` defines the serializer configuration if you are using the
|
251
|
-
default serializer. You can also specify serializers for singular/plural data.
|
252
|
-
|
253
|
-
```ruby
|
254
|
-
class Api::MoviesController < ApiController
|
255
|
-
include RESTFramework::ModelControllerMixin
|
256
|
-
|
257
|
-
self.native_serializer_config = {
|
258
|
-
only: [:id, :name],
|
259
|
-
methods: [:active, :some_expensive_computed_property],
|
260
|
-
include: {cast_members: { only: [:id, :name], methods: [:net_worth] }},
|
261
|
-
}
|
262
|
-
|
263
|
-
# Or you could configure a default and a plural serializer:
|
264
|
-
self.native_serializer_config = {
|
265
|
-
only: [:id, :name],
|
266
|
-
methods: [:active, :some_expensive_computed_property],
|
267
|
-
include: {cast_members: { only: [:id, :name], methods: [:net_worth] }},
|
268
|
-
}
|
269
|
-
self.native_serializer_plural_config = {
|
270
|
-
only: [:id, :name],
|
271
|
-
methods: [:active],
|
272
|
-
include: {cast_members: { only: [:id, :name], methods: [:net_worth] }},
|
273
|
-
}
|
274
|
-
|
275
|
-
# Or you could configure a default and a singular serializer:
|
276
|
-
self.native_serializer_config = {
|
277
|
-
only: [:id, :name],
|
278
|
-
methods: [:active],
|
279
|
-
include: {cast_members: { only: [:id, :name], methods: [:net_worth] }},
|
280
|
-
}
|
281
|
-
self.native_serializer_singular_config = {
|
282
|
-
only: [:id, :name],
|
283
|
-
methods: [:active, :some_expensive_computed_property],
|
284
|
-
include: {cast_members: { only: [:id, :name], methods: [:net_worth] }},
|
285
|
-
}
|
286
|
-
end
|
287
|
-
```
|
288
|
-
|
289
|
-
### Specifying Allowed Parameters
|
290
|
-
|
291
|
-
The `allowed_parameters` property defines the allowed parameters for create/update actions. The
|
292
|
-
framework uses strong parameters to execute this filtering.
|
293
|
-
|
294
|
-
```ruby
|
295
|
-
class Api::MoviesController < ApiController
|
296
|
-
include RESTFramework::ModelControllerMixin
|
297
|
-
|
298
|
-
self.allowed_parameters = [:name]
|
299
|
-
end
|
300
|
-
```
|
301
|
-
|
302
|
-
If you want different allowed parameters for create/update actions, or if you need stronger control
|
303
|
-
over what request body parameters get passed to create/update, then you can also override the
|
304
|
-
`get_create_params` or `get_update_params` methods.
|
305
|
-
|
306
|
-
### Controlling Create Behavior
|
307
|
-
|
308
|
-
The `create_from_recordset` attribute (`true` by default) is a boolean to control the behavior in
|
309
|
-
the `create` action. If it is disabled, records will not be created from the filtered recordset, but
|
310
|
-
rather will be created directly from the model interface.
|
311
|
-
|
312
|
-
For example, if this is your controller:
|
313
|
-
|
314
|
-
```ruby
|
315
|
-
class Api::CoolMoviesController < ApiController
|
316
|
-
include RESTFramework::ModelControllerMixin
|
317
|
-
|
318
|
-
# Notice that `cool` is read-only with the following two configurations:
|
319
|
-
self.fields = [:id, :name]
|
320
|
-
self.native_serializer_config = {only: [:id, :name, :cool]}
|
321
|
-
|
322
|
-
# New records created from this controller will have `cool` set to `true`.
|
323
|
-
def get_recordset
|
324
|
-
return Movie.where(cool: true)
|
325
|
-
end
|
326
|
-
end
|
327
|
-
```
|
328
|
-
|
329
|
-
Then if you hit the `create` action with the payload `{name: "Superman"}`, it will also set `cool`
|
330
|
-
to `true` on the new record, because that property is inherited from the recordset.
|
331
|
-
|
332
|
-
## ReadOnlyModelControllerMixin
|
333
|
-
|
334
|
-
`ReadOnlyModelControllerMixin` only enables list/show actions.
|
335
|
-
|
336
|
-
```ruby
|
337
|
-
class Api::ReadOnlyMoviesController < ApiController
|
338
|
-
include RESTFramework::ReadOnlyModelControllerMixin
|
339
|
-
|
340
|
-
self.model = Movie
|
341
|
-
end
|
342
|
-
```
|
@@ -1,60 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: default
|
3
|
-
title: Serializers
|
4
|
-
position: 3
|
5
|
-
slug: serializers
|
6
|
-
---
|
7
|
-
# Serializers
|
8
|
-
|
9
|
-
Serializers allow complex objects to be converted to Ruby primitives (`Array` and `Hash` objects),
|
10
|
-
which can then be converted to JSON or XML.
|
11
|
-
|
12
|
-
## NativeSerializer
|
13
|
-
|
14
|
-
This serializer uses Rails' native `ActiveModel::Serialization.serializable_hash` method to convert
|
15
|
-
records/recordsets to Ruby primitives (`Array` and `Hash`).
|
16
|
-
|
17
|
-
This is the default serializer, you can configure it using the controller class attributes
|
18
|
-
`native_serializer_config` (or `native_serializer_singular_config` /
|
19
|
-
`native_serializer_plural_config`):
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
class Api::MoviesController < ApiController
|
23
|
-
include RESTFramework::ModelControllerMixin
|
24
|
-
|
25
|
-
self.native_serializer_config = {
|
26
|
-
only: [:id, :name],
|
27
|
-
methods: [:active, :some_expensive_computed_property],
|
28
|
-
include: {cast_members: { only: [:id, :name] }},
|
29
|
-
}
|
30
|
-
end
|
31
|
-
```
|
32
|
-
|
33
|
-
If you want to re-use a serializer, then you can define it as a standalone class, and you can even
|
34
|
-
nest them. You can also define separate configurations for serializing individual records vs
|
35
|
-
recordsets using `singular_config` and `plural_config`, respectively.
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
class Api::MoviesController < ApiController
|
39
|
-
include RESTFramework::ModelControllerMixin
|
40
|
-
|
41
|
-
class CastMemberSerializer < RESTFramework::NativeSerializer
|
42
|
-
self.config = { only: [:id, :name], methods: [:net_worth] }
|
43
|
-
self.plural_config = { only: [:id, :name] }
|
44
|
-
end
|
45
|
-
|
46
|
-
class MovieSerializer < RESTFramework::NativeSerializer
|
47
|
-
self.config = {
|
48
|
-
only: [:id, :name],
|
49
|
-
include: {cast_members: CastMemberSerializer.new(many: true)},
|
50
|
-
}
|
51
|
-
self.singular_config = {
|
52
|
-
only: [:id, :name],
|
53
|
-
methods: [:active, :some_expensive_computed_property],
|
54
|
-
include: {cast_members: CastMemberSerializer.new(many: true)},
|
55
|
-
}
|
56
|
-
end
|
57
|
-
|
58
|
-
self.serializer_class = MovieSerializer
|
59
|
-
end
|
60
|
-
```
|
@@ -1,41 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: default
|
3
|
-
title: Filtering / Ordering
|
4
|
-
position: 4
|
5
|
-
slug: filtering-and-ordering
|
6
|
-
---
|
7
|
-
# Filtering and Ordering
|
8
|
-
|
9
|
-
While you can control the recordset that the API exposes, sometimes you want the user to control the
|
10
|
-
records they want to see, or the order of those records. Both filtering and ordering are
|
11
|
-
accomplished through a generic mechanism called "filters". To control the filter backends that a
|
12
|
-
controller uses, you can either adjust the `filter_backends` controller attribute or you can
|
13
|
-
override the `get_filter_backends()` method.
|
14
|
-
|
15
|
-
## ModelQueryFilter
|
16
|
-
|
17
|
-
This filter provides basic user-controllable filtering of the recordset using query params. For
|
18
|
-
example, a request to `/api/movies?cool=true` would return movies where `cool` is `true`.
|
19
|
-
|
20
|
-
If you include `ModelControllerMixin` into your controller, `ModelQueryFilter` is included in the filter
|
21
|
-
backends by default.
|
22
|
-
|
23
|
-
## ModelOrderingFilter
|
24
|
-
|
25
|
-
This filter provides basic user-controllable ordering of the recordset using query params. For
|
26
|
-
example, a request to `/api/movies?ordering=name` could order the movies by `name` rather than `id`.
|
27
|
-
`ordering=-name` would invert the ordering. You can also order with multiple parameters with a comma
|
28
|
-
separated list, like: `ordering=director,-name`.
|
29
|
-
|
30
|
-
If you include `ModelControllerMixin` into your controller, `ModelOrderingFilter` is included in the
|
31
|
-
filter backends by default. You can use `ordering_fields` to controller which fields are allowed to
|
32
|
-
be ordered by. To adjust the parameter that the user passes, adjust `ordering_query_param`; the
|
33
|
-
default is `"ordering"`.
|
34
|
-
|
35
|
-
## ModelSearchFilter
|
36
|
-
|
37
|
-
This filter provides basic user-controllable searching of the recordset using the `search` query
|
38
|
-
parameter (adjustable with the `search_query_param`). For example, a request to
|
39
|
-
`/api/movies?search=Star` could return movies where `name` contains the string `Star`. The search is
|
40
|
-
performed against the `search_fields` attribute, but if that is not set, then the search is
|
41
|
-
performed against a configurable default set of fields (`search_columns`).
|
data/docs/_guide/5_pagination.md
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: default
|
3
|
-
title: Pagination
|
4
|
-
position: 5
|
5
|
-
slug: pagination
|
6
|
-
---
|
7
|
-
# Pagination
|
8
|
-
|
9
|
-
For large result sets, you may need to provide pagination. You can configure the paginator for a
|
10
|
-
controller by setting the `paginator_class` to the paginator you want to use.
|
11
|
-
|
12
|
-
## PageNumberPaginator
|
13
|
-
|
14
|
-
This is a simple paginator which splits a recordset into pages and allows the user to select the
|
15
|
-
desired page using the `page` query parameter (e.g., `/api/movies?page=3`). To adjust this query
|
16
|
-
parameter, set the `page_query_param` controller attribute.
|
17
|
-
|
18
|
-
By default the user can adjust the page size using the `page_size` query param. To adjust this query
|
19
|
-
parameter, you can set the `page_size_query_param` controller attribute, or set it to `nil` to
|
20
|
-
disable this functionality. By default, there is no upper limit to the size of a page a user can
|
21
|
-
request. To enforce an upper limit, set the `max_page_size` controller attribute.
|
@@ -1,144 +0,0 @@
|
|
1
|
-
{% capture headingsWorkspace %}
|
2
|
-
{% comment %}
|
3
|
-
Copyright (c) 2018 Vladimir "allejo" Jimenez
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person
|
6
|
-
obtaining a copy of this software and associated documentation
|
7
|
-
files (the "Software"), to deal in the Software without
|
8
|
-
restriction, including without limitation the rights to use,
|
9
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
-
copies of the Software, and to permit persons to whom the
|
11
|
-
Software is furnished to do so, subject to the following
|
12
|
-
conditions:
|
13
|
-
|
14
|
-
The above copyright notice and this permission notice shall be
|
15
|
-
included in all copies or substantial portions of the Software.
|
16
|
-
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
19
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
23
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
24
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
25
|
-
{% endcomment %}
|
26
|
-
{% comment %}
|
27
|
-
Version 1.0.7
|
28
|
-
https://github.com/allejo/jekyll-anchor-headings
|
29
|
-
|
30
|
-
"Be the pull request you wish to see in the world." ~Ben Balter
|
31
|
-
|
32
|
-
Usage:
|
33
|
-
{% include anchor_headings.html html=content anchorBody="#" %}
|
34
|
-
|
35
|
-
Parameters:
|
36
|
-
* html (string) - the HTML of compiled markdown generated by kramdown in Jekyll
|
37
|
-
|
38
|
-
Optional Parameters:
|
39
|
-
* beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content
|
40
|
-
* anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `<a>` tag; you may NOT use `href`, `class` or `title`;
|
41
|
-
the `%heading%` and `%html_id%` placeholders are available
|
42
|
-
* anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available
|
43
|
-
* anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space
|
44
|
-
* anchorTitle (string) : '' - The `title` attribute that will be used for anchors
|
45
|
-
* h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored
|
46
|
-
* h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored
|
47
|
-
* bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content
|
48
|
-
* bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content
|
49
|
-
|
50
|
-
Output:
|
51
|
-
The original HTML with the addition of anchors inside of all of the h1-h6 headings.
|
52
|
-
{% endcomment %}
|
53
|
-
|
54
|
-
{% assign minHeader = include.h_min | default: 1 %}
|
55
|
-
{% assign maxHeader = include.h_max | default: 6 %}
|
56
|
-
{% assign beforeHeading = include.beforeHeading %}
|
57
|
-
{% assign nodes = include.html | split: '<h' %}
|
58
|
-
|
59
|
-
{% capture edited_headings %}{% endcapture %}
|
60
|
-
|
61
|
-
{% for _node in nodes %}
|
62
|
-
{% capture node %}{{ _node | strip }}{% endcapture %}
|
63
|
-
|
64
|
-
{% if node == "" %}
|
65
|
-
{% continue %}
|
66
|
-
{% endif %}
|
67
|
-
|
68
|
-
{% assign nextChar = node | replace: '"', '' | strip | slice: 0, 1 %}
|
69
|
-
{% assign headerLevel = nextChar | times: 1 %}
|
70
|
-
|
71
|
-
<!-- If the level is cast to 0, it means it's not a h1-h6 tag, so let's see if we need to fix it -->
|
72
|
-
{% if headerLevel == 0 %}
|
73
|
-
<!-- Split up the node based on closing angle brackets and get the first one. -->
|
74
|
-
{% assign firstChunk = node | split: '>' | first %}
|
75
|
-
|
76
|
-
<!-- If the first chunk does NOT contain a '<', that means we've broken another HTML tag that starts with 'h' -->
|
77
|
-
{% unless firstChunk contains '<' %}
|
78
|
-
{% capture node %}<h{{ node }}{% endcapture %}
|
79
|
-
{% endunless %}
|
80
|
-
|
81
|
-
{% capture edited_headings %}{{ edited_headings }}{{ node }}{% endcapture %}
|
82
|
-
{% continue %}
|
83
|
-
{% endif %}
|
84
|
-
|
85
|
-
{% capture _closingTag %}</h{{ headerLevel }}>{% endcapture %}
|
86
|
-
{% assign _workspace = node | split: _closingTag %}
|
87
|
-
{% assign _idWorkspace = _workspace[0] | split: 'id="' %}
|
88
|
-
{% assign _idWorkspace = _idWorkspace[1] | split: '"' %}
|
89
|
-
{% assign html_id = _idWorkspace[0] %}
|
90
|
-
|
91
|
-
{% capture _hAttrToStrip %}{{ _workspace[0] | split: '>' | first }}>{% endcapture %}
|
92
|
-
{% assign header = _workspace[0] | replace: _hAttrToStrip, '' %}
|
93
|
-
|
94
|
-
<!-- Build the anchor to inject for our heading -->
|
95
|
-
{% capture anchor %}{% endcapture %}
|
96
|
-
|
97
|
-
{% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %}
|
98
|
-
{% capture anchor %}href="#{{ html_id }}"{% endcapture %}
|
99
|
-
|
100
|
-
{% if include.anchorClass %}
|
101
|
-
{% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %}
|
102
|
-
{% endif %}
|
103
|
-
|
104
|
-
{% if include.anchorTitle %}
|
105
|
-
{% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', header }}"{% endcapture %}
|
106
|
-
{% endif %}
|
107
|
-
|
108
|
-
{% if include.anchorAttrs %}
|
109
|
-
{% capture anchor %}{{ anchor }} {{ include.anchorAttrs | replace: '%heading%', header | replace: '%html_id%', html_id }}{% endcapture %}
|
110
|
-
{% endif %}
|
111
|
-
|
112
|
-
{% capture anchor %}<a {{ anchor }}>{{ include.anchorBody | replace: '%heading%', header | default: '' }}</a>{% endcapture %}
|
113
|
-
|
114
|
-
<!-- In order to prevent adding extra space after a heading, we'll let the 'anchor' value contain it -->
|
115
|
-
{% if beforeHeading %}
|
116
|
-
{% capture anchor %}{{ anchor }} {% endcapture %}
|
117
|
-
{% else %}
|
118
|
-
{% capture anchor %} {{ anchor }}{% endcapture %}
|
119
|
-
{% endif %}
|
120
|
-
{% endif %}
|
121
|
-
|
122
|
-
{% capture new_heading %}
|
123
|
-
<h{{ _hAttrToStrip }}
|
124
|
-
{{ include.bodyPrefix }}
|
125
|
-
{% if beforeHeading %}
|
126
|
-
{{ anchor }}{{ header }}
|
127
|
-
{% else %}
|
128
|
-
{{ header }}{{ anchor }}
|
129
|
-
{% endif %}
|
130
|
-
{{ include.bodySuffix }}
|
131
|
-
</h{{ headerLevel }}>
|
132
|
-
{% endcapture %}
|
133
|
-
|
134
|
-
<!--
|
135
|
-
If we have content after the `</hX>` tag, then we'll want to append that here so we don't lost any content.
|
136
|
-
-->
|
137
|
-
{% assign chunkCount = _workspace | size %}
|
138
|
-
{% if chunkCount > 1 %}
|
139
|
-
{% capture new_heading %}{{ new_heading }}{{ _workspace | last }}{% endcapture %}
|
140
|
-
{% endif %}
|
141
|
-
|
142
|
-
{% capture edited_headings %}{{ edited_headings }}{{ new_heading }}{% endcapture %}
|
143
|
-
{% endfor %}
|
144
|
-
{% endcapture %}{% assign headingsWorkspace = '' %}{{ edited_headings | strip }}
|
@@ -1,9 +0,0 @@
|
|
1
|
-
<!-- AUTOGENERATED -->
|
2
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
|
3
|
-
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous" referrerpolicy="no-referrer" defer="defer"></script>
|
4
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.4/font/bootstrap-icons.min.css" crossorigin="anonymous">
|
5
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js" integrity="sha512-bgHRAiTjGrzHzLyKOnpFvaEpGzJet3z4tZnXGjpsCcqOnAH6VGUx9frc5bcIhKTVLEiCO6vEhNAgx5jtLUYrfA==" crossorigin="anonymous" referrerpolicy="no-referrer" defer="defer"></script>
|
6
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/json.min.js" integrity="sha512-0xYvyncS9OLE7GOpNBZFnwyh9+bq4HVgk4yVVYI678xRvE22ASicF1v6fZ1UiST+M6pn17MzFZdvVCI3jTHSyw==" crossorigin="anonymous" referrerpolicy="no-referrer" defer="defer"></script>
|
7
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/xml.min.js" integrity="sha512-5zBcw+OKRkaNyvUEPlTSfYylVzgpi7KpncY36b0gRudfxIYIH0q0kl2j26uCUB3YBRM6ytQQEZSgRg+ZlBTmdA==" crossorigin="anonymous" referrerpolicy="no-referrer" defer="defer"></script>
|
8
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/a11y-dark.min.css" integrity="sha512-Vj6gPCk8EZlqnoveEyuGyYaWZ1+jyjMPg8g4shwyyNlRQl6d3L9At02ZHQr5K6s5duZl/+YKMnM3/8pDhoUphg==" crossorigin="anonymous" class="rrf-dark-mode">
|
9
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/a11y-light.min.css" integrity="sha512-WDk6RzwygsN9KecRHAfm9HTN87LQjqdygDmkHSJxVkVI7ErCZ8ZWxP6T8RvBujY1n2/E4Ac+bn2ChXnp5rnnHA==" crossorigin="anonymous" class="rrf-light-mode">
|