rest_framework 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/VERSION +1 -0
- data/lib/rest_framework/controller_mixins/base.rb +17 -13
- data/lib/rest_framework/controller_mixins/models.rb +54 -25
- data/lib/rest_framework/errors.rb +2 -0
- data/lib/rest_framework/filters.rb +14 -6
- data/lib/rest_framework/generators/controller_generator.rb +58 -17
- data/lib/rest_framework/routers.rb +29 -39
- data/lib/rest_framework/serializers.rb +11 -13
- data/lib/rest_framework/version.rb +18 -21
- metadata +3 -3
- data/lib/rest_framework/VERSION_STAMP +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a4c53fa557df9090c749745efce556214252b76e2115df09917970e9a9c8b5e
|
4
|
+
data.tar.gz: 5c33946ae697618f726532e9b45056f2e112d3f81f6efb5c9a37ab8d9b3b002e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddfd6544b96284e871684d2f448e622631bd88631ea78ebe4170d2ff2fe4f1654901ef86a96584e3c5d0a2538bcef5d29f85152795aa689df58fc98cb05f7b3b
|
7
|
+
data.tar.gz: 1ab60515fcf543c0df574a6cf3913648736d19d559b1d9fbe55f891ce3e6926026357369580430ada33b6e294a081d8058b297bb3f146b3d17f4671b10683d55
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/rest_framework.svg)](https://badge.fury.io/rb/rest_framework)
|
4
4
|
[![Build Status](https://travis-ci.org/gregschmit/rails-rest-framework.svg?branch=master)](https://travis-ci.org/gregschmit/rails-rest-framework)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/github/gregschmit/rails-rest-framework/badge.svg?branch=master)](https://coveralls.io/github/gregschmit/rails-rest-framework?branch=master)
|
6
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/ba5df7706cb544d78555/maintainability)](https://codeclimate.com/github/gregschmit/rails-rest-framework/maintainability)
|
6
7
|
|
7
8
|
A framework for DRY RESTful APIs in Ruby on Rails.
|
8
9
|
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
@@ -79,8 +79,12 @@ module RESTFramework::BaseControllerMixin
|
|
79
79
|
|
80
80
|
protected
|
81
81
|
|
82
|
-
# Helper to get
|
83
|
-
|
82
|
+
# Helper to get the configured serializer class.
|
83
|
+
def get_serializer_class
|
84
|
+
return self.class.serializer_class
|
85
|
+
end
|
86
|
+
|
87
|
+
# Helper to get filtering backends, defaulting to no backends.
|
84
88
|
def get_filter_backends
|
85
89
|
return self.class.filter_backends || []
|
86
90
|
end
|
@@ -95,16 +99,10 @@ module RESTFramework::BaseControllerMixin
|
|
95
99
|
return data
|
96
100
|
end
|
97
101
|
|
98
|
-
# Helper to get the configured serializer class.
|
99
|
-
# @return [RESTFramework::BaseSerializer]
|
100
|
-
def get_serializer_class
|
101
|
-
return self.class.serializer_class
|
102
|
-
end
|
103
|
-
|
104
102
|
def record_invalid(e)
|
105
|
-
return api_response(
|
106
|
-
|
107
|
-
)
|
103
|
+
return api_response({
|
104
|
+
message: "Record invalid.", exception: e, errors: e.record&.errors
|
105
|
+
}, status: 400)
|
108
106
|
end
|
109
107
|
|
110
108
|
def record_not_found(e)
|
@@ -112,11 +110,15 @@ module RESTFramework::BaseControllerMixin
|
|
112
110
|
end
|
113
111
|
|
114
112
|
def record_not_saved(e)
|
115
|
-
return api_response({
|
113
|
+
return api_response({
|
114
|
+
message: "Record not saved.", exception: e, errors: e.record&.errors
|
115
|
+
}, status: 406)
|
116
116
|
end
|
117
117
|
|
118
118
|
def record_not_destroyed(e)
|
119
|
-
return api_response({
|
119
|
+
return api_response({
|
120
|
+
message: "Record not destroyed.", exception: e, errors: e.record&.errors
|
121
|
+
}, status: 406)
|
120
122
|
end
|
121
123
|
|
122
124
|
# Helper for showing routes under a controller action, used for the browsable API.
|
@@ -124,7 +126,9 @@ module RESTFramework::BaseControllerMixin
|
|
124
126
|
begin
|
125
127
|
formatter = ActionDispatch::Routing::ConsoleFormatter::Sheet
|
126
128
|
rescue NameError
|
129
|
+
# :nocov:
|
127
130
|
formatter = ActionDispatch::Routing::ConsoleFormatter
|
131
|
+
# :nocov:
|
128
132
|
end
|
129
133
|
return ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes).format(
|
130
134
|
formatter.new
|
@@ -20,6 +20,10 @@ module RESTFramework::BaseModelControllerMixin
|
|
20
20
|
fields: nil,
|
21
21
|
action_fields: nil,
|
22
22
|
|
23
|
+
# Attributes for finding records.
|
24
|
+
find_by_fields: nil,
|
25
|
+
find_by_query_param: 'find_by',
|
26
|
+
|
23
27
|
# Attributes for create/update parameters.
|
24
28
|
allowed_parameters: nil,
|
25
29
|
allowed_action_parameters: nil,
|
@@ -35,7 +39,8 @@ module RESTFramework::BaseModelControllerMixin
|
|
35
39
|
ordering_query_param: 'ordering',
|
36
40
|
|
37
41
|
# Other misc attributes.
|
38
|
-
|
42
|
+
create_from_recordset: true, # Option for `recordset.create` vs `Model.create` behavior.
|
43
|
+
filter_recordset_before_find: true, # Option to control if filtering is done before find.
|
39
44
|
}.each do |a, default|
|
40
45
|
unless base.respond_to?(a)
|
41
46
|
base.class_attribute(a)
|
@@ -60,11 +65,6 @@ module RESTFramework::BaseModelControllerMixin
|
|
60
65
|
return (action_config[action] if action) || self.class.send(generic_config_key)
|
61
66
|
end
|
62
67
|
|
63
|
-
# Get a list of parameters allowed for the current action.
|
64
|
-
def get_allowed_parameters
|
65
|
-
return _get_specific_action_config(:allowed_action_parameters, :allowed_parameters)&.map(&:to_s)
|
66
|
-
end
|
67
|
-
|
68
68
|
# Get a list of fields for the current action.
|
69
69
|
def get_fields
|
70
70
|
return (
|
@@ -74,14 +74,32 @@ module RESTFramework::BaseModelControllerMixin
|
|
74
74
|
)
|
75
75
|
end
|
76
76
|
|
77
|
+
# Get a list of find_by fields for the current action.
|
78
|
+
def get_find_by_fields
|
79
|
+
return self.class.find_by_fields&.map(&:to_s) || self.get_fields
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get a list of find_by fields for the current action.
|
83
|
+
def get_filterset_fields
|
84
|
+
return self.class.filterset_fields&.map(&:to_s) || self.get_fields
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get a list of ordering fields for the current action.
|
88
|
+
def get_ordering_fields
|
89
|
+
return self.class.ordering_fields&.map(&:to_s) || self.get_fields
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get a list of parameters allowed for the current action.
|
93
|
+
def get_allowed_parameters
|
94
|
+
return _get_specific_action_config(:allowed_action_parameters, :allowed_parameters)&.map(&:to_s)
|
95
|
+
end
|
96
|
+
|
77
97
|
# Helper to get the configured serializer class, or `NativeSerializer` as a default.
|
78
|
-
# @return [RESTFramework::BaseSerializer]
|
79
98
|
def get_serializer_class
|
80
99
|
return self.class.serializer_class || RESTFramework::NativeSerializer
|
81
100
|
end
|
82
101
|
|
83
|
-
#
|
84
|
-
# @return [RESTFramework::BaseFilter]
|
102
|
+
# Helper to get filtering backends, defaulting to using `ModelFilter` and `ModelOrderingFilter`.
|
85
103
|
def get_filter_backends
|
86
104
|
return self.class.filter_backends || [
|
87
105
|
RESTFramework::ModelFilter, RESTFramework::ModelOrderingFilter
|
@@ -94,9 +112,7 @@ module RESTFramework::BaseModelControllerMixin
|
|
94
112
|
fields = self.get_allowed_parameters || self.get_fields
|
95
113
|
|
96
114
|
# Filter the request body.
|
97
|
-
body_params = request.request_parameters.select { |p|
|
98
|
-
fields.include?(p)
|
99
|
-
}
|
115
|
+
body_params = request.request_parameters.select { |p| fields.include?(p) }
|
100
116
|
|
101
117
|
# Add query params in place of missing body params, if configured.
|
102
118
|
if self.class.accept_generic_params_as_body_params
|
@@ -113,9 +129,7 @@ module RESTFramework::BaseModelControllerMixin
|
|
113
129
|
end
|
114
130
|
|
115
131
|
# Filter fields in exclude_body_fields.
|
116
|
-
(self.class.exclude_body_fields || []).each
|
117
|
-
body_params.delete(f.to_s)
|
118
|
-
end
|
132
|
+
(self.class.exclude_body_fields || []).each { |f| body_params.delete(f.to_s) }
|
119
133
|
|
120
134
|
body_params
|
121
135
|
end
|
@@ -123,14 +137,6 @@ module RESTFramework::BaseModelControllerMixin
|
|
123
137
|
alias :get_create_params :get_body_params
|
124
138
|
alias :get_update_params :get_body_params
|
125
139
|
|
126
|
-
# Get a record by the primary key from the (non-filtered) recordset.
|
127
|
-
def get_record
|
128
|
-
if pk = params[self.get_model.primary_key]
|
129
|
-
return self.get_recordset.find(pk)
|
130
|
-
end
|
131
|
-
return nil
|
132
|
-
end
|
133
|
-
|
134
140
|
# Get the model for this controller.
|
135
141
|
def get_model(from_get_recordset: false)
|
136
142
|
return @model if instance_variable_defined?(:@model) && @model
|
@@ -164,6 +170,29 @@ module RESTFramework::BaseModelControllerMixin
|
|
164
170
|
|
165
171
|
return nil
|
166
172
|
end
|
173
|
+
|
174
|
+
# Get a single record by primary key or another column, if allowed.
|
175
|
+
def get_record
|
176
|
+
recordset = self.get_recordset
|
177
|
+
find_by_fields = self.get_find_by_fields
|
178
|
+
find_by_key = self.get_model.primary_key
|
179
|
+
|
180
|
+
# Find by another column if it's permitted.
|
181
|
+
if find_by_query_param && params[find_by_query_param].in?(find_by_fields)
|
182
|
+
find_by_key = params[find_by_query_param]
|
183
|
+
end
|
184
|
+
|
185
|
+
# Filter recordset, if configured.
|
186
|
+
if self.filter_recordset_before_find
|
187
|
+
recordset = self.get_filtered_data(recordset)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Return the record.
|
191
|
+
if find_by_value = params[:id] # Route key is always :id by Rails convention.
|
192
|
+
return self.get_recordset.find_by!(find_by_key => find_by_value)
|
193
|
+
end
|
194
|
+
return nil
|
195
|
+
end
|
167
196
|
end
|
168
197
|
|
169
198
|
|
@@ -200,8 +229,8 @@ end
|
|
200
229
|
# Mixin for creating records.
|
201
230
|
module RESTFramework::CreateModelMixin
|
202
231
|
def create
|
203
|
-
if self.get_recordset.respond_to?(:create!) &&
|
204
|
-
# Create with any properties inherited from the recordset
|
232
|
+
if self.get_recordset.respond_to?(:create!) && self.create_from_recordset
|
233
|
+
# Create with any properties inherited from the recordset.
|
205
234
|
@record = self.get_recordset.create!(self.get_create_params)
|
206
235
|
else
|
207
236
|
# Otherwise, perform a "bare" create.
|
@@ -2,6 +2,7 @@
|
|
2
2
|
class RESTFramework::Error < StandardError
|
3
3
|
end
|
4
4
|
|
5
|
+
|
5
6
|
class RESTFramework::NilPassedToAPIResponseError < RESTFramework::Error
|
6
7
|
def message
|
7
8
|
return <<~MSG.split("\n").join(' ')
|
@@ -14,6 +15,7 @@ class RESTFramework::NilPassedToAPIResponseError < RESTFramework::Error
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
18
|
+
|
17
19
|
class RESTFramework::UnserializableError < RESTFramework::Error
|
18
20
|
def initialize(object)
|
19
21
|
@object = object
|
@@ -14,7 +14,7 @@ end
|
|
14
14
|
class RESTFramework::ModelFilter < RESTFramework::BaseFilter
|
15
15
|
# Filter params for keys allowed by the current action's filterset_fields/fields config.
|
16
16
|
def _get_filter_params
|
17
|
-
fields = @controller.
|
17
|
+
fields = @controller.send(:get_filterset_fields)
|
18
18
|
return @controller.request.query_parameters.select { |p|
|
19
19
|
fields.include?(p)
|
20
20
|
}.to_h.symbolize_keys # convert from HashWithIndifferentAccess to Hash w/keys
|
@@ -36,17 +36,25 @@ end
|
|
36
36
|
class RESTFramework::ModelOrderingFilter < RESTFramework::BaseFilter
|
37
37
|
# Convert ordering string to an ordering configuration.
|
38
38
|
def _get_ordering
|
39
|
-
return nil
|
39
|
+
return nil if @controller.class.ordering_query_param.blank?
|
40
|
+
ordering_fields = @controller.send(:get_ordering_fields)
|
40
41
|
|
41
42
|
order_string = @controller.params[@controller.class.ordering_query_param]
|
42
43
|
unless order_string.blank?
|
43
|
-
|
44
|
+
ordering = {}
|
45
|
+
order_string.split(',').each do |field|
|
44
46
|
if field[0] == '-'
|
45
|
-
|
47
|
+
column = field[1..-1]
|
48
|
+
direction = :desc
|
46
49
|
else
|
47
|
-
|
50
|
+
column = field
|
51
|
+
direction = :asc
|
48
52
|
end
|
49
|
-
|
53
|
+
if column.in?(ordering_fields)
|
54
|
+
ordering[column.to_sym] = direction
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return ordering
|
50
58
|
end
|
51
59
|
|
52
60
|
return nil
|
@@ -1,26 +1,67 @@
|
|
1
1
|
require 'rails/generators'
|
2
2
|
|
3
3
|
|
4
|
+
# Some projects don't have the inflection "REST" as an acronym, so this is a helper class to prevent
|
5
|
+
# this generator from being namespaced under `r_e_s_t_framework`.
|
6
|
+
# :nocov:
|
7
|
+
class RESTFrameworkCustomGeneratorControllerNamespace < String
|
8
|
+
def camelize
|
9
|
+
return "RESTFramework"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
# :nocov:
|
13
|
+
|
14
|
+
|
4
15
|
class RESTFramework::Generators::ControllerGenerator < Rails::Generators::Base
|
16
|
+
PATH_REGEX = /^\/*([a-z0-9_\/]*[a-z0-9_])(?:[\.a-z\/]*)$/
|
17
|
+
|
5
18
|
desc <<~END
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
`
|
17
|
-
Credit card controller with URLs like /credit_card/debit.
|
18
|
-
Controller: app/controllers/credit_cards_controller.rb
|
19
|
-
Functional Test: test/functional/credit_cards_controller_test.rb
|
20
|
-
Helper: app/helpers/credit_cards_helper.rb
|
19
|
+
Description:
|
20
|
+
Generates a new REST Framework controller.
|
21
|
+
|
22
|
+
Specify the controller as a path, including the module, if needed, like:
|
23
|
+
'parent_module/controller_name'.
|
24
|
+
|
25
|
+
Example:
|
26
|
+
`rails generate rest_framework:controller user_api/groups`
|
27
|
+
|
28
|
+
Generates a controller at `app/controllers/user_api/groups_controller.rb` named
|
29
|
+
`UserApi::GroupsController`.
|
21
30
|
END
|
22
31
|
|
23
|
-
|
24
|
-
|
32
|
+
argument :path, type: :string
|
33
|
+
class_option(
|
34
|
+
:parent_class,
|
35
|
+
type: :string,
|
36
|
+
default: 'ApplicationController',
|
37
|
+
desc: "Inheritance parent",
|
38
|
+
)
|
39
|
+
class_option(
|
40
|
+
:include_base,
|
41
|
+
type: :boolean,
|
42
|
+
default: false,
|
43
|
+
desc: "Include `BaseControllerMixin`, not `ModelControllerMixin`",
|
44
|
+
)
|
45
|
+
|
46
|
+
# Some projects may not have the inflection "REST" as an acronym, which changes this generator to
|
47
|
+
# be namespaced in `r_e_s_t_framework`, which is weird.
|
48
|
+
def self.namespace
|
49
|
+
return RESTFrameworkCustomGeneratorControllerNamespace.new("rest_framework:controller")
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_rest_controller_file
|
53
|
+
unless (path_match = PATH_REGEX.match(self.path))
|
54
|
+
raise StandardError.new("Path isn't correct.")
|
55
|
+
end
|
56
|
+
|
57
|
+
cleaned_path = path_match[1]
|
58
|
+
content = <<~END
|
59
|
+
class #{cleaned_path.camelize}Controller < #{options[:parent_class]}
|
60
|
+
include RESTFramework::#{
|
61
|
+
options[:include_base] ? "BaseControllerMixin" : "ModelControllerMixin"
|
62
|
+
}
|
63
|
+
end
|
64
|
+
END
|
65
|
+
create_file("app/controllers/#{path}_controller.rb", content)
|
25
66
|
end
|
26
67
|
end
|
@@ -6,7 +6,7 @@ module ActionDispatch::Routing
|
|
6
6
|
# Internal helper to take extra_actions hash and convert to a consistent format.
|
7
7
|
protected def _parse_extra_actions(extra_actions)
|
8
8
|
return (extra_actions || {}).map do |k,v|
|
9
|
-
kwargs = {}
|
9
|
+
kwargs = {action: k}
|
10
10
|
path = k
|
11
11
|
|
12
12
|
# Convert structure to path/methods/kwargs.
|
@@ -72,6 +72,16 @@ module ActionDispatch::Routing
|
|
72
72
|
return controller
|
73
73
|
end
|
74
74
|
|
75
|
+
# Interal interface for routing extra actions.
|
76
|
+
protected def _route_extra_actions(actions, &block)
|
77
|
+
actions.each do |action_config|
|
78
|
+
action_config[:methods].each do |m|
|
79
|
+
public_send(m, action_config[:path], **action_config[:kwargs])
|
80
|
+
end
|
81
|
+
yield if block_given?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
75
85
|
# Internal core implementation of the `rest_resource(s)` router, both singular and plural.
|
76
86
|
# @param default_singular [Boolean] the default plurality of the resource if the plurality is
|
77
87
|
# not otherwise defined by the controller
|
@@ -89,9 +99,11 @@ module ActionDispatch::Routing
|
|
89
99
|
kwargs[:controller] = name unless kwargs[:controller]
|
90
100
|
|
91
101
|
# determine plural/singular resource
|
92
|
-
|
102
|
+
force_singular = kwargs.delete(:force_singular)
|
103
|
+
force_plural = kwargs.delete(:force_plural)
|
104
|
+
if force_singular
|
93
105
|
singular = true
|
94
|
-
elsif
|
106
|
+
elsif force_plural
|
95
107
|
singular = false
|
96
108
|
elsif !controller_class.singleton_controller.nil?
|
97
109
|
singular = controller_class.singleton_controller
|
@@ -100,28 +112,20 @@ module ActionDispatch::Routing
|
|
100
112
|
end
|
101
113
|
resource_method = singular ? :resource : :resources
|
102
114
|
|
103
|
-
#
|
115
|
+
# Call either `resource` or `resources`, passing appropriate modifiers.
|
104
116
|
skip_undefined = kwargs.delete(:skip_undefined) || true
|
105
117
|
skip = controller_class.get_skip_actions(skip_undefined: skip_undefined)
|
106
118
|
public_send(resource_method, name, except: skip, **kwargs) do
|
107
119
|
if controller_class.respond_to?(:extra_member_actions)
|
108
120
|
member do
|
109
121
|
actions = self._parse_extra_actions(controller_class.extra_member_actions)
|
110
|
-
actions
|
111
|
-
action_config[:methods].each do |m|
|
112
|
-
public_send(m, action_config[:path], **action_config[:kwargs])
|
113
|
-
end
|
114
|
-
end
|
122
|
+
_route_extra_actions(actions)
|
115
123
|
end
|
116
124
|
end
|
117
125
|
|
118
126
|
collection do
|
119
127
|
actions = self._parse_extra_actions(controller_class.extra_actions)
|
120
|
-
actions
|
121
|
-
action_config[:methods].each do |m|
|
122
|
-
public_send(m, action_config[:path], **action_config[:kwargs])
|
123
|
-
end
|
124
|
-
end
|
128
|
+
_route_extra_actions(actions)
|
125
129
|
end
|
126
130
|
|
127
131
|
yield if block_given?
|
@@ -145,6 +149,7 @@ module ActionDispatch::Routing
|
|
145
149
|
# Route a controller without the default resourceful paths.
|
146
150
|
def rest_route(name=nil, **kwargs, &block)
|
147
151
|
controller = kwargs.delete(:controller) || name
|
152
|
+
route_root_to = kwargs.delete(:route_root_to)
|
148
153
|
if controller.is_a?(Class)
|
149
154
|
controller_class = controller
|
150
155
|
else
|
@@ -157,42 +162,27 @@ module ActionDispatch::Routing
|
|
157
162
|
# Route actions using the resourceful router, but skip all builtin actions.
|
158
163
|
actions = self._parse_extra_actions(controller_class.extra_actions)
|
159
164
|
public_send(:resource, name, only: [], **kwargs) do
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
end
|
164
|
-
yield if block_given?
|
165
|
+
# Route a root for this resource.
|
166
|
+
if route_root_to
|
167
|
+
get '', action: route_root_to
|
165
168
|
end
|
169
|
+
|
170
|
+
_route_extra_actions(actions, &block)
|
166
171
|
end
|
167
172
|
end
|
168
173
|
|
169
174
|
# Route a controller's `#root` to '/' in the current scope/namespace, along with other actions.
|
170
|
-
# @param name [Symbol] the snake_case name of the controller
|
171
175
|
def rest_root(name=nil, **kwargs, &block)
|
172
176
|
# By default, use RootController#root.
|
173
177
|
root_action = kwargs.delete(:action) || :root
|
174
178
|
controller = kwargs.delete(:controller) || name || :root
|
175
179
|
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
controller_class = self._get_controller_class(controller, pluralize: false)
|
181
|
-
actions = self._parse_extra_actions(controller_class.extra_actions)
|
182
|
-
actions.each do |action_config|
|
183
|
-
# Add :action unless kwargs defines it.
|
184
|
-
unless action_config[:kwargs].key?(:action)
|
185
|
-
action_config[:kwargs][:action] = action_config[:path]
|
186
|
-
end
|
180
|
+
# Remove path if name is nil (routing to the root of current namespace).
|
181
|
+
unless name
|
182
|
+
kwargs[:path] = ''
|
183
|
+
end
|
187
184
|
|
188
|
-
|
189
|
-
public_send(
|
190
|
-
m,
|
191
|
-
File.join(name.to_s, action_config[:path].to_s),
|
192
|
-
controller: controller,
|
193
|
-
**action_config[:kwargs],
|
194
|
-
)
|
195
|
-
end
|
185
|
+
return rest_route(controller, route_root_to: root_action, **kwargs) do
|
196
186
|
yield if block_given?
|
197
187
|
end
|
198
188
|
end
|
@@ -3,6 +3,10 @@ class RESTFramework::BaseSerializer
|
|
3
3
|
@object = object
|
4
4
|
@controller = controller
|
5
5
|
end
|
6
|
+
|
7
|
+
def serialize
|
8
|
+
raise NotImplementedError
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
12
|
|
@@ -27,7 +31,9 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
|
|
27
31
|
# Determine model either explicitly, or by inspecting @object or @controller.
|
28
32
|
@model = model
|
29
33
|
@model ||= @object.class if @object.is_a?(ActiveRecord::Base)
|
30
|
-
@model ||= @object[0].class if
|
34
|
+
@model ||= @object[0].class if (
|
35
|
+
@many && @object.is_a?(Enumerable) && @object.is_a?(ActiveRecord::Base)
|
36
|
+
)
|
31
37
|
@model ||= @controller.send(:get_model) if @controller
|
32
38
|
end
|
33
39
|
|
@@ -115,29 +121,21 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
|
|
115
121
|
|
116
122
|
# Allow a serializer instance to be used as a hash directly in a nested serializer config.
|
117
123
|
def [](key)
|
118
|
-
|
119
|
-
@_nested_config = self.get_serializer_config
|
120
|
-
end
|
124
|
+
@_nested_config ||= self.get_serializer_config
|
121
125
|
return @_nested_config[key]
|
122
126
|
end
|
123
127
|
def []=(key, value)
|
124
|
-
|
125
|
-
@_nested_config = self.get_serializer_config
|
126
|
-
end
|
128
|
+
@_nested_config ||= self.get_serializer_config
|
127
129
|
return @_nested_config[key] = value
|
128
130
|
end
|
129
131
|
|
130
132
|
# Allow a serializer class to be used as a hash directly in a nested serializer config.
|
131
133
|
def self.[](key)
|
132
|
-
|
133
|
-
@_nested_config = self.new.get_serializer_config
|
134
|
-
end
|
134
|
+
@_nested_config ||= self.new.get_serializer_config
|
135
135
|
return @_nested_config[key]
|
136
136
|
end
|
137
137
|
def self.[]=(key, value)
|
138
|
-
|
139
|
-
@_nested_config = self.new.get_serializer_config
|
140
|
-
end
|
138
|
+
@_nested_config ||= self.new.get_serializer_config
|
141
139
|
return @_nested_config[key] = value
|
142
140
|
end
|
143
141
|
end
|
@@ -1,35 +1,32 @@
|
|
1
|
+
# Do not use Rails-specific helper methods here (e.g., `blank?`) so the module can run standalone.
|
1
2
|
module RESTFramework
|
2
3
|
module Version
|
3
|
-
|
4
|
+
VERSION_FILEPATH = File.expand_path("../../VERSION", __dir__)
|
4
5
|
|
5
6
|
def self.get_version(skip_git: false)
|
6
|
-
# Return cached @_version, if available.
|
7
|
-
return @_version if @_version
|
8
|
-
|
9
7
|
# First, attempt to get the version from git.
|
10
8
|
unless skip_git
|
11
|
-
|
12
|
-
|
13
|
-
raise "blank version" if version.nil? || version.match(/^\w*$/)
|
14
|
-
# Check for local changes.
|
15
|
-
changes = `git status --porcelain 2>/dev/null`
|
16
|
-
version << '.localchanges' if changes.strip.length > 0
|
17
|
-
return version
|
18
|
-
rescue
|
19
|
-
end
|
9
|
+
version = `git describe --dirty --broken 2>/dev/null`&.strip
|
10
|
+
return version unless !version || version.empty?
|
20
11
|
end
|
21
12
|
|
22
|
-
# Git failed, so try to find a
|
13
|
+
# Git failed or was skipped, so try to find a VERSION file.
|
23
14
|
begin
|
24
|
-
version = File.read(
|
25
|
-
unless version
|
26
|
-
|
27
|
-
end
|
28
|
-
rescue
|
15
|
+
version = File.read(VERSION_FILEPATH)&.strip
|
16
|
+
return version unless !version || version.blank?
|
17
|
+
rescue SystemCallError
|
29
18
|
end
|
30
19
|
|
31
|
-
# No
|
32
|
-
return '
|
20
|
+
# No VERSION file, so version is unknown.
|
21
|
+
return 'unknown'
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.stamp_version
|
25
|
+
File.write(VERSION_FILEPATH, RESTFramework::VERSION)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.unstamp_version
|
29
|
+
File.delete(VERSION_FILEPATH) if File.exist?(VERSION_FILEPATH)
|
33
30
|
end
|
34
31
|
end
|
35
32
|
|
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.
|
4
|
+
version: 0.3.0
|
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: 2021-
|
11
|
+
date: 2021-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -33,12 +33,12 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- LICENSE
|
35
35
|
- README.md
|
36
|
+
- VERSION
|
36
37
|
- app/views/layouts/rest_framework.html.erb
|
37
38
|
- app/views/rest_framework/_head.html.erb
|
38
39
|
- app/views/rest_framework/_routes.html.erb
|
39
40
|
- app/views/rest_framework/default.html.erb
|
40
41
|
- lib/rest_framework.rb
|
41
|
-
- lib/rest_framework/VERSION_STAMP
|
42
42
|
- lib/rest_framework/controller_mixins.rb
|
43
43
|
- lib/rest_framework/controller_mixins/base.rb
|
44
44
|
- lib/rest_framework/controller_mixins/models.rb
|
@@ -1 +0,0 @@
|
|
1
|
-
0.2.0
|