rest_framework 0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +46 -0
- data/lib/rest_framework.rb +6 -0
- data/lib/rest_framework/VERSION_STAMP +1 -0
- data/lib/rest_framework/controllers.rb +2 -0
- data/lib/rest_framework/controllers/base.rb +66 -0
- data/lib/rest_framework/controllers/models.rb +222 -0
- data/lib/rest_framework/routers.rb +132 -0
- data/lib/rest_framework/version.rb +35 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c71a3fea7904490cd834aff65231d4a18804e8cd487a07314e475a73d9a6500e
|
4
|
+
data.tar.gz: bde5421c92b4c960bc9b09b369a36b2d4df463b0722490c35cbaf00cdb6b6a66
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 21db95368e8223a1b086e63b9724eb7cb35cb5eb42db9eedb5eca557662be24363f225ab69fb98d2996152c69d58218a5156fdaba1345330660c974313b3f912
|
7
|
+
data.tar.gz: 2f32d14d77eb8f60b29019afd81f6b926e2bd97268b2cd6d4828698adf4b66debea2959f00403913a6e74a970f858d960a4d3c9268a1f6fcccd9549c1aca992e
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Gregory N. Schmit
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# REST Framework
|
2
|
+
|
3
|
+
REST Framework helps you build awesome APIs in Ruby on Rails.
|
4
|
+
|
5
|
+
**The Problem**: Building controllers for APIs usually involves writing a lot of redundant CRUD
|
6
|
+
logic, and routing them can be obnoxious.
|
7
|
+
|
8
|
+
**The Solution**: This gem handles the common logic so you can focus on the parts of your API which
|
9
|
+
make it unique.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'rest_framework'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle install
|
22
|
+
|
23
|
+
Or install it yourself with:
|
24
|
+
|
25
|
+
$ gem install rest_framework
|
26
|
+
|
27
|
+
## Development/Testing
|
28
|
+
|
29
|
+
After you clone the repository, cd'ing into the directory should create a new gemset if you are
|
30
|
+
using RVM. Then run `bundle install` to install the appropriate gems.
|
31
|
+
|
32
|
+
To run the full test suite:
|
33
|
+
|
34
|
+
$ rake test
|
35
|
+
|
36
|
+
To run unit tests:
|
37
|
+
|
38
|
+
$ rake test:unit
|
39
|
+
|
40
|
+
To run integration tests on a sample app:
|
41
|
+
|
42
|
+
$ rake test:app
|
43
|
+
|
44
|
+
To run that sample app live:
|
45
|
+
|
46
|
+
$ rake test:app:run
|
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module RESTFramework
|
2
|
+
|
3
|
+
module ClassMethodHelpers
|
4
|
+
def _restframework_attr_reader(property, default: nil)
|
5
|
+
method = <<~RUBY
|
6
|
+
def #{property}
|
7
|
+
return _restframework_try_class_level_variable_get(
|
8
|
+
#{property.inspect},
|
9
|
+
default: #{default.inspect},
|
10
|
+
)
|
11
|
+
end
|
12
|
+
RUBY
|
13
|
+
self.module_eval(method)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module BaseControllerMixin
|
18
|
+
# Default action for API root.
|
19
|
+
# TODO: use api_response and show sub-routes.
|
20
|
+
def root
|
21
|
+
render inline: "This is the root of your awesome API!"
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
extend ClassMethodHelpers
|
28
|
+
|
29
|
+
# Interface for getting class-level instance/class variables.
|
30
|
+
private def _restframework_try_class_level_variable_get(name, default: nil)
|
31
|
+
begin
|
32
|
+
v = instance_variable_get("@#{name}")
|
33
|
+
return v unless v.nil?
|
34
|
+
rescue NameError
|
35
|
+
end
|
36
|
+
begin
|
37
|
+
v = class_variable_get("@@#{name}")
|
38
|
+
return v unless v.nil?
|
39
|
+
rescue NameError
|
40
|
+
end
|
41
|
+
return default
|
42
|
+
end
|
43
|
+
|
44
|
+
# Interface for registering exceptions handlers.
|
45
|
+
# private def _restframework_register_exception_handlers
|
46
|
+
# rescue_from
|
47
|
+
# end
|
48
|
+
|
49
|
+
_restframework_attr_reader(:extra_actions, default: {})
|
50
|
+
_restframework_attr_reader(:skip_actions, default: [])
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.included(base)
|
54
|
+
base.extend ClassMethods
|
55
|
+
end
|
56
|
+
|
57
|
+
# Helper alias for `respond_to`/`render`, and replace nil responses with blank ones.
|
58
|
+
def api_response(value, **kwargs)
|
59
|
+
respond_to do |format|
|
60
|
+
format.html
|
61
|
+
format.json { render json: value || '', **kwargs }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module RESTFramework
|
4
|
+
|
5
|
+
module BaseModelControllerMixin
|
6
|
+
include BaseControllerMixin
|
7
|
+
|
8
|
+
# By default (and for now), we will just use `as_json`, but we should consider supporting:
|
9
|
+
# active_model_serializers (problem:
|
10
|
+
# https://github.com/rails-api/active_model_serializers#whats-happening-to-ams)
|
11
|
+
# fast_jsonapi (really good and fast serializers)
|
12
|
+
#@serializer
|
13
|
+
#@list_serializer
|
14
|
+
#@show_serializer
|
15
|
+
#@create_serializer
|
16
|
+
#@update_serializer
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
extend ClassMethodHelpers
|
20
|
+
include BaseControllerMixin::ClassMethods
|
21
|
+
|
22
|
+
_restframework_attr_reader(:model)
|
23
|
+
_restframework_attr_reader(:recordset)
|
24
|
+
_restframework_attr_reader(:singleton_controller)
|
25
|
+
|
26
|
+
_restframework_attr_reader(:fields)
|
27
|
+
_restframework_attr_reader(:list_fields)
|
28
|
+
_restframework_attr_reader(:show_fields)
|
29
|
+
_restframework_attr_reader(:create_fields)
|
30
|
+
_restframework_attr_reader(:update_fields)
|
31
|
+
|
32
|
+
_restframework_attr_reader(:extra_member_actions, default: {})
|
33
|
+
|
34
|
+
# For model-based mixins, `@extra_collection_actions` is synonymous with `@extra_actions`.
|
35
|
+
def extra_actions
|
36
|
+
return (
|
37
|
+
_restframework_try_class_level_variable_get(:extra_collection_actions) ||
|
38
|
+
_restframework_try_class_level_variable_get(:extra_actions, default: {})
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.included(base)
|
44
|
+
base.extend ClassMethods
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# Get a list of fields for the current action.
|
50
|
+
def get_fields
|
51
|
+
return @fields if @fields
|
52
|
+
|
53
|
+
# index action should use list_fields
|
54
|
+
name = (action_name == 'index') ? 'list' : action_name
|
55
|
+
|
56
|
+
begin
|
57
|
+
@fields = self.class.send("#{name}_fields")
|
58
|
+
rescue NameError
|
59
|
+
end
|
60
|
+
@fields ||= self.class.fields || []
|
61
|
+
|
62
|
+
return @fields
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get a configuration passable to `as_json` for the model.
|
66
|
+
def get_model_serializer_config
|
67
|
+
fields = self.get_fields
|
68
|
+
unless fields.blank?
|
69
|
+
columns, methods = fields.partition { |f| f.to_s.in?(self.get_model.column_names) }
|
70
|
+
return {only: columns, methods: methods}
|
71
|
+
end
|
72
|
+
return {}
|
73
|
+
end
|
74
|
+
|
75
|
+
# Filter the request body for keys allowed by the current action's field config.
|
76
|
+
def _get_field_values_from_request_body
|
77
|
+
return @_get_field_values_from_request_body ||= (request.request_parameters.select { |p|
|
78
|
+
self.get_fields.include?(p.to_sym) || self.get_fields.include?(p.to_s)
|
79
|
+
})
|
80
|
+
end
|
81
|
+
alias :get_create_params :_get_field_values_from_request_body
|
82
|
+
alias :get_update_params :_get_field_values_from_request_body
|
83
|
+
|
84
|
+
# Filter params for keys allowed by the current action's field config.
|
85
|
+
def _get_field_values_from_params
|
86
|
+
return @_get_field_values_from_params ||= params.permit(*self.get_fields)
|
87
|
+
end
|
88
|
+
alias :get_lookup_params :_get_field_values_from_params
|
89
|
+
alias :get_filter_params :_get_field_values_from_params
|
90
|
+
|
91
|
+
# Get the recordset, filtered by the filter params.
|
92
|
+
def get_filtered_recordset
|
93
|
+
filter_params = self.get_filter_params
|
94
|
+
unless filter_params.blank?
|
95
|
+
return self.get_recordset.where(**self.get_filter_params)
|
96
|
+
end
|
97
|
+
return self.get_recordset
|
98
|
+
end
|
99
|
+
|
100
|
+
# Get a record by `id` or return a single record if recordset is filtered down to a single record.
|
101
|
+
def get_record
|
102
|
+
records = self.get_filtered_recordset
|
103
|
+
if params['id'] # direct lookup
|
104
|
+
return records.find(params['id'])
|
105
|
+
elsif records.length == 1
|
106
|
+
return records[0]
|
107
|
+
end
|
108
|
+
return nil
|
109
|
+
end
|
110
|
+
|
111
|
+
# Internal interface for get_model, protecting against infinite recursion with get_recordset.
|
112
|
+
private def _get_model(from_internal_get_recordset: false)
|
113
|
+
return @model if @model
|
114
|
+
return self.class.model if self.class.model
|
115
|
+
unless from_get_recordset # prevent infinite recursion
|
116
|
+
recordset = self._get_recordset(from_internal_get_model: true)
|
117
|
+
return (@model = recordset.klass) if recordset
|
118
|
+
end
|
119
|
+
begin
|
120
|
+
return (@model = self.class.name.demodulize.match(/(.*)Controller/)[1].singularize.constantize)
|
121
|
+
rescue NameError
|
122
|
+
end
|
123
|
+
return nil
|
124
|
+
end
|
125
|
+
|
126
|
+
# Internal interface for get_recordset, protecting against infinite recursion with get_model.
|
127
|
+
private def _get_recordset(from_internal_get_model: false)
|
128
|
+
return @recordset if @recordset
|
129
|
+
return self.class.recordset if self.class.recordset
|
130
|
+
unless from_get_model # prevent infinite recursion
|
131
|
+
model = self._get_model(from_internal_get_recordset: true)
|
132
|
+
return (@recordset = model.all) if model
|
133
|
+
end
|
134
|
+
return nil
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get the model for this controller.
|
138
|
+
def get_model
|
139
|
+
return _get_model
|
140
|
+
end
|
141
|
+
|
142
|
+
# Get the base set of records this controller has access to.
|
143
|
+
def get_recordset
|
144
|
+
return _get_recordset
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
module ListModelMixin
|
149
|
+
# TODO: pagination classes like Django
|
150
|
+
def index
|
151
|
+
@records = self.get_filtered_recordset
|
152
|
+
api_response(@records, **self.get_model_serializer_config)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
module ShowModelMixin
|
157
|
+
def show
|
158
|
+
@record = self.get_record
|
159
|
+
api_response(@record, **self.get_model_serializer_config)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
module CreateModelMixin
|
164
|
+
def create
|
165
|
+
begin
|
166
|
+
@record = self.get_model.create!(self.get_create_params)
|
167
|
+
rescue ActiveRecord::RecordInvalid => e
|
168
|
+
api_response(e.record.messages, status: 400)
|
169
|
+
end
|
170
|
+
api_response(@record, **self.get_model_serializer_config)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
module UpdateModelMixin
|
175
|
+
def update
|
176
|
+
@record = self.get_record
|
177
|
+
if @record
|
178
|
+
@record.attributes(self.get_update_params)
|
179
|
+
@record.save!
|
180
|
+
api_response(@record, **self.get_model_serializer_config)
|
181
|
+
else
|
182
|
+
api_response({detail: "Record not found."}, status: 404)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
module DestroyModelMixin
|
188
|
+
def destroy
|
189
|
+
@record = self.get_record
|
190
|
+
if @record
|
191
|
+
@record.destroy!
|
192
|
+
api_response('')
|
193
|
+
else
|
194
|
+
api_response({detail: "Method 'DELETE' not allowed."}, status: 405)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
module ReadOnlyModelControllerMixin
|
200
|
+
include BaseModelControllerMixin
|
201
|
+
def self.included(base)
|
202
|
+
base.extend BaseModelControllerMixin::ClassMethods
|
203
|
+
end
|
204
|
+
|
205
|
+
include ListModelMixin
|
206
|
+
include ShowModelMixin
|
207
|
+
end
|
208
|
+
|
209
|
+
module ModelControllerMixin
|
210
|
+
include BaseModelControllerMixin
|
211
|
+
def self.included(base)
|
212
|
+
base.extend BaseModelControllerMixin::ClassMethods
|
213
|
+
end
|
214
|
+
|
215
|
+
include ListModelMixin
|
216
|
+
include ShowModelMixin
|
217
|
+
include CreateModelMixin
|
218
|
+
include UpdateModelMixin
|
219
|
+
include DestroyModelMixin
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'action_dispatch/routing/mapper'
|
3
|
+
|
4
|
+
module ActionDispatch::Routing
|
5
|
+
class Mapper
|
6
|
+
# Private interface to get the controller class from the name and current scope.
|
7
|
+
protected def _get_controller_class(name, pluralize: true, fallback_reverse_pluralization: true)
|
8
|
+
# get class name
|
9
|
+
name = name.to_s.camelize # camelize to leave plural names plural
|
10
|
+
name = name.pluralize if pluralize
|
11
|
+
if name == name.pluralize
|
12
|
+
name_reverse = name.singularize
|
13
|
+
else
|
14
|
+
name_reverse = name.pluralize
|
15
|
+
end
|
16
|
+
name += "Controller"
|
17
|
+
name_reverse += "Controller"
|
18
|
+
|
19
|
+
# get scope for the class
|
20
|
+
if @scope[:module]
|
21
|
+
mod = @scope[:module].to_s.classify.constantize
|
22
|
+
else
|
23
|
+
mod = Object
|
24
|
+
end
|
25
|
+
|
26
|
+
# convert class name to class
|
27
|
+
begin
|
28
|
+
controller = mod.const_get(name, false)
|
29
|
+
rescue NameError
|
30
|
+
if fallback_reverse_pluralization
|
31
|
+
controller = mod.const_get(name_reverse, false)
|
32
|
+
else
|
33
|
+
raise
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
return controller
|
38
|
+
end
|
39
|
+
|
40
|
+
# Core implementation of the `rest_resource(s)` router, both singular and plural.
|
41
|
+
# @param default_singular [Boolean] the default plurality of the resource if the plurality is
|
42
|
+
# not otherwise defined by the controller
|
43
|
+
# @param name [Symbol] the resource name, from which path and controller are deduced by default
|
44
|
+
protected def _rest_resources(default_singular, name, **kwargs, &block)
|
45
|
+
controller = kwargs[:controller] || name
|
46
|
+
if controller.is_a?(Class)
|
47
|
+
controller_class = controller
|
48
|
+
else
|
49
|
+
controller_class = _get_controller_class(controller, pluralize: !default_singular)
|
50
|
+
end
|
51
|
+
|
52
|
+
# set controller if it's not explicitly set
|
53
|
+
unless kwargs[:controller]
|
54
|
+
kwargs[:controller] = name
|
55
|
+
end
|
56
|
+
|
57
|
+
# determine plural/singular resource
|
58
|
+
if kwargs.delete(:force_singular)
|
59
|
+
singular = true
|
60
|
+
elsif kwargs.delete(:force_plural)
|
61
|
+
singular = false
|
62
|
+
elsif !controller_class.singleton_controller.nil?
|
63
|
+
singular = controller_class.singleton_controller
|
64
|
+
else
|
65
|
+
singular = default_singular
|
66
|
+
end
|
67
|
+
resource_method = singular ? :resource : :resources
|
68
|
+
|
69
|
+
# call either `resource` or `resources`, passing appropriate modifiers
|
70
|
+
public_send(resource_method, name, except: controller_class.skip_actions, **kwargs) do
|
71
|
+
if controller_class.respond_to?(:extra_member_actions)
|
72
|
+
member do
|
73
|
+
controller_class.extra_member_actions.each do |action, methods|
|
74
|
+
methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
|
75
|
+
methods.each do |m|
|
76
|
+
public_send(m, action)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
collection do
|
83
|
+
controller_class.extra_actions.each do |action, methods|
|
84
|
+
methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
|
85
|
+
methods.each do |m|
|
86
|
+
public_send(m, action)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
yield if block_given?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Public interface for creating singular RESTful resource routes.
|
96
|
+
def rest_resource(*names, **kwargs, &block)
|
97
|
+
names.each do |n|
|
98
|
+
self._rest_resources(true, n, **kwargs, &block)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Public interface for creating plural RESTful resource routes.
|
103
|
+
def rest_resources(*names, **kwargs, &block)
|
104
|
+
names.each do |n|
|
105
|
+
self._rest_resources(false, n, **kwargs, &block)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Route a controller's `#root` to '/' in the current scope/namespace, along with other actions.
|
110
|
+
# @param label [Symbol] the snake_case name of the controller
|
111
|
+
def rest_root(path=nil, **kwargs, &block)
|
112
|
+
# by default, use RootController#root
|
113
|
+
root_action = kwargs.delete(:action) || :root
|
114
|
+
controller = kwargs.delete(:controller) || path || :root
|
115
|
+
path = path.to_s
|
116
|
+
|
117
|
+
# route the root
|
118
|
+
get path, controller: controller, action: root_action
|
119
|
+
|
120
|
+
# route any additional actions
|
121
|
+
controller_class = self._get_controller_class(controller, pluralize: false)
|
122
|
+
controller_class.extra_actions.each do |action, methods|
|
123
|
+
methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
|
124
|
+
methods.each do |m|
|
125
|
+
public_send(m, File.join(path, action.to_s), controller: controller, action: action)
|
126
|
+
end
|
127
|
+
yield if block_given?
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RESTFramework
|
2
|
+
module Version
|
3
|
+
@_version = nil
|
4
|
+
|
5
|
+
def self.get_version
|
6
|
+
# Return cached @_version, if available.
|
7
|
+
return @_version if @_version
|
8
|
+
|
9
|
+
# First, attempt to get the version from git.
|
10
|
+
begin
|
11
|
+
version = `git describe`.strip
|
12
|
+
raise "blank version" if version.nil? || version.match(/^\w*$/)
|
13
|
+
# Check for local changes.
|
14
|
+
changes = `git status --porcelain`
|
15
|
+
version << '.localchanges' if changes.strip.length > 0
|
16
|
+
return version
|
17
|
+
rescue
|
18
|
+
end
|
19
|
+
|
20
|
+
# Git failed, so try to find a VERSION_STAMP.
|
21
|
+
begin
|
22
|
+
version = File.read(File.expand_path("VERSION_STAMP", __dir__))
|
23
|
+
unless version.nil? || version.match(/^\w*$/)
|
24
|
+
return (@_version = version) # cache VERSION_STAMP content in @_version
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
end
|
28
|
+
|
29
|
+
# No VERSION_STAMP, so version is unknown.
|
30
|
+
return '0.unknown'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
VERSION = Version.get_version()
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rest_framework
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gregory N. Schmit
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-09-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
description: A framework for DRY RESTful APIs in Ruby on Rails.
|
28
|
+
email:
|
29
|
+
- schmitgreg@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- lib/rest_framework.rb
|
37
|
+
- lib/rest_framework/VERSION_STAMP
|
38
|
+
- lib/rest_framework/controllers.rb
|
39
|
+
- lib/rest_framework/controllers/base.rb
|
40
|
+
- lib/rest_framework/controllers/models.rb
|
41
|
+
- lib/rest_framework/routers.rb
|
42
|
+
- lib/rest_framework/version.rb
|
43
|
+
homepage: https://github.com/gregschmit/rails-rest-framework
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata:
|
47
|
+
homepage_uri: https://github.com/gregschmit/rails-rest-framework
|
48
|
+
source_code_uri: https://github.com/gregschmit/rails-rest-framework
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 2.3.0
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubygems_version: 3.0.8
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: A framework for DRY RESTful APIs in Ruby on Rails.
|
68
|
+
test_files: []
|