rest_framework 0.9.8 → 0.9.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b06a61592498f8debce6f504b4eee90ceeef6fdff63dbb769bd70c623cd9631
4
- data.tar.gz: ab5b1284a3504104b77cc38278bad01a1dfa30ce7ebcd65323b73e0dd31e58a2
3
+ metadata.gz: 4b816fbe24e240ce66a74b2a3c18fd0a75a449c878c9a0126e4c14ddbaafe5b8
4
+ data.tar.gz: 383836204fd789afd4270794e0d7da57e05b8b8e8f537dd19c7fa2bf6ff1e2eb
5
5
  SHA512:
6
- metadata.gz: ed04505314f252ac1058732a875711090fb07499edac42814bf72e5b15f90f833040e40399df279654727041af30789c8a931e06d83b9fc1c67f46d4f0da850f
7
- data.tar.gz: abd68ae8ab71f2fff8f7a933270a467811143096f7cdde16d21c99ac3faeadc8f958cb0bcdde94c1b57f1d620fc278f8d9b5e3b4e2cec5851fb4616f9c325d41
6
+ metadata.gz: 0a845ce1b30eab8ad874e432268092e5e9117200a320d9446a3e333a88d202257987767fd6b9bad2b7b0768c52e564e1a0beede15408027c7c48c8b91beffcd4
7
+ data.tar.gz: a1ae6ccfd603c7759d5db717249790a7b124bc06b39ff3f88eba16527874ec8788e4fdcb149c4e96ca0a6a8dae1ea3361519acfb830e1dfda6bc5ea2b521177b
data/README.md CHANGED
@@ -27,87 +27,122 @@ YARD Docs: [rubydoc.info/gems/rest_framework](https://rubydoc.info/gems/rest_fra
27
27
  Add this line to your application's Gemfile:
28
28
 
29
29
  ```ruby
30
- gem 'rest_framework'
30
+ gem "rest_framework"
31
31
  ```
32
32
 
33
- And then execute:
33
+ And then run:
34
34
 
35
35
  ```shell
36
- $ bundle install
36
+ bundle install
37
37
  ```
38
38
 
39
- Or install it yourself with:
39
+ ## Quick Usage Tutorial
40
40
 
41
- ```shell
42
- $ gem install rest_framework
43
- ```
41
+ This section provides some simple examples to quickly get you started using the framework.
44
42
 
45
- ## Quick Usage Tutorial
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:
45
+
46
+ ```text
47
+ controllers/
48
+ ├─ api_controller.rb
49
+ └─ api/
50
+ ├─ root_controller.rb
51
+ ├─ movies_controller.rb
52
+ └─ users_controller.rb
53
+ ```
46
54
 
47
55
  ### Controller Mixins
48
56
 
49
- To transform a controller into a RESTful controller, you can either include `BaseControllerMixin`,
50
- `ReadOnlyModelControllerMixin`, or `ModelControllerMixin`. `BaseControllerMixin` provides a `root`
51
- action and a simple interface for routing arbitrary additional actions:
57
+ The root `ApiController` can include any common behavior you want to share across all your API
58
+ controllers:
52
59
 
53
60
  ```ruby
54
61
  class ApiController < ApplicationController
55
62
  include RESTFramework::BaseControllerMixin
63
+
64
+ # Setting up a paginator class here makes more sense than defining it on every child controller.
65
+ self.paginator_class = RESTFramework::PageNumberPaginator
66
+
67
+ # The page_size attribute doesn't exist on the `BaseControllerMixin`, but for child controllers
68
+ # that include the `ModelControllerMixin`, they will inherit this attribute and will not overwrite
69
+ # it.
70
+ class_attribute(:page_size, default: 30)
71
+ end
72
+ ```
73
+
74
+ A root controller can provide actions that exist on the root of your API. It's best to define a
75
+ dedicated root controller, rather than using the `ApiController` for this purpose, so that actions
76
+ don't propagate to child controllers:
77
+
78
+ ```ruby
79
+ class Api::RootController < ApiController
56
80
  self.extra_actions = {test: :get}
57
81
 
82
+ def root
83
+ return api_response(
84
+ {
85
+ message: "Welcome to the API.",
86
+ how_to_authenticate: <<~END.lines.map(&:strip).join(" "),
87
+ You can use this API with your normal login session. Otherwise, you can insert your API
88
+ key into a Bearer Authorization header, or into the URL parameters with the name
89
+ `api_key`.
90
+ END
91
+ },
92
+ )
93
+ end
94
+
58
95
  def test
59
- render api_response({message: "Test successful!"})
96
+ return api_response({message: "Hello, world!"})
60
97
  end
61
98
  end
62
99
  ```
63
100
 
64
- `ModelControllerMixin` assists with providing the standard model CRUD for your controller.
101
+ And here is an example of a resource controller:
65
102
 
66
103
  ```ruby
67
104
  class Api::MoviesController < ApiController
68
105
  include RESTFramework::ModelControllerMixin
69
106
 
70
- self.recordset = Movie.where(enabled: true)
107
+ self.fields = [:id, :name, :release_date, :enabled]
108
+ self.extra_member_actions = {first: :get}
109
+
110
+ def first
111
+ # Always use the bang method, since the framework will rescue `RecordNotFound` and return a
112
+ # sensible error response.
113
+ return api_response(self.get_records.first!)
114
+ end
115
+
116
+ def get_recordset
117
+ return Movie.where(enabled: true)
118
+ end
71
119
  end
72
120
  ```
73
121
 
74
- `ReadOnlyModelControllerMixin` only enables list/show actions, but since we're naming this
75
- controller in a way that doesn't make the model obvious, we can set that explicitly:
122
+ You can also configure a resource's fields dynamically using `include` and `exclude` keys:
76
123
 
77
124
  ```ruby
78
- class Api::ReadOnlyMoviesController < ApiController
79
- include RESTFramework::ReadOnlyModelControllerMixin
125
+ class Api::UsersController < ApiController
126
+ include RESTFramework::ModelControllerMixin
80
127
 
81
- self.model = Movie
128
+ self.fields = {include: [:calculated_popularity], exclude: [:impersonation_token]}
82
129
  end
83
130
  ```
84
131
 
85
- Note that you can also override the `get_recordset` instance method to override the API behavior
86
- dynamically per-request.
87
-
88
132
  ### Routing
89
133
 
90
134
  You can use Rails' `resource`/`resources` routers to route your API, however if you want
91
135
  `extra_actions` / `extra_member_actions` to be routed automatically, then you can use `rest_route`
92
- for non-resourceful controllers, or `rest_resource` / `rest_resources` resourceful routers. You can
93
- also use `rest_root` to route the root of your API:
136
+ for non-resourceful controllers, or `rest_resource` / `rest_resources` resourceful routers. To route
137
+ the root, use `rest_root`.
94
138
 
95
139
  ```ruby
96
140
  Rails.application.routes.draw do
97
- rest_root :api # will find `api_controller` and route the `root` action to '/api'
98
- namespace :api do
99
- rest_resources :movies
100
- rest_resources :users
101
- end
102
- end
103
- ```
104
-
105
- Or if you want the API root to be routed to `Api::RootController#root`:
141
+ # If you wanted to route actions from the `ApiController`, then you would use this:
142
+ # rest_root :api # Will find `api_controller` and route the `root` action to '/api'.
106
143
 
107
- ```ruby
108
- Rails.application.routes.draw do
109
144
  namespace :api do
110
- rest_root # will route `Api::RootController#root` to '/' in this namespace ('/api')
145
+ rest_root # Will route `Api::RootController#root` to '/' in this namespace ('/api').
111
146
  rest_resources :movies
112
147
  rest_resources :users
113
148
  end
@@ -117,14 +152,7 @@ end
117
152
  ## Development/Testing
118
153
 
119
154
  After you clone the repository, cd'ing into the directory should create a new gemset if you are
120
- using RVM. Then run `bundle install` to install the appropriate gems.
121
-
122
- To run the test suite:
123
-
124
- ```shell
125
- $ rails test
126
- ```
155
+ using RVM. Then run `bin/setup` to install the appropriate gems and set things up.
127
156
 
128
157
  The top-level `bin/rails` proxies all Rails commands to the test project, so you can operate it via
129
- the usual commands. Ensure you run `rails db:setup` before running `rails server` or
130
- `rails console`.
158
+ the usual commands (e.g., `rails test`, `rails server` and `rails console`).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.8
1
+ 0.9.9
@@ -29,7 +29,6 @@
29
29
  h1, h2, h3, h4, h5, h6 {
30
30
  color: var(--rrf-red);
31
31
  font-weight: normal;
32
- margin-bottom: 0;
33
32
  }
34
33
  html[data-bs-theme="dark"] h1,
35
34
  html[data-bs-theme="dark"] h2,
@@ -290,7 +289,7 @@
290
289
 
291
290
  // Convert plain-text links to anchor tag links.
292
291
  function rrfLinkify(text) {
293
- return text.replace(/(https?:\/\/[^\s<>"]+)/g, "<a href=\"$1\" target=\"_blank\">$1</a>")
292
+ return text.replace(/(https?:\/\/[^\s<>"]+)/g, "<a href=\"$1\">$1</a>")
294
293
  }
295
294
 
296
295
  // Replace the document when doing form submission (mainly to support PUT/PATCH/DELETE).
@@ -1,7 +1,7 @@
1
1
  <div class="row">
2
2
  <div>
3
3
  <%= render partial: "rest_framework/heading/actions" if @route_groups.present? %>
4
- <h1 class="m-0"><%= @heading_title || @title %></h1>
4
+ <h1 style="margin: 0"><%= @heading_title || @title %></h1>
5
5
  <% if @description.present? %>
6
6
  <br><br><p style="display: inline-block; margin-bottom: 0"><%= @description %></p>
7
7
  <% end %>
@@ -17,7 +17,7 @@
17
17
  <% end %>
18
18
  </ul>
19
19
  </div>
20
- <div class="tab-content pt-2">
20
+ <div class="tab-content">
21
21
  <div class="tab-pane fade show active" id="tab-json" role="tabpanel">
22
22
  <% if @json_payload.present? %>
23
23
  <div><pre class="rrf-copy"><code class="language-json"><%=
@@ -1,16 +1,14 @@
1
1
  <div class="row">
2
2
  <div>
3
- <pre><code><%
3
+ <pre class="mb-2"><code class="language-plaintext"><%
4
4
  concat request.request_method
5
5
  if request.method != request.request_method
6
6
  concat " (via #{request.method})"
7
7
  end
8
8
  concat " #{request.path}"
9
9
  %></code></pre>
10
- <pre><code><%
10
+ <pre><code class="language-plaintext"><%
11
11
  concat "HTTP #{response.status} #{response.message}"
12
- concat "\n"
13
- concat "Content-Type: #{response.content_type}"
14
12
  %></code></pre>
15
13
  </div>
16
14
  </div>
@@ -34,7 +34,7 @@
34
34
  <% end %>
35
35
  </ul>
36
36
  </div>
37
- <div class="tab-content pt-2">
37
+ <div class="tab-content">
38
38
  <div class="tab-pane fade show active" id="tab-routes" role="tabpanel">
39
39
  <%= render partial: "rest_framework/routes_and_forms/routes" %>
40
40
  </div>
@@ -49,4 +49,4 @@
49
49
  </div>
50
50
  <% end %>
51
51
  </div>
52
- </div>
52
+ </div>
@@ -0,0 +1,5 @@
1
+ class RESTFramework::Errors::BaseError < StandardError
2
+ end
3
+
4
+ # Alias for convenience.
5
+ RESTFramework::BaseError = RESTFramework::Errors::BaseError
@@ -0,0 +1,14 @@
1
+ class RESTFramework::Errors::NilPassedToAPIResponseError < RESTFramework::Errors::BaseError
2
+ def message
3
+ return <<~MSG.split("\n").join(" ")
4
+ Payload of `nil` was passed to `api_response`; this is unsupported. If you want a blank
5
+ response, pass `''` (an empty string) as the payload. If this was the result of a `find_by`
6
+ (or similar Active Record method) not finding a record, you should use the bang version (e.g.,
7
+ `find_by!`) to raise `ActiveRecord::RecordNotFound`, which the REST controller will catch and
8
+ return an appropriate error response.
9
+ MSG
10
+ end
11
+ end
12
+
13
+ # Alias for convenience.
14
+ RESTFramework::NilPassedToAPIResponseError = RESTFramework::Errors::NilPassedToAPIResponseError
@@ -0,0 +1,18 @@
1
+ class RESTFramework::Errors::UnknownModelError < RESTFramework::Errors::BaseError
2
+ def initialize(controller_class)
3
+ super()
4
+ @controller_class = controller_class
5
+ end
6
+
7
+ def message
8
+ return <<~MSG.split("\n").join(" ")
9
+ The model class for `#{@controller_class}` could not be determined. Any controller that
10
+ includes `RESTFramework::BaseModelControllerMixin` (directly or indirectly) must either set
11
+ the `model` attribute on the controller, or the model must be deducible from the controller
12
+ name (e.g., `UsersController` could resolve to the `User` model).
13
+ MSG
14
+ end
15
+ end
16
+
17
+ # Alias for convenience.
18
+ RESTFramework::UnknownModelError = RESTFramework::Errors::UnknownModelError
@@ -1,31 +1,7 @@
1
- # Top-level class for all REST Framework errors.
2
- class RESTFramework::Error < StandardError
1
+ module RESTFramework::Errors
3
2
  end
4
3
 
5
- class RESTFramework::NilPassedToAPIResponseError < RESTFramework::Error
6
- def message
7
- return <<~MSG.split("\n").join(" ")
8
- Payload of `nil` was passed to `api_response`; this is unsupported. If you want a blank
9
- response, pass `''` (an empty string) as the payload. If this was the result of a `find_by`
10
- (or similar Active Record method) not finding a record, you should use the bang version (e.g.,
11
- `find_by!`) to raise `ActiveRecord::RecordNotFound`, which the REST controller will catch and
12
- return an appropriate error response.
13
- MSG
14
- end
15
- end
16
-
17
- class RESTFramework::UnknownModelError < RESTFramework::Error
18
- def initialize(controller_class)
19
- super()
20
- @controller_class = controller_class
21
- end
4
+ require_relative "errors/base_error"
22
5
 
23
- def message
24
- return <<~MSG.split("\n").join(" ")
25
- The model class for `#{@controller_class}` could not be determined. Any controller that
26
- includes `RESTFramework::BaseModelControllerMixin` (directly or indirectly) must either set
27
- the `model` attribute on the controller, or the model must be deducible from the controller
28
- name (e.g., `UsersController` could resolve to the `User` model).
29
- MSG
30
- end
31
- end
6
+ require_relative "errors/nil_passed_to_api_response_error"
7
+ require_relative "errors/unknown_model_error"
@@ -31,9 +31,6 @@ module RESTFramework::Mixins::BulkCreateModelMixin
31
31
  end
32
32
  end
33
33
 
34
- # Alias for convenience.
35
- RESTFramework::BulkCreateModelMixin = RESTFramework::Mixins::BulkCreateModelMixin
36
-
37
34
  # Mixin for updating records in bulk.
38
35
  module RESTFramework::Mixins::BulkUpdateModelMixin
39
36
  def update_all
@@ -59,9 +56,6 @@ module RESTFramework::Mixins::BulkUpdateModelMixin
59
56
  end
60
57
  end
61
58
 
62
- # Alias for convenience.
63
- RESTFramework::BulkUpdateModelMixin = RESTFramework::Mixins::BulkUpdateModelMixin
64
-
65
59
  # Mixin for destroying records in bulk.
66
60
  module RESTFramework::Mixins::BulkDestroyModelMixin
67
61
  def destroy_all
@@ -89,21 +83,21 @@ module RESTFramework::Mixins::BulkDestroyModelMixin
89
83
  end
90
84
  end
91
85
 
92
- # Alias for convenience.
93
- RESTFramework::BulkDestroyModelMixin = RESTFramework::Mixins::BulkDestroyModelMixin
94
-
95
86
  # Mixin that includes all the CRUD bulk mixins.
96
87
  module RESTFramework::Mixins::BulkModelControllerMixin
97
- include RESTFramework::ModelControllerMixin
88
+ include RESTFramework::Mixins::ModelControllerMixin
98
89
 
99
- include RESTFramework::BulkCreateModelMixin
100
- include RESTFramework::BulkUpdateModelMixin
101
- include RESTFramework::BulkDestroyModelMixin
90
+ include RESTFramework::Mixins::BulkCreateModelMixin
91
+ include RESTFramework::Mixins::BulkUpdateModelMixin
92
+ include RESTFramework::Mixins::BulkDestroyModelMixin
102
93
 
103
94
  def self.included(base)
104
- RESTFramework::ModelControllerMixin.included(base)
95
+ RESTFramework::Mixins::ModelControllerMixin.included(base)
105
96
  end
106
97
  end
107
98
 
108
- # Alias for convenience.
99
+ # Aliases for convenience.
100
+ RESTFramework::BulkCreateModelMixin = RESTFramework::Mixins::BulkCreateModelMixin
101
+ RESTFramework::BulkUpdateModelMixin = RESTFramework::Mixins::BulkUpdateModelMixin
102
+ RESTFramework::BulkDestroyModelMixin = RESTFramework::Mixins::BulkDestroyModelMixin
109
103
  RESTFramework::BulkModelControllerMixin = RESTFramework::Mixins::BulkModelControllerMixin
@@ -631,9 +631,6 @@ module RESTFramework::Mixins::BaseModelControllerMixin
631
631
  end
632
632
  end
633
633
 
634
- # Alias for convenience.
635
- RESTFramework::BaseModelControllerMixin = RESTFramework::Mixins::BaseModelControllerMixin
636
-
637
634
  # Mixin for listing records.
638
635
  module RESTFramework::Mixins::ListModelMixin
639
636
  def index
@@ -662,9 +659,6 @@ module RESTFramework::Mixins::ListModelMixin
662
659
  end
663
660
  end
664
661
 
665
- # Alias for convenience.
666
- RESTFramework::ListModelMixin = RESTFramework::Mixins::ListModelMixin
667
-
668
662
  # Mixin for showing records.
669
663
  module RESTFramework::Mixins::ShowModelMixin
670
664
  def show
@@ -672,9 +666,6 @@ module RESTFramework::Mixins::ShowModelMixin
672
666
  end
673
667
  end
674
668
 
675
- # Alias for convenience.
676
- RESTFramework::ShowModelMixin = RESTFramework::Mixins::ShowModelMixin
677
-
678
669
  # Mixin for creating records.
679
670
  module RESTFramework::Mixins::CreateModelMixin
680
671
  def create
@@ -687,9 +678,6 @@ module RESTFramework::Mixins::CreateModelMixin
687
678
  end
688
679
  end
689
680
 
690
- # Alias for convenience.
691
- RESTFramework::CreateModelMixin = RESTFramework::Mixins::CreateModelMixin
692
-
693
681
  # Mixin for updating records.
694
682
  module RESTFramework::Mixins::UpdateModelMixin
695
683
  def update
@@ -704,9 +692,6 @@ module RESTFramework::Mixins::UpdateModelMixin
704
692
  end
705
693
  end
706
694
 
707
- # Alias for convenience.
708
- RESTFramework::UpdateModelMixin = RESTFramework::Mixins::UpdateModelMixin
709
-
710
695
  # Mixin for destroying records.
711
696
  module RESTFramework::Mixins::DestroyModelMixin
712
697
  def destroy
@@ -720,38 +705,39 @@ module RESTFramework::Mixins::DestroyModelMixin
720
705
  end
721
706
  end
722
707
 
723
- # Alias for convenience.
724
- RESTFramework::DestroyModelMixin = RESTFramework::Mixins::DestroyModelMixin
725
-
726
708
  # Mixin that includes show/list mixins.
727
709
  module RESTFramework::Mixins::ReadOnlyModelControllerMixin
728
- include RESTFramework::BaseModelControllerMixin
710
+ include RESTFramework::Mixins::BaseModelControllerMixin
729
711
 
730
- include RESTFramework::ListModelMixin
731
- include RESTFramework::ShowModelMixin
712
+ include RESTFramework::Mixins::ListModelMixin
713
+ include RESTFramework::Mixins::ShowModelMixin
732
714
 
733
715
  def self.included(base)
734
716
  RESTFramework::BaseModelControllerMixin.included(base)
735
717
  end
736
718
  end
737
719
 
738
- # Alias for convenience.
739
- RESTFramework::ReadOnlyModelControllerMixin = RESTFramework::Mixins::ReadOnlyModelControllerMixin
740
-
741
720
  # Mixin that includes all the CRUD mixins.
742
721
  module RESTFramework::Mixins::ModelControllerMixin
743
- include RESTFramework::BaseModelControllerMixin
722
+ include RESTFramework::Mixins::BaseModelControllerMixin
744
723
 
745
- include RESTFramework::ListModelMixin
746
- include RESTFramework::ShowModelMixin
747
- include RESTFramework::CreateModelMixin
748
- include RESTFramework::UpdateModelMixin
749
- include RESTFramework::DestroyModelMixin
724
+ include RESTFramework::Mixins::ListModelMixin
725
+ include RESTFramework::Mixins::ShowModelMixin
726
+ include RESTFramework::Mixins::CreateModelMixin
727
+ include RESTFramework::Mixins::UpdateModelMixin
728
+ include RESTFramework::Mixins::DestroyModelMixin
750
729
 
751
730
  def self.included(base)
752
731
  RESTFramework::BaseModelControllerMixin.included(base)
753
732
  end
754
733
  end
755
734
 
756
- # Alias for convenience.
735
+ # Aliases for convenience.
736
+ RESTFramework::BaseModelControllerMixin = RESTFramework::Mixins::BaseModelControllerMixin
737
+ RESTFramework::ListModelMixin = RESTFramework::Mixins::ListModelMixin
738
+ RESTFramework::ShowModelMixin = RESTFramework::Mixins::ShowModelMixin
739
+ RESTFramework::CreateModelMixin = RESTFramework::Mixins::CreateModelMixin
740
+ RESTFramework::UpdateModelMixin = RESTFramework::Mixins::UpdateModelMixin
741
+ RESTFramework::DestroyModelMixin = RESTFramework::Mixins::DestroyModelMixin
742
+ RESTFramework::ReadOnlyModelControllerMixin = RESTFramework::Mixins::ReadOnlyModelControllerMixin
757
743
  RESTFramework::ModelControllerMixin = RESTFramework::Mixins::ModelControllerMixin
@@ -59,13 +59,24 @@ class RESTFramework::Paginators::PageNumberPaginator < RESTFramework::Paginators
59
59
 
60
60
  # Wrap the serialized page with appropriate metadata. TODO: include links.
61
61
  def get_paginated_response(serialized_page)
62
+ page_query_param = @controller.page_query_param
63
+ base_params = @controller.params.to_unsafe_h
64
+ next_url = if @page_number < @total_pages
65
+ @controller.url_for({**base_params, page_query_param => @page_number + 1})
66
+ end
67
+ previous_url = if @page_number > 1
68
+ @controller.url_for({**base_params, page_query_param => @page_number - 1})
69
+ end
70
+
62
71
  return {
63
72
  count: @count,
64
73
  page: @page_number,
65
74
  page_size: @page_size,
66
75
  total_pages: @total_pages,
76
+ next: next_url,
77
+ previous: previous_url,
67
78
  results: serialized_page,
68
- }
79
+ }.compact
69
80
  end
70
81
  end
71
82
 
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.8
4
+ version: 0.9.9
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-07 00:00:00.000000000 Z
11
+ date: 2023-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -53,6 +53,9 @@ files:
53
53
  - lib/rest_framework.rb
54
54
  - lib/rest_framework/engine.rb
55
55
  - lib/rest_framework/errors.rb
56
+ - lib/rest_framework/errors/base_error.rb
57
+ - lib/rest_framework/errors/nil_passed_to_api_response_error.rb
58
+ - lib/rest_framework/errors/unknown_model_error.rb
56
59
  - lib/rest_framework/filters.rb
57
60
  - lib/rest_framework/filters/base_filter.rb
58
61
  - lib/rest_framework/filters/model_ordering_filter.rb