rest_framework 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|