rest_framework 0.9.7 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -0
  3. data/README.md +73 -45
  4. data/VERSION +1 -1
  5. data/app/views/layouts/rest_framework.html.erb +1 -1
  6. data/app/views/rest_framework/_head.html.erb +1 -2
  7. data/app/views/rest_framework/_heading.html.erb +1 -1
  8. data/app/views/rest_framework/_payloads.html.erb +1 -1
  9. data/app/views/rest_framework/_request_metadata.html.erb +2 -4
  10. data/app/views/rest_framework/_routes_and_forms.html.erb +2 -2
  11. data/lib/rest_framework/errors/base_error.rb +5 -0
  12. data/lib/rest_framework/errors/nil_passed_to_api_response_error.rb +14 -0
  13. data/lib/rest_framework/errors/unknown_model_error.rb +18 -0
  14. data/lib/rest_framework/errors.rb +4 -28
  15. data/lib/rest_framework/filters/{base.rb → base_filter.rb} +4 -1
  16. data/lib/rest_framework/filters/{model_ordering.rb → model_ordering_filter.rb} +4 -1
  17. data/lib/rest_framework/filters/{model_query.rb → model_query_filter.rb} +4 -1
  18. data/lib/rest_framework/filters/{model_search.rb → model_search_filter.rb} +4 -1
  19. data/lib/rest_framework/filters/{ransack.rb → ransack_filter.rb} +4 -1
  20. data/lib/rest_framework/filters.rb +5 -5
  21. data/lib/rest_framework/{controller_mixins/base.rb → mixins/base_controller_mixin.rb} +4 -5
  22. data/lib/rest_framework/{controller_mixins/bulk.rb → mixins/bulk_model_controller_mixin.rb} +16 -10
  23. data/lib/rest_framework/{controller_mixins/models.rb → mixins/model_controller_mixin.rb} +34 -53
  24. data/lib/rest_framework/mixins.rb +7 -0
  25. data/lib/rest_framework/paginators/base_paginator.rb +19 -0
  26. data/lib/rest_framework/paginators/page_number_paginator.rb +84 -0
  27. data/lib/rest_framework/paginators.rb +3 -84
  28. data/lib/rest_framework/routers.rb +0 -1
  29. data/lib/rest_framework/serializers/active_model_serializer_adapter_factory.rb +20 -0
  30. data/lib/rest_framework/serializers/base_serializer.rb +40 -0
  31. data/lib/rest_framework/serializers/native_serializer.rb +360 -0
  32. data/lib/rest_framework/serializers.rb +4 -383
  33. data/lib/rest_framework.rb +1 -1
  34. metadata +20 -12
  35. data/lib/rest_framework/controller_mixins.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a9201bc66da6f1038a27aad8e0754d3b14973c20ca5bb3486b545c081e1cf31
4
- data.tar.gz: af160d2b5f66a1d2ab4b40dcd366e5f10d46e5b4f075ac01926cfbcbc03a5c62
3
+ metadata.gz: 4b816fbe24e240ce66a74b2a3c18fd0a75a449c878c9a0126e4c14ddbaafe5b8
4
+ data.tar.gz: 383836204fd789afd4270794e0d7da57e05b8b8e8f537dd19c7fa2bf6ff1e2eb
5
5
  SHA512:
6
- metadata.gz: 756aa93e81e2cd240a6d383df774c8003a4063e514bd19acce8857a36ae6844c4ee3dddafdd2c9a246ab4f213f9c9b01bd52bcf2758d84b6ec09b59f73ae3257
7
- data.tar.gz: e7b9e1e1730604c3702e9e1c8b744c87ac6d474db8cb70f32457467ddbc25817bc94404b26560c4b19f3ac0ecdd4704ff9393cbd7a88216052ee13071a97a23a
6
+ metadata.gz: 0a845ce1b30eab8ad874e432268092e5e9117200a320d9446a3e333a88d202257987767fd6b9bad2b7b0768c52e564e1a0beede15408027c7c48c8b91beffcd4
7
+ data.tar.gz: a1ae6ccfd603c7759d5db717249790a7b124bc06b39ff3f88eba16527874ec8788e4fdcb149c4e96ca0a6a8dae1ea3361519acfb830e1dfda6bc5ea2b521177b
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --private
2
+ --protected
3
+ -
4
+ LICENSE
5
+ README.md
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.7
1
+ 0.9.9
@@ -1,5 +1,5 @@
1
1
  <!doctype html>
2
- <html class="rrf-mode">
2
+ <html lang="en" class="rrf-mode">
3
3
  <head>
4
4
  <title><%= @title %></title>
5
5
 
@@ -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"
@@ -1,4 +1,4 @@
1
- class RESTFramework::BaseFilter
1
+ class RESTFramework::Filters::BaseFilter
2
2
  def initialize(controller:)
3
3
  @controller = controller
4
4
  end
@@ -7,3 +7,6 @@ class RESTFramework::BaseFilter
7
7
  raise NotImplementedError
8
8
  end
9
9
  end
10
+
11
+ # Alias for convenience.
12
+ RESTFramework::BaseFilter = RESTFramework::Filters::BaseFilter
@@ -1,5 +1,5 @@
1
1
  # A filter backend which handles ordering of the recordset.
2
- class RESTFramework::ModelOrderingFilter < RESTFramework::BaseFilter
2
+ class RESTFramework::Filters::ModelOrderingFilter < RESTFramework::Filters::BaseFilter
3
3
  # Get a list of ordering fields for the current action.
4
4
  def _get_fields
5
5
  return @controller.ordering_fields&.map(&:to_s) || @controller.get_fields
@@ -46,3 +46,6 @@ class RESTFramework::ModelOrderingFilter < RESTFramework::BaseFilter
46
46
  return data
47
47
  end
48
48
  end
49
+
50
+ # Alias for convenience.
51
+ RESTFramework::ModelOrderingFilter = RESTFramework::Filters::ModelOrderingFilter
@@ -1,5 +1,5 @@
1
1
  # A simple filtering backend that supports filtering a recordset based on query parameters.
2
- class RESTFramework::ModelQueryFilter < RESTFramework::BaseFilter
2
+ class RESTFramework::Filters::ModelQueryFilter < RESTFramework::Filters::BaseFilter
3
3
  # Get a list of filterset fields for the current action.
4
4
  def _get_fields
5
5
  # Always return a list of strings; `@controller.get_fields` already does this.
@@ -49,3 +49,6 @@ class RESTFramework::ModelQueryFilter < RESTFramework::BaseFilter
49
49
  return data
50
50
  end
51
51
  end
52
+
53
+ # Alias for convenience.
54
+ RESTFramework::ModelQueryFilter = RESTFramework::Filters::ModelQueryFilter
@@ -1,5 +1,5 @@
1
1
  # Multi-field text searching on models.
2
- class RESTFramework::ModelSearchFilter < RESTFramework::BaseFilter
2
+ class RESTFramework::Filters::ModelSearchFilter < RESTFramework::Filters::BaseFilter
3
3
  # Get a list of search fields for the current action.
4
4
  def _get_fields
5
5
  if search_fields = @controller.search_fields
@@ -39,3 +39,6 @@ class RESTFramework::ModelSearchFilter < RESTFramework::BaseFilter
39
39
  return data
40
40
  end
41
41
  end
42
+
43
+ # Alias for convenience.
44
+ RESTFramework::ModelSearchFilter = RESTFramework::Filters::ModelSearchFilter
@@ -1,5 +1,5 @@
1
1
  # Adapter for the `ransack` gem.
2
- class RESTFramework::RansackFilter < RESTFramework::BaseFilter
2
+ class RESTFramework::Filters::RansackFilter < RESTFramework::Filters::BaseFilter
3
3
  # Filter data according to the request query parameters.
4
4
  def get_filtered_data(data)
5
5
  q = @controller.request.query_parameters[@controller.ransack_query_param]
@@ -23,3 +23,6 @@ class RESTFramework::RansackFilter < RESTFramework::BaseFilter
23
23
  return data
24
24
  end
25
25
  end
26
+
27
+ # Alias for convenience.
28
+ RESTFramework::RansackFilter = RESTFramework::Filters::RansackFilter
@@ -1,9 +1,9 @@
1
1
  module RESTFramework::Filters
2
2
  end
3
3
 
4
- require_relative "filters/base"
4
+ require_relative "filters/base_filter"
5
5
 
6
- require_relative "filters/model_ordering"
7
- require_relative "filters/model_query"
8
- require_relative "filters/model_search"
9
- require_relative "filters/ransack"
6
+ require_relative "filters/model_ordering_filter"
7
+ require_relative "filters/model_query_filter"
8
+ require_relative "filters/model_search_filter"
9
+ require_relative "filters/ransack_filter"
@@ -1,11 +1,7 @@
1
- require_relative "../errors"
2
- require_relative "../serializers"
3
- require_relative "../utils"
4
-
5
1
  # This module provides the common functionality for any controller mixins, a `root` action, and
6
2
  # the ability to route arbitrary actions with `extra_actions`. This is also where `api_response`
7
3
  # is defined.
8
- module RESTFramework::BaseControllerMixin
4
+ module RESTFramework::Mixins::BaseControllerMixin
9
5
  RRF_BASE_CONFIG = {
10
6
  extra_actions: nil,
11
7
  extra_member_actions: nil,
@@ -348,3 +344,6 @@ module RESTFramework::BaseControllerMixin
348
344
  return api_response(self.get_options_metadata)
349
345
  end
350
346
  end
347
+
348
+ # Alias for convenience.
349
+ RESTFramework::BaseControllerMixin = RESTFramework::Mixins::BaseControllerMixin
@@ -1,8 +1,8 @@
1
- require_relative "models"
1
+ require_relative "model_controller_mixin"
2
2
 
3
3
  # Mixin for creating records in bulk. This is unique compared to update/destroy because we overload
4
4
  # the existing `create` action to support bulk creation.
5
- module RESTFramework::BulkCreateModelMixin
5
+ module RESTFramework::Mixins::BulkCreateModelMixin
6
6
  # While bulk update/destroy are obvious because they create new router endpoints, bulk create
7
7
  # overloads the existing collection `POST` endpoint, so we add a special key to the options
8
8
  # metadata to indicate bulk create is supported.
@@ -32,7 +32,7 @@ module RESTFramework::BulkCreateModelMixin
32
32
  end
33
33
 
34
34
  # Mixin for updating records in bulk.
35
- module RESTFramework::BulkUpdateModelMixin
35
+ module RESTFramework::Mixins::BulkUpdateModelMixin
36
36
  def update_all
37
37
  records = self.update_all!
38
38
  serialized_records = self.bulk_serialize(records)
@@ -57,7 +57,7 @@ module RESTFramework::BulkUpdateModelMixin
57
57
  end
58
58
 
59
59
  # Mixin for destroying records in bulk.
60
- module RESTFramework::BulkDestroyModelMixin
60
+ module RESTFramework::Mixins::BulkDestroyModelMixin
61
61
  def destroy_all
62
62
  if params[:_json].is_a?(Array)
63
63
  records = self.destroy_all!
@@ -84,14 +84,20 @@ module RESTFramework::BulkDestroyModelMixin
84
84
  end
85
85
 
86
86
  # Mixin that includes all the CRUD bulk mixins.
87
- module RESTFramework::BulkModelControllerMixin
88
- include RESTFramework::ModelControllerMixin
87
+ module RESTFramework::Mixins::BulkModelControllerMixin
88
+ include RESTFramework::Mixins::ModelControllerMixin
89
89
 
90
- include RESTFramework::BulkCreateModelMixin
91
- include RESTFramework::BulkUpdateModelMixin
92
- include RESTFramework::BulkDestroyModelMixin
90
+ include RESTFramework::Mixins::BulkCreateModelMixin
91
+ include RESTFramework::Mixins::BulkUpdateModelMixin
92
+ include RESTFramework::Mixins::BulkDestroyModelMixin
93
93
 
94
94
  def self.included(base)
95
- RESTFramework::ModelControllerMixin.included(base)
95
+ RESTFramework::Mixins::ModelControllerMixin.included(base)
96
96
  end
97
97
  end
98
+
99
+ # Aliases for convenience.
100
+ RESTFramework::BulkCreateModelMixin = RESTFramework::Mixins::BulkCreateModelMixin
101
+ RESTFramework::BulkUpdateModelMixin = RESTFramework::Mixins::BulkUpdateModelMixin
102
+ RESTFramework::BulkDestroyModelMixin = RESTFramework::Mixins::BulkDestroyModelMixin
103
+ RESTFramework::BulkModelControllerMixin = RESTFramework::Mixins::BulkModelControllerMixin