rest_framework 0.9.9 → 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -21
- data/VERSION +1 -1
- data/lib/rest_framework/filters/model_ordering_filter.rb +3 -1
- data/lib/rest_framework/filters/model_query_filter.rb +21 -7
- data/lib/rest_framework/mixins/model_controller_mixin.rb +10 -19
- data/lib/rest_framework/version.rb +1 -1
- data/lib/rest_framework.rb +15 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2db255f618d449ef621f1337d182993c21b5d8d87e5e8c960c8b42093248c91d
|
4
|
+
data.tar.gz: 4612f2e11733ae69e418cd2877b8150e2a1dbd4fb0cd34ed29727dcec007f305
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04457aa989c261900e8e1e55829dbb3cc3aed3afda800433944497996a330a92fdff403351be8e4b83b7b44fea658ecd57a3ab20b4b9e41587398a52b8203680
|
7
|
+
data.tar.gz: e67d99fd29629b7bf31e37f3f27edc8e7d5d222172e6b91e5d2340eec0d891b340029097dc798411410d9c5ecbdffe316521c0dd47e8810c6fe897b0ff59624b
|
data/README.md
CHANGED
@@ -7,12 +7,10 @@
|
|
7
7
|
|
8
8
|
A framework for DRY RESTful APIs in Ruby on Rails.
|
9
9
|
|
10
|
-
**The Problem**: Building controllers for APIs usually involves writing a lot of redundant CRUD
|
11
|
-
|
12
|
-
filtering, and pagination can be tedious.
|
10
|
+
**The Problem**: Building controllers for APIs usually involves writing a lot of redundant CRUD logic, and routing them can be obnoxious.
|
11
|
+
Building and maintaining features like ordering, filtering, and pagination can be tedious.
|
13
12
|
|
14
|
-
**The Solution**: This framework implements browsable API responses, CRUD actions for your models,
|
15
|
-
and features like ordering/filtering/pagination, so you can focus on building awesome APIs.
|
13
|
+
**The Solution**: This framework implements browsable API responses, CRUD actions for your models, and features like ordering/filtering/pagination, so you can focus on building awesome APIs.
|
16
14
|
|
17
15
|
Website/Guide: [rails-rest-framework.com](https://rails-rest-framework.com)
|
18
16
|
|
@@ -40,8 +38,7 @@ bundle install
|
|
40
38
|
|
41
39
|
This section provides some simple examples to quickly get you started using the framework.
|
42
40
|
|
43
|
-
For the purpose of this example, you'll want to add an `api_controller.rb` to your controllers, as
|
44
|
-
well as a directory for the resources:
|
41
|
+
For the purpose of this example, you'll want to add an `api_controller.rb` to your controllers, as well as a directory for the resources:
|
45
42
|
|
46
43
|
```text
|
47
44
|
controllers/
|
@@ -54,8 +51,7 @@ controllers/
|
|
54
51
|
|
55
52
|
### Controller Mixins
|
56
53
|
|
57
|
-
The root `ApiController` can include any common behavior you want to share across all your API
|
58
|
-
controllers:
|
54
|
+
The root `ApiController` can include any common behavior you want to share across all your API controllers:
|
59
55
|
|
60
56
|
```ruby
|
61
57
|
class ApiController < ApplicationController
|
@@ -71,9 +67,8 @@ class ApiController < ApplicationController
|
|
71
67
|
end
|
72
68
|
```
|
73
69
|
|
74
|
-
A root controller can provide actions that exist on the root of your API.
|
75
|
-
dedicated root controller, rather than using the `ApiController` for this purpose, so that actions
|
76
|
-
don't propagate to child controllers:
|
70
|
+
A root controller can provide actions that exist on the root of your API.
|
71
|
+
It's best to define a dedicated root controller, rather than using the `ApiController` for this purpose, so that actions don't propagate to child controllers:
|
77
72
|
|
78
73
|
```ruby
|
79
74
|
class Api::RootController < ApiController
|
@@ -119,7 +114,8 @@ class Api::MoviesController < ApiController
|
|
119
114
|
end
|
120
115
|
```
|
121
116
|
|
122
|
-
|
117
|
+
When `fields` is nil, then it will default to all columns.
|
118
|
+
The `fields` attribute can also be a hash to include or exclude fields rather than defining them manually:
|
123
119
|
|
124
120
|
```ruby
|
125
121
|
class Api::UsersController < ApiController
|
@@ -131,10 +127,9 @@ end
|
|
131
127
|
|
132
128
|
### Routing
|
133
129
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
the root, use `rest_root`.
|
130
|
+
Use `rest_route` for non-resourceful controllers, or `rest_resource` / `rest_resources` resourceful routers.
|
131
|
+
These routers add some features to the Rails builtin `resource`/`resources` routers, such as automatically routing extra actions defined on the controller.
|
132
|
+
To route the root, use `rest_root`.
|
138
133
|
|
139
134
|
```ruby
|
140
135
|
Rails.application.routes.draw do
|
@@ -151,8 +146,7 @@ end
|
|
151
146
|
|
152
147
|
## Development/Testing
|
153
148
|
|
154
|
-
After you clone the repository, cd'ing into the directory should create a new gemset if you are
|
155
|
-
|
149
|
+
After you clone the repository, cd'ing into the directory should create a new gemset if you are using RVM.
|
150
|
+
Then run `bin/setup` to install the appropriate gems and set things up.
|
156
151
|
|
157
|
-
The top-level `bin/rails` proxies all Rails commands to the test project, so you can operate it via
|
158
|
-
the usual commands (e.g., `rails test`, `rails server` and `rails console`).
|
152
|
+
The top-level `bin/rails` proxies all Rails commands to the test project, so you can operate it via the usual commands (e.g., `rails test`, `rails server` and `rails console`).
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.10
|
@@ -15,6 +15,7 @@ class RESTFramework::Filters::ModelOrderingFilter < RESTFramework::Filters::Base
|
|
15
15
|
|
16
16
|
if order_string.present?
|
17
17
|
ordering = {}.with_indifferent_access
|
18
|
+
|
18
19
|
order_string.split(",").each do |field|
|
19
20
|
if field[0] == "-"
|
20
21
|
column = field[1..-1]
|
@@ -24,10 +25,11 @@ class RESTFramework::Filters::ModelOrderingFilter < RESTFramework::Filters::Base
|
|
24
25
|
direction = :asc
|
25
26
|
end
|
26
27
|
|
27
|
-
next if !column.in?(fields) && column.split(".").first.in?(fields)
|
28
|
+
next if !column.in?(fields) && !column.split(".").first.in?(fields)
|
28
29
|
|
29
30
|
ordering[column] = direction
|
30
31
|
end
|
32
|
+
|
31
33
|
return ordering
|
32
34
|
end
|
33
35
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# A simple filtering backend that supports filtering a recordset based on query parameters.
|
2
2
|
class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFilter
|
3
|
+
NIL_VALUES = ["nil", "null"].freeze
|
4
|
+
|
3
5
|
# Get a list of filterset fields for the current action.
|
4
6
|
def _get_fields
|
5
7
|
# Always return a list of strings; `@controller.get_fields` already does this.
|
@@ -9,8 +11,9 @@ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFil
|
|
9
11
|
# Filter params for keys allowed by the current action's filterset_fields/fields config.
|
10
12
|
def _get_filter_params
|
11
13
|
fields = self._get_fields
|
14
|
+
includes = []
|
12
15
|
|
13
|
-
|
16
|
+
filter_params = @controller.request.query_parameters.select { |p, _|
|
14
17
|
# Remove any trailing `__in` from the field name.
|
15
18
|
field = p.chomp("__in")
|
16
19
|
|
@@ -20,7 +23,12 @@ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFil
|
|
20
23
|
next false unless field.in?(fields)
|
21
24
|
|
22
25
|
sub_fields = @controller.class.get_field_config(field)[:sub_fields] || []
|
23
|
-
|
26
|
+
if sub_field.in?(sub_fields)
|
27
|
+
includes << field.to_sym
|
28
|
+
next true
|
29
|
+
end
|
30
|
+
|
31
|
+
next false
|
24
32
|
end
|
25
33
|
|
26
34
|
next field.in?(fields)
|
@@ -28,21 +36,27 @@ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFil
|
|
28
36
|
# Convert fields ending in `__in` to array values.
|
29
37
|
if p.end_with?("__in")
|
30
38
|
p = p.chomp("__in")
|
31
|
-
v = v.split(",")
|
39
|
+
v = v.split(",").map { |v| v.in?(NIL_VALUES) ? nil : v }
|
32
40
|
end
|
33
41
|
|
34
42
|
# Convert "nil" and "null" to nil.
|
35
|
-
|
36
|
-
v = nil
|
37
|
-
end
|
43
|
+
v = nil if v.in?(NIL_VALUES)
|
38
44
|
|
39
45
|
[p, v]
|
40
46
|
}.to_h.symbolize_keys
|
47
|
+
|
48
|
+
return filter_params, includes
|
41
49
|
end
|
42
50
|
|
43
51
|
# Filter data according to the request query parameters.
|
44
52
|
def get_filtered_data(data)
|
45
|
-
|
53
|
+
filter_params, includes = self._get_filter_params
|
54
|
+
|
55
|
+
if filter_params.any?
|
56
|
+
if includes.any?
|
57
|
+
data = data.includes(*includes)
|
58
|
+
end
|
59
|
+
|
46
60
|
return data.where(**filter_params)
|
47
61
|
end
|
48
62
|
|
@@ -33,17 +33,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
|
|
33
33
|
# Options for handling request body parameters.
|
34
34
|
allowed_parameters: nil,
|
35
35
|
filter_pk_from_request_body: true,
|
36
|
-
exclude_body_fields:
|
37
|
-
created_at
|
38
|
-
created_by
|
39
|
-
created_by_id
|
40
|
-
updated_at
|
41
|
-
updated_by
|
42
|
-
updated_by_id
|
43
|
-
_method
|
44
|
-
utf8
|
45
|
-
authenticity_token
|
46
|
-
].freeze,
|
36
|
+
exclude_body_fields: RESTFramework.config.exclude_body_fields,
|
47
37
|
|
48
38
|
# Attributes for the default native serializer.
|
49
39
|
native_serializer_config: nil,
|
@@ -515,7 +505,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
|
|
515
505
|
ActionController::Parameters.new(data).permit(*allowed_params)
|
516
506
|
end
|
517
507
|
|
518
|
-
# Filter primary key if configured.
|
508
|
+
# Filter primary key, if configured.
|
519
509
|
if self.filter_pk_from_request_body && bulk_mode != :update
|
520
510
|
body_params.delete(pk)
|
521
511
|
end
|
@@ -527,7 +517,7 @@ module RESTFramework::Mixins::BaseModelControllerMixin
|
|
527
517
|
#
|
528
518
|
# rubocop:disable Layout/LineLength
|
529
519
|
#
|
530
|
-
#
|
520
|
+
# Example base64 image:
|
531
521
|
# data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=
|
532
522
|
#
|
533
523
|
# rubocop:enable Layout/LineLength
|
@@ -572,7 +562,6 @@ module RESTFramework::Mixins::BaseModelControllerMixin
|
|
572
562
|
# Cache the result.
|
573
563
|
return @record if @record
|
574
564
|
|
575
|
-
recordset = self.get_recordset
|
576
565
|
find_by_key = self.class.get_model.primary_key
|
577
566
|
is_pk = true
|
578
567
|
|
@@ -588,16 +577,18 @@ module RESTFramework::Mixins::BaseModelControllerMixin
|
|
588
577
|
end
|
589
578
|
end
|
590
579
|
|
591
|
-
#
|
592
|
-
if self.filter_recordset_before_find
|
593
|
-
|
580
|
+
# Get the recordset, filtering if configured.
|
581
|
+
collection = if self.filter_recordset_before_find
|
582
|
+
self.get_records
|
583
|
+
else
|
584
|
+
self.get_recordset
|
594
585
|
end
|
595
586
|
|
596
587
|
# Return the record. Route key is always `:id` by Rails convention.
|
597
588
|
if is_pk
|
598
|
-
return @record =
|
589
|
+
return @record = collection.find(request.path_parameters[:id])
|
599
590
|
else
|
600
|
-
return @record =
|
591
|
+
return @record = collection.find_by!(find_by_key => request.path_parameters[:id])
|
601
592
|
end
|
602
593
|
end
|
603
594
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
# Do not use Rails-specific helper methods here (e.g., `blank?`) so the module can run standalone.
|
2
1
|
module RESTFramework
|
2
|
+
# Do not use Rails-specific helper methods here (e.g., `blank?`) so the module can run standalone.
|
3
3
|
module Version
|
4
4
|
VERSION_FILEPATH = File.expand_path("../../VERSION", __dir__)
|
5
5
|
UNKNOWN = "0-unknown"
|
data/lib/rest_framework.rb
CHANGED
@@ -122,9 +122,19 @@ module RESTFramework
|
|
122
122
|
# Global configuration should be kept minimal, as controller-level configurations allows multiple
|
123
123
|
# APIs to be defined to behave differently.
|
124
124
|
class Config
|
125
|
-
DEFAULT_EXCLUDE_ASSOCIATION_CLASSES = [].freeze
|
126
125
|
DEFAULT_LABEL_FIELDS = %w(name label login title email username url).freeze
|
127
126
|
DEFAULT_SEARCH_COLUMNS = DEFAULT_LABEL_FIELDS + %w(description note).freeze
|
127
|
+
DEFAULT_EXCLUDE_BODY_FIELDS = %w[
|
128
|
+
created_at
|
129
|
+
created_by
|
130
|
+
created_by_id
|
131
|
+
updated_at
|
132
|
+
updated_by
|
133
|
+
updated_by_id
|
134
|
+
_method
|
135
|
+
utf8
|
136
|
+
authenticity_token
|
137
|
+
].freeze
|
128
138
|
|
129
139
|
# Do not run `rrf_finalize` on controllers automatically using a `TracePoint` hook. This is a
|
130
140
|
# performance option and must be global because we have to determine this before any
|
@@ -155,6 +165,9 @@ module RESTFramework
|
|
155
165
|
# The default search columns to use when generating search filters.
|
156
166
|
attr_accessor :search_columns
|
157
167
|
|
168
|
+
# The default list of fields to exclude from the body of the request.
|
169
|
+
attr_accessor :exclude_body_fields
|
170
|
+
|
158
171
|
# Option to use vendored assets (requires sprockets or propshaft) rather than linking to
|
159
172
|
# external assets (the default).
|
160
173
|
attr_accessor :use_vendored_assets
|
@@ -163,6 +176,7 @@ module RESTFramework
|
|
163
176
|
self.show_backtrace = Rails.env.development?
|
164
177
|
self.label_fields = DEFAULT_LABEL_FIELDS
|
165
178
|
self.search_columns = DEFAULT_SEARCH_COLUMNS
|
179
|
+
self.exclude_body_fields = DEFAULT_EXCLUDE_BODY_FIELDS
|
166
180
|
end
|
167
181
|
end
|
168
182
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregory N. Schmit
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|