rest_framework 1.0.0.rc1 → 1.0.0
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 +4 -4
- data/README.md +6 -2
- data/VERSION +1 -1
- data/lib/rest_framework/errors/nil_passed_to_render_api_error.rb +1 -1
- data/lib/rest_framework/errors/unknown_model_error.rb +1 -1
- data/lib/rest_framework/filters/ordering_filter.rb +3 -3
- data/lib/rest_framework/filters/query_filter.rb +13 -14
- data/lib/rest_framework/filters/ransack_filter.rb +1 -1
- data/lib/rest_framework/filters/search_filter.rb +3 -3
- data/lib/rest_framework/generators/controller_generator.rb +2 -2
- data/lib/rest_framework/mixins/base_controller_mixin.rb +34 -33
- data/lib/rest_framework/mixins/bulk_model_controller_mixin.rb +8 -15
- data/lib/rest_framework/mixins/model_controller_mixin.rb +42 -35
- data/lib/rest_framework/paginators/page_number_paginator.rb +6 -6
- data/lib/rest_framework/routers.rb +7 -7
- data/lib/rest_framework/serializers/active_model_serializer_adapter_factory.rb +4 -2
- data/lib/rest_framework/serializers/base_serializer.rb +7 -5
- data/lib/rest_framework/serializers/native_serializer.rb +22 -22
- data/lib/rest_framework/utils.rb +21 -21
- data/lib/rest_framework/version.rb +1 -1
- data/lib/rest_framework.rb +9 -9
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90b0053684520db23e669f2badfea90f4bc138106f79cfece16e17fc4ef449f0
|
4
|
+
data.tar.gz: 03a2d6ec4d1178fca154641ca6522df27592fa2b32b7024de76ceec827d23a8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb23fb3f071a17bbc1aaf2f8c5b8571e47a46a8faeeeb43f851dc64d60d422b7a12ba924200e5ec4124b5b75fe06f868a8ee623c97345753f7d1dc3d5244c16d
|
7
|
+
data.tar.gz: 2828fe0ca8cf5415c781f09da370dc1e92e5408b21e0d77650151aa1d9234e0a31e1e4fb8db2737166acdeba4166b79f42659086fdbd0dcf6bd80150cfb73f11
|
data/README.md
CHANGED
@@ -152,5 +152,9 @@ After you clone the repository, cd'ing into the directory should create a new ge
|
|
152
152
|
using RVM. Then run `bin/setup` to install the appropriate gems and set things up.
|
153
153
|
|
154
154
|
The top-level `bin/rails` proxies all Rails commands to the test project, so you can operate it via
|
155
|
-
the usual commands (e.g., `rails test`, `rails
|
156
|
-
|
155
|
+
the usual commands (e.g., `rails test`, `rails console`). For development, use `bin/dev` to run the
|
156
|
+
web server and the job queue, which serves the test app and coverage/brakeman reports:
|
157
|
+
|
158
|
+
- Test App: [http://127.0.0.1:3000](http://127.0.0.1:3000)
|
159
|
+
- API: [http://127.0.0.1:3000/api](http://127.0.0.1:3000/api)
|
160
|
+
- Reports: [http://127.0.0.1:3000/reports](http://127.0.0.1:3000/reports)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0
|
1
|
+
1.0.0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class RESTFramework::Errors::NilPassedToRenderAPIError < RESTFramework::Errors::BaseError
|
2
2
|
def message
|
3
|
-
|
3
|
+
<<~MSG.split("\n").join(" ")
|
4
4
|
Payload of `nil` was passed to `render_api`; this is unsupported. If you want a blank
|
5
5
|
response, pass `''` (an empty string) as the payload. If this was the result of a `find_by`
|
6
6
|
(or similar Active Record method) not finding a record, you should use the bang version (e.g.,
|
@@ -5,7 +5,7 @@ class RESTFramework::Errors::UnknownModelError < RESTFramework::Errors::BaseErro
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def message
|
8
|
-
|
8
|
+
<<~MSG.split("\n").join(" ")
|
9
9
|
The model class for `#{@controller_class}` could not be determined. Any controller that
|
10
10
|
includes `RESTFramework::BaseModelControllerMixin` (directly or indirectly) must either set
|
11
11
|
the `model` attribute on the controller, or the model must be deducible from the controller
|
@@ -2,7 +2,7 @@
|
|
2
2
|
class RESTFramework::Filters::OrderingFilter < RESTFramework::Filters::BaseFilter
|
3
3
|
# Get a list of ordering fields for the current action.
|
4
4
|
def _get_fields
|
5
|
-
|
5
|
+
@controller.class.ordering_fields&.map(&:to_s) || @controller.get_fields
|
6
6
|
end
|
7
7
|
|
8
8
|
# Convert ordering string to an ordering configuration.
|
@@ -34,7 +34,7 @@ class RESTFramework::Filters::OrderingFilter < RESTFramework::Filters::BaseFilte
|
|
34
34
|
return ordering
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
nil
|
38
38
|
end
|
39
39
|
|
40
40
|
# Order data according to the request query parameters.
|
@@ -46,7 +46,7 @@ class RESTFramework::Filters::OrderingFilter < RESTFramework::Filters::BaseFilte
|
|
46
46
|
return data.send(reorder ? :reorder : :order, ordering)
|
47
47
|
end
|
48
48
|
|
49
|
-
|
49
|
+
data
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -13,18 +13,18 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
|
|
13
13
|
true: true,
|
14
14
|
false: false,
|
15
15
|
null: nil,
|
16
|
-
lt: ->(f, v) { {f => ...v} },
|
16
|
+
lt: ->(f, v) { { f => ...v } },
|
17
17
|
# `gt` must negate `lte` because Rails doesn't support `>` with endless ranges.
|
18
|
-
gt: ->(f, v) { Not.new({f => ..v}) },
|
19
|
-
lte: ->(f, v) { {f => ..v} },
|
20
|
-
gte: ->(f, v) { {f => v..} },
|
21
|
-
not: ->(f, v) { Not.new({f => v}) },
|
22
|
-
cont: ->(f, v) { ["#{f} LIKE ?", "%#{ActiveRecord::Base.sanitize_sql_like(v)}%"] },
|
18
|
+
gt: ->(f, v) { Not.new({ f => ..v }) },
|
19
|
+
lte: ->(f, v) { { f => ..v } },
|
20
|
+
gte: ->(f, v) { { f => v.. } },
|
21
|
+
not: ->(f, v) { Not.new({ f => v }) },
|
22
|
+
cont: ->(f, v) { [ "#{f} LIKE ?", "%#{ActiveRecord::Base.sanitize_sql_like(v)}%" ] },
|
23
23
|
in: ->(f, v) {
|
24
24
|
if v.is_a?(Array)
|
25
|
-
{f => v.map { |v| v == "null" ? nil : v }}
|
25
|
+
{ f => v.map { |v| v == "null" ? nil : v } }
|
26
26
|
elsif v.is_a?(String)
|
27
|
-
{f => v.split(",").map { |v| v == "null" ? nil : v }}
|
27
|
+
{ f => v.split(",").map { |v| v == "null" ? nil : v } }
|
28
28
|
end
|
29
29
|
},
|
30
30
|
}.freeze
|
@@ -33,7 +33,7 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
|
|
33
33
|
# Get a list of filter fields for the current action.
|
34
34
|
def _get_fields
|
35
35
|
# Always return a list of strings; `@controller.get_fields` already does this.
|
36
|
-
|
36
|
+
@controller.class.filter_fields&.map(&:to_s) || @controller.get_fields
|
37
37
|
end
|
38
38
|
|
39
39
|
# Helper to find a variation of a field using a predicate. For example, there could be a field
|
@@ -62,7 +62,7 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
|
|
62
62
|
base_query = @controller.request.query_parameters.map { |field, v|
|
63
63
|
# First, if field is a simple filterable field, return early.
|
64
64
|
if field.in?(fields)
|
65
|
-
next [field, v]
|
65
|
+
next [ field, v ]
|
66
66
|
end
|
67
67
|
|
68
68
|
# First, try to parse a simple predicate and check if it is filterable.
|
@@ -81,7 +81,7 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
|
|
81
81
|
sub_fields = @controller.class.field_configuration[root_field][:sub_fields] || []
|
82
82
|
if sub_field.in?(sub_fields)
|
83
83
|
includes << root_field.to_sym
|
84
|
-
next [field, v]
|
84
|
+
next [ field, v ]
|
85
85
|
elsif pred_sub_field && pred_sub_field.in?(sub_fields)
|
86
86
|
includes << root_field.to_sym
|
87
87
|
field = pred_field
|
@@ -99,13 +99,12 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
|
|
99
99
|
if cfg.is_a?(Proc)
|
100
100
|
pred_queries << cfg.call(field, v)
|
101
101
|
else
|
102
|
-
pred_queries << {field => cfg}
|
102
|
+
pred_queries << { field => cfg }
|
103
103
|
end
|
104
104
|
|
105
105
|
next nil
|
106
106
|
}.compact.to_h.symbolize_keys
|
107
107
|
|
108
|
-
puts "GNS: #{base_query.inspect} #{pred_queries.inspect} #{includes.inspect}"
|
109
108
|
return base_query, pred_queries, includes
|
110
109
|
end
|
111
110
|
|
@@ -129,7 +128,7 @@ class RESTFramework::Filters::QueryFilter < RESTFramework::Filters::BaseFilter
|
|
129
128
|
end
|
130
129
|
end
|
131
130
|
|
132
|
-
|
131
|
+
data
|
133
132
|
end
|
134
133
|
end
|
135
134
|
|
@@ -6,7 +6,7 @@ class RESTFramework::Filters::SearchFilter < RESTFramework::Filters::BaseFilter
|
|
6
6
|
end
|
7
7
|
|
8
8
|
columns = @controller.class.get_model.column_names
|
9
|
-
|
9
|
+
@controller.get_fields.select { |f|
|
10
10
|
f.in?(RESTFramework.config.search_columns) && f.in?(columns)
|
11
11
|
}
|
12
12
|
end
|
@@ -30,12 +30,12 @@ class RESTFramework::Filters::SearchFilter < RESTFramework::Filters::BaseFilter
|
|
30
30
|
fields.map { |f|
|
31
31
|
"CAST(#{f} AS #{data_type}) #{@controller.class.search_ilike ? "ILIKE" : "LIKE"} ?"
|
32
32
|
}.join(" OR "),
|
33
|
-
*(["%#{search}%"] * fields.length),
|
33
|
+
*([ "%#{search}%" ] * fields.length),
|
34
34
|
)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
data
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -5,7 +5,7 @@ require "rails/generators"
|
|
5
5
|
# :nocov:
|
6
6
|
class RESTFrameworkCustomGeneratorControllerNamespace < String
|
7
7
|
def camelize
|
8
|
-
|
8
|
+
"RESTFramework"
|
9
9
|
end
|
10
10
|
end
|
11
11
|
# :nocov:
|
@@ -41,7 +41,7 @@ class RESTFramework::Generators::ControllerGenerator < Rails::Generators::Base
|
|
41
41
|
# Some projects may not have the inflection "REST" as an acronym, which changes this generator to
|
42
42
|
# be namespaced in `r_e_s_t_framework`, which is weird.
|
43
43
|
def self.namespace
|
44
|
-
|
44
|
+
RESTFrameworkCustomGeneratorControllerNamespace.new("rest_framework:controller")
|
45
45
|
end
|
46
46
|
|
47
47
|
def create_rest_controller_file
|
@@ -11,7 +11,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
11
11
|
title: nil,
|
12
12
|
description: nil,
|
13
13
|
version: nil,
|
14
|
-
inflect_acronyms: ["ID", "IDs", "REST", "API", "APIs"].freeze,
|
14
|
+
inflect_acronyms: [ "ID", "IDs", "REST", "API", "APIs" ].freeze,
|
15
15
|
openapi_include_children: false,
|
16
16
|
|
17
17
|
# Options related to serialization.
|
@@ -38,14 +38,14 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
38
38
|
|
39
39
|
# Default action for API root.
|
40
40
|
def root
|
41
|
-
render(api: {message: "This is the API root."})
|
41
|
+
render(api: { message: "This is the API root." })
|
42
42
|
end
|
43
43
|
|
44
44
|
module ClassMethods
|
45
45
|
# By default, this is the name of the controller class, titleized and with any custom inflection
|
46
46
|
# acronyms applied.
|
47
47
|
def get_title
|
48
|
-
|
48
|
+
self.title || RESTFramework::Utils.inflect(
|
49
49
|
self.name.demodulize.chomp("Controller").titleize(keep_id_suffix: true),
|
50
50
|
self.inflect_acronyms,
|
51
51
|
)
|
@@ -53,10 +53,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
53
53
|
|
54
54
|
# Get a label from a field/column name, titleized and inflected.
|
55
55
|
def label_for(s)
|
56
|
-
|
57
|
-
s.to_s.titleize(keep_id_suffix: true),
|
58
|
-
self.inflect_acronyms,
|
59
|
-
)
|
56
|
+
RESTFramework::Utils.inflect(s.to_s.titleize(keep_id_suffix: true), self.inflect_acronyms)
|
60
57
|
end
|
61
58
|
|
62
59
|
# Define any behavior to execute at the end of controller definition.
|
@@ -72,7 +69,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
72
69
|
# :nocov:
|
73
70
|
|
74
71
|
def openapi_response_content_types
|
75
|
-
|
72
|
+
@openapi_response_content_types ||= [
|
76
73
|
"text/html",
|
77
74
|
self.serialize_to_json ? "application/json" : nil,
|
78
75
|
self.serialize_to_xml ? "application/xml" : nil,
|
@@ -80,7 +77,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
80
77
|
end
|
81
78
|
|
82
79
|
def openapi_request_content_types
|
83
|
-
|
80
|
+
@openapi_request_content_types ||= [
|
84
81
|
"application/json",
|
85
82
|
"application/x-www-form-urlencoded",
|
86
83
|
"multipart/form-data",
|
@@ -91,7 +88,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
91
88
|
resp_cts = self.openapi_response_content_types
|
92
89
|
req_cts = self.openapi_request_content_types
|
93
90
|
|
94
|
-
|
91
|
+
routes.group_by { |r| r[:concat_path] }.map { |concat_path, routes|
|
95
92
|
[
|
96
93
|
concat_path.gsub(/:([0-9A-Za-z_-]+)/, "{\\1}"),
|
97
94
|
routes.map { |route|
|
@@ -99,28 +96,24 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
99
96
|
summary = metadata.delete(:label).presence || self.label_for(route[:action])
|
100
97
|
description = metadata.delete(:description).presence
|
101
98
|
extra_action = RESTFramework::EXTRA_ACTION_ROUTES.include?(route[:path])
|
102
|
-
error_response = {"$ref" => "#/components/responses/BadRequest"}
|
103
|
-
not_found_response = {"$ref" => "#/components/responses/NotFound"}
|
104
|
-
spec = {tags: [tag], summary: summary, description: description}.compact
|
99
|
+
error_response = { "$ref" => "#/components/responses/BadRequest" }
|
100
|
+
not_found_response = { "$ref" => "#/components/responses/NotFound" }
|
101
|
+
spec = { tags: [ tag ], summary: summary, description: description }.compact
|
105
102
|
|
106
103
|
# All routes should have a successful response.
|
107
104
|
spec[:responses] = {
|
108
|
-
200 => {content: resp_cts.map { |ct| [ct, {}] }.to_h, description: "Success"},
|
105
|
+
200 => { content: resp_cts.map { |ct| [ ct, {} ] }.to_h, description: "Success" },
|
109
106
|
}
|
110
107
|
|
111
108
|
# Builtin POST, PUT, PATCH, and DELETE should have a 400 and 404 response.
|
112
|
-
if route[:verb].in?(["POST", "PUT", "PATCH", "DELETE"]) && !extra_action
|
109
|
+
if route[:verb].in?([ "POST", "PUT", "PATCH", "DELETE" ]) && !extra_action
|
113
110
|
spec[:responses][400] = error_response
|
114
111
|
spec[:responses][404] = not_found_response
|
115
112
|
end
|
116
113
|
|
117
114
|
# All POST, PUT, PATCH should have a request body.
|
118
|
-
if route[:verb].in?(["POST", "PUT", "PATCH"])
|
119
|
-
spec[:requestBody] ||= {
|
120
|
-
content: req_cts.map { |ct|
|
121
|
-
[ct, {}]
|
122
|
-
}.to_h,
|
123
|
-
}
|
115
|
+
if route[:verb].in?([ "POST", "PUT", "PATCH" ])
|
116
|
+
spec[:requestBody] ||= { content: req_cts.map { |ct| [ ct, {} ] }.to_h }
|
124
117
|
end
|
125
118
|
|
126
119
|
# Add remaining metadata as an extension.
|
@@ -134,7 +127,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
134
127
|
name: p,
|
135
128
|
in: "path",
|
136
129
|
required: true,
|
137
|
-
schema: {type: "integer"},
|
130
|
+
schema: { type: "integer" },
|
138
131
|
}
|
139
132
|
},
|
140
133
|
},
|
@@ -146,23 +139,25 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
146
139
|
def openapi_document(request, route_group_name, routes)
|
147
140
|
server = request.base_url + request.original_fullpath.gsub(/\?.*/, "")
|
148
141
|
|
149
|
-
|
142
|
+
{
|
150
143
|
openapi: "3.1.1",
|
151
144
|
info: {
|
152
145
|
title: self.get_title,
|
153
146
|
description: self.description,
|
154
147
|
version: self.version.to_s,
|
155
148
|
}.compact,
|
156
|
-
servers: [{url: server}],
|
149
|
+
servers: [ { url: server } ],
|
157
150
|
paths: self.openapi_paths(routes, route_group_name),
|
158
|
-
tags: [{name: route_group_name, description: self.description}.compact],
|
151
|
+
tags: [ { name: route_group_name, description: self.description }.compact ],
|
159
152
|
components: {
|
160
153
|
schemas: {
|
161
154
|
"Error" => {
|
162
155
|
type: "object",
|
163
|
-
required: ["message"],
|
156
|
+
required: [ "message" ],
|
164
157
|
properties: {
|
165
|
-
message: {type: "string"
|
158
|
+
message: { type: "string" },
|
159
|
+
errors: { type: "object" },
|
160
|
+
exception: { type: "string" },
|
166
161
|
},
|
167
162
|
},
|
168
163
|
},
|
@@ -170,13 +165,19 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
170
165
|
"BadRequest": {
|
171
166
|
description: "Bad Request",
|
172
167
|
content: self.openapi_response_content_types.map { |ct|
|
173
|
-
[
|
168
|
+
[
|
169
|
+
ct,
|
170
|
+
ct == "text/html" ? {} : { schema: { "$ref" => "#/components/schemas/Error" } },
|
171
|
+
]
|
174
172
|
}.to_h,
|
175
173
|
},
|
176
174
|
"NotFound": {
|
177
175
|
description: "Not Found",
|
178
176
|
content: self.openapi_response_content_types.map { |ct|
|
179
|
-
[
|
177
|
+
[
|
178
|
+
ct,
|
179
|
+
ct == "text/html" ? {} : { schema: { "$ref" => "#/components/schemas/Error" } },
|
180
|
+
]
|
180
181
|
}.to_h,
|
181
182
|
},
|
182
183
|
},
|
@@ -249,12 +250,12 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
249
250
|
end
|
250
251
|
|
251
252
|
def get_serializer_class
|
252
|
-
|
253
|
+
self.class.serializer_class
|
253
254
|
end
|
254
255
|
|
255
256
|
# Serialize the given data using the `serializer_class`.
|
256
257
|
def serialize(data, **kwargs)
|
257
|
-
|
258
|
+
RESTFramework::Utils.wrap_ams(self.get_serializer_class).new(
|
258
259
|
data, controller: self, **kwargs
|
259
260
|
).serialize
|
260
261
|
end
|
@@ -278,7 +279,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
278
279
|
end
|
279
280
|
|
280
281
|
def route_groups
|
281
|
-
|
282
|
+
@route_groups ||= RESTFramework::Utils.get_routes(Rails.application.routes, request)
|
282
283
|
end
|
283
284
|
|
284
285
|
# Render a browsable API for `html` format, along with basic `json`/`xml` formats, and with
|
@@ -379,7 +380,7 @@ module RESTFramework::Mixins::BaseControllerMixin
|
|
379
380
|
end
|
380
381
|
end
|
381
382
|
|
382
|
-
|
383
|
+
document
|
383
384
|
end
|
384
385
|
|
385
386
|
def options
|
@@ -7,7 +7,7 @@ module RESTFramework::Mixins::BulkCreateModelMixin
|
|
7
7
|
# overloads the existing collection `POST` endpoint, so we add a special key to the OpenAPI
|
8
8
|
# metadata to indicate bulk create is supported.
|
9
9
|
def openapi_document
|
10
|
-
|
10
|
+
super.merge({ "x-rrf-bulk-create": true })
|
11
11
|
end
|
12
12
|
|
13
13
|
def create
|
@@ -17,7 +17,7 @@ module RESTFramework::Mixins::BulkCreateModelMixin
|
|
17
17
|
return render(api: serialized_records)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
super
|
21
21
|
end
|
22
22
|
|
23
23
|
# Perform the `create` call, and return the collection of (possibly) created records.
|
@@ -25,9 +25,7 @@ module RESTFramework::Mixins::BulkCreateModelMixin
|
|
25
25
|
create_data = self.get_create_params(bulk_mode: true)[:_json]
|
26
26
|
|
27
27
|
# Perform bulk create in a transaction.
|
28
|
-
|
29
|
-
next self.get_create_from.create(create_data)
|
30
|
-
end
|
28
|
+
ActiveRecord::Base.transaction { self.get_create_from.create(create_data) }
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
@@ -42,17 +40,15 @@ module RESTFramework::Mixins::BulkUpdateModelMixin
|
|
42
40
|
# Perform the `update` call and return the collection of (possibly) updated records.
|
43
41
|
def update_all!
|
44
42
|
pk = self.class.get_model.primary_key
|
45
|
-
|
43
|
+
data = if params[:_json].is_a?(Array)
|
46
44
|
self.get_create_params(bulk_mode: :update)[:_json].index_by { |r| r[pk] }
|
47
45
|
else
|
48
46
|
create_params = self.get_create_params
|
49
|
-
{create_params[pk] => create_params}
|
47
|
+
{ create_params[pk] => create_params }
|
50
48
|
end
|
51
49
|
|
52
50
|
# Perform bulk update in a transaction.
|
53
|
-
|
54
|
-
next self.get_recordset.update(update_data.keys, update_data.values)
|
55
|
-
end
|
51
|
+
ActiveRecord::Base.transaction { self.get_recordset.update(data.keys, data.values) }
|
56
52
|
end
|
57
53
|
end
|
58
54
|
|
@@ -66,8 +62,7 @@ module RESTFramework::Mixins::BulkDestroyModelMixin
|
|
66
62
|
end
|
67
63
|
|
68
64
|
render(
|
69
|
-
api: {message: "Bulk destroy requires an array of primary keys as input."},
|
70
|
-
status: 400,
|
65
|
+
api: { message: "Bulk destroy requires an array of primary keys as input." }, status: 400,
|
71
66
|
)
|
72
67
|
end
|
73
68
|
|
@@ -77,9 +72,7 @@ module RESTFramework::Mixins::BulkDestroyModelMixin
|
|
77
72
|
destroy_data = self.request.request_parameters[:_json]
|
78
73
|
|
79
74
|
# Perform bulk destroy in a transaction.
|
80
|
-
|
81
|
-
next self.get_recordset.where(pk => destroy_data).destroy_all
|
82
|
-
end
|
75
|
+
ActiveRecord::Base.transaction { self.get_recordset.where(pk => destroy_data).destroy_all }
|
83
76
|
end
|
84
77
|
end
|
85
78
|
|