rest_framework 0.9.7 → 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.
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