rest_rails 0.1.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/MIT-LICENSE +20 -0
- data/README.md +16 -0
- data/Rakefile +32 -0
- data/app/assets/config/rest_rails_manifest.js +1 -0
- data/app/assets/stylesheets/rest_rails/application.css +1 -0
- data/app/controllers/rest_rails/application_controller.rb +36 -0
- data/app/controllers/rest_rails/data_controller.rb +180 -0
- data/app/helpers/rest_rails/application_helper.rb +59 -0
- data/config/routes.rb +15 -0
- data/lib/rest_rails/engine.rb +12 -0
- data/lib/rest_rails/error.rb +4 -0
- data/lib/rest_rails/version.rb +3 -0
- data/lib/rest_rails.rb +12 -0
- data/lib/tasks/rest_rails_tasks.rake +4 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7fbfcc915cc6cd4b87ab45165c5ae83644327250414b2695ac6792afcb938903
|
4
|
+
data.tar.gz: 45955c0053d64c977ed9f4460681e2972503ca9c84ae739eb6b173553898a447
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 21952e44ba928b34a0232bd4e49a6dd38e60adebbc9f8c590d4fa8e94f2eed6f92a0064d15d2112e65c9b542232d5ce7e9cda3736aaa4a12ea39817b6d61725b
|
7
|
+
data.tar.gz: 8d6968c5743e3002095fccef95bdaf48b53032320c3a2349b4bc1e8265b5c2095c1a911f4d855095da55d17609765ae65e4dc4485efdc4f01d17660f7c502c44
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2019 Sergio Rivas
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# RestRails
|
2
|
+
Rails Plugin for quick intelligent API Creation by Tuitu Technology Solutions
|
3
|
+
|
4
|
+
## How To Use
|
5
|
+
|
6
|
+
Add To Gemfile: `gem 'rest_rails'`
|
7
|
+
|
8
|
+
Then place in the bottom of Rails Routes:
|
9
|
+
|
10
|
+
```
|
11
|
+
mount RestRails::Engine => '/api/v1', as: 'rest'
|
12
|
+
```
|
13
|
+
## TODO
|
14
|
+
|
15
|
+
- Add Documentation
|
16
|
+
- Add Test Suite
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'RestRails'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
// no need for js
|
@@ -0,0 +1 @@
|
|
1
|
+
/* no need for CSS*/
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RestRails
|
2
|
+
class ApplicationController < ActionController::API
|
3
|
+
before_action :authenticate_user!, if: -> {self.respond_to?("authenticate_user!") && RestRails.authenticatable}
|
4
|
+
before_action :set_locale
|
5
|
+
|
6
|
+
rescue_from StandardError, with: :internal_server_error
|
7
|
+
rescue_from RestRails::Error, with: :internal_server_error
|
8
|
+
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def not_found(exception)
|
13
|
+
if RestRails.debug
|
14
|
+
raise exception
|
15
|
+
else
|
16
|
+
render json: { error: exception.message }, status: :not_found
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def internal_server_error(exception)
|
21
|
+
if RestRails.debug
|
22
|
+
raise exception
|
23
|
+
elsif Rails.env.development?
|
24
|
+
response = { type: exception.class.to_s, error: exception.message }
|
25
|
+
else
|
26
|
+
response = { error: "Internal Server Error" }
|
27
|
+
end
|
28
|
+
render json: response, status: :internal_server_error
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_locale
|
32
|
+
I18n.locale = params[:locale] || session[:locale] || I18n.default_locale
|
33
|
+
session[:locale] = I18n.locale
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'json'
|
2
|
+
module RestRails
|
3
|
+
class DataController < RestRails::ApplicationController
|
4
|
+
include RestRails::ApplicationHelper
|
5
|
+
before_action :set_model, only: [:index, :show, :create, :update, :destroy, :fetch_column, :attach, :unattach]
|
6
|
+
before_action :set_object, only: [:show, :update, :destroy, :fetch_column, :attach, :unattach]
|
7
|
+
|
8
|
+
def index
|
9
|
+
p_hash = index_params.to_h
|
10
|
+
|
11
|
+
@objects = @model.all.in_groups_of(100) if p_hash.blank?
|
12
|
+
@objects = @model.where(p_hash).in_groups_of(100) if p_hash.present?
|
13
|
+
|
14
|
+
if params[:page].blank? || (params[:page].to_i < 1)
|
15
|
+
if @objects.empty?
|
16
|
+
render json: []
|
17
|
+
else
|
18
|
+
render json: @objects[0].reject{|x|x.nil?}.map{|x| standardize_json(x) }
|
19
|
+
end
|
20
|
+
else
|
21
|
+
i = params[:page].to_i - 1
|
22
|
+
render json: @objects[i].reject{|x|x.nil?}.map{|x| standardize_json(x) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def show
|
27
|
+
render json: {code: 200}.merge(standardize_json(@object))
|
28
|
+
end
|
29
|
+
|
30
|
+
def create
|
31
|
+
@object = @model.new(model_params)
|
32
|
+
|
33
|
+
attach_files
|
34
|
+
if @object.save
|
35
|
+
render json: {code: 200, msg: "success", object: standardize_json(@object)}
|
36
|
+
else
|
37
|
+
render json: {code: 300, msg: "FAILED!"}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def update
|
42
|
+
attach_files
|
43
|
+
if @object.update(model_params)
|
44
|
+
render json: {code: 200, msg: "success", object: standardize_json(@object)}
|
45
|
+
else
|
46
|
+
render json: {code: 300, msg: "FAILED!"}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy
|
51
|
+
if @object.destroy
|
52
|
+
render json: {code: 200, msg: "success"}
|
53
|
+
else
|
54
|
+
render json: {code: 300, msg: "FAILED!"}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch_column
|
59
|
+
raise RestRails::Error.new "Column '#{params[:column]}' does not exist for #{params[:table_name]} table!" unless @model.attribute_names.include?(params[:column])
|
60
|
+
|
61
|
+
render json: {code: 200, value: @object.public_send(params[:column])}
|
62
|
+
end
|
63
|
+
|
64
|
+
def attach
|
65
|
+
# post '/:table_name/:id/attach/:attachment_name' => 'data#attach'
|
66
|
+
raise RestRails::Error.new "No Attached file!" unless params[:attachment].is_a?(ActionDispatch::Http::UploadedFile)
|
67
|
+
raise RestRails::Error.new "Attachment '#{params[:attachment_name]}' does not exist for #{params[:table_name]} table!" unless attachments_for(@model.new).include?(params[:attachment_name].to_sym)
|
68
|
+
|
69
|
+
@object.public_send(params[:attachment_name].to_sym).attach(params[:attachment])
|
70
|
+
render json: {code: 200, msg: "attached!"}
|
71
|
+
end
|
72
|
+
|
73
|
+
def unattach
|
74
|
+
# delete '/:table_name/:id/unattach/:attachment_id' => 'data#unattach'
|
75
|
+
att = ActiveStorage::Attachment.find(params[:attachment_id])
|
76
|
+
|
77
|
+
raise RestRails::Error.new "Unauthorized! Attachment does not belong to object!" unless (@object.id == att.record_id) && (@object.is_a? att.record_type.constantize)
|
78
|
+
|
79
|
+
att.purge
|
80
|
+
|
81
|
+
render json: {code: 200, msg: "success"}
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def set_model
|
87
|
+
# /api/v1/:table_name/...
|
88
|
+
# e.g. /api/v1/users => User
|
89
|
+
|
90
|
+
# Take the tablename, and make the Model of the relative table_name
|
91
|
+
@model = model_for(params[:table_name])
|
92
|
+
end
|
93
|
+
|
94
|
+
def set_object
|
95
|
+
# Take model from "set_model"
|
96
|
+
@object = @model.find(params[:id])
|
97
|
+
end
|
98
|
+
|
99
|
+
def index_params
|
100
|
+
mn = @model.model_name.singular.to_sym
|
101
|
+
# {user: {name: "something", other_column_name: "somevalue"}}
|
102
|
+
return {} if params[mn].blank?
|
103
|
+
# MAKE LIST OF THINGS TO PERMIT:
|
104
|
+
arr = @model.attribute_names.map(&:to_sym)
|
105
|
+
arr.delete(:created_at)
|
106
|
+
arr.delete(:updated_at)
|
107
|
+
|
108
|
+
# allow arrays for all columns for flexible where queries
|
109
|
+
arr += arr.map do |attr|
|
110
|
+
{attr=>[]}
|
111
|
+
end
|
112
|
+
params.require(mn).permit(arr)
|
113
|
+
end
|
114
|
+
|
115
|
+
def attach_files
|
116
|
+
# BASED ON ACTIVE STORAGE
|
117
|
+
mn = @model.model_name.singular.to_sym # /users => user
|
118
|
+
#
|
119
|
+
file_set = attachments_for(@model.new)
|
120
|
+
file_set.each do |fs|
|
121
|
+
next if params[mn].blank? || params[mn][fs].blank?
|
122
|
+
attachment = params[mn][fs]
|
123
|
+
|
124
|
+
if attachment.is_a?(ActionDispatch::Http::UploadedFile)
|
125
|
+
@object.public_send(fs).attach(attachment)
|
126
|
+
elsif attachment.is_a?(Array) && attachment.first.is_a?(ActionDispatch::Http::UploadedFile)
|
127
|
+
@object.public_send(fs).attach(attachment)
|
128
|
+
elsif attachment.is_a?(Array)
|
129
|
+
params[mn][fs] = attachment.reject{|x| x.include?("/rails/active_storage/blobs")}
|
130
|
+
elsif attachment.is_a? String
|
131
|
+
params[mn][fs] = nil if attachment.include?("/rails/active_storage/blobs")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# ==========UNIVERSAL STRONG PARAMS SETUP=================
|
137
|
+
def model_params
|
138
|
+
mn = @model.model_name.singular.to_sym
|
139
|
+
# {user: {name: "something", other_column_name: "somevalue"}}
|
140
|
+
return {} if params[mn].blank? # to allow create for empty items
|
141
|
+
|
142
|
+
# params.require(:table_name).permit(:column_name1, :column_name2, etc., array_type: [], array_type2: [])
|
143
|
+
params.require(mn).permit(permitted_columns)
|
144
|
+
end
|
145
|
+
|
146
|
+
def permit_array?(attr)
|
147
|
+
permitable_classes = [ActiveStorage::Attached::Many, Array]
|
148
|
+
permitable_classes.include?(@model.new.send(attr).class)
|
149
|
+
end
|
150
|
+
|
151
|
+
def permitted_columns
|
152
|
+
@columns = @model.attribute_names.map(&:to_sym)
|
153
|
+
@columns.delete(:id)
|
154
|
+
@columns.delete(:created_at)
|
155
|
+
@columns.delete(:updated_at)
|
156
|
+
|
157
|
+
@columns.map! do |attr|
|
158
|
+
new_val = permit_array?(attr) ? {attr=>[]} : attr
|
159
|
+
new_val
|
160
|
+
end
|
161
|
+
permitted_attachments if RestRails.active_storage_attachments
|
162
|
+
end
|
163
|
+
|
164
|
+
def permitted_attachments
|
165
|
+
file_set = attachments_for(@model.new)
|
166
|
+
file_set += file_set.select{|x| permit_array?(x)}.map do |attr|
|
167
|
+
{attr=>[]}
|
168
|
+
end
|
169
|
+
|
170
|
+
@columns = @columns + file_set
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module RestRails
|
2
|
+
module ApplicationHelper
|
3
|
+
def standardize_json(ar_object)
|
4
|
+
h = ar_object.serializable_hash
|
5
|
+
h.merge!(serial_attachments(ar_object)) if attachments_for(ar_object).present?
|
6
|
+
h
|
7
|
+
end
|
8
|
+
|
9
|
+
# ==========================================================================
|
10
|
+
# SERIALIZE ATTACHMENTS FOR JSON
|
11
|
+
# ==========================================================================
|
12
|
+
|
13
|
+
def serial_attachments(ar_object)
|
14
|
+
h = {}
|
15
|
+
attachment_types = attachments_for(ar_object)
|
16
|
+
attachment_types.each do |att|
|
17
|
+
attached = self.public_send(att)
|
18
|
+
att_h = {attachment_id: att.id, url: link_for_attached(attached)}
|
19
|
+
h[att] = att_h
|
20
|
+
end
|
21
|
+
return h
|
22
|
+
end
|
23
|
+
|
24
|
+
def blob_link(x)
|
25
|
+
host = RestRails.domain
|
26
|
+
Rails.application.routes.url_helpers.rails_blob_url(x, host: host)
|
27
|
+
end
|
28
|
+
|
29
|
+
def link_for_attached(attached)
|
30
|
+
if attached.class == ActiveStorage::Attached::Many
|
31
|
+
return attached.map{|x| blob_link(x) }
|
32
|
+
elsif attached.class == ActiveStorage::Attached::One
|
33
|
+
x = attached.attachment
|
34
|
+
return blob_link(x) unless x.nil?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def attachments_for(ar_object)
|
39
|
+
meths = ar_object.class.methods.map(&:to_s)
|
40
|
+
attach_meths = meths.select{|x| x.include?("with_attached")}
|
41
|
+
attach_meths.map{|x| x[14..-1].to_sym}
|
42
|
+
end
|
43
|
+
|
44
|
+
# ==========================================================================
|
45
|
+
# OTHER HELPERS
|
46
|
+
# ==========================================================================
|
47
|
+
|
48
|
+
def model_for(table_name)
|
49
|
+
ignored = ["active_storage_blobs", "active_storage_attachments",
|
50
|
+
"schema_migrations", "ar_internal_metadata"]
|
51
|
+
tables = ActiveRecord::Base.connection.tables.reject{ |x| ignored.include?(x) }
|
52
|
+
|
53
|
+
raise RestRails::Error.new "Table '#{table_name}' does not exist in your database!" unless tables.include?(table_name)
|
54
|
+
|
55
|
+
# Take the tablename, and make the Model of the relative table_name
|
56
|
+
table_name.classify.constantize # "users" => User
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
RestRails::Engine.routes.draw do
|
2
|
+
scope module: 'rest_rails' do
|
3
|
+
get '/:table_name' => 'data#index', as: 'data_index'
|
4
|
+
post '/:table_name' => 'data#create'
|
5
|
+
|
6
|
+
get '/:table_name/:id' => 'data#show', as: 'data_show'
|
7
|
+
patch '/:table_name/:id' => 'data#update'
|
8
|
+
delete '/:table_name/:id' => 'data#destroy', as: 'data_destroy'
|
9
|
+
|
10
|
+
post '/:table_name/:id/attach/:attachment_name' => 'data#attach'
|
11
|
+
delete '/:table_name/:id/unattach/:attachment_id' => 'data#unattach'
|
12
|
+
|
13
|
+
get '/:table_name/:id/:column' => 'data#fetch_column'
|
14
|
+
end
|
15
|
+
end
|
data/lib/rest_rails.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "rest_rails/engine"
|
2
|
+
|
3
|
+
module RestRails
|
4
|
+
mattr_accessor :debug, default: false
|
5
|
+
mattr_accessor :authenticatable, default: false
|
6
|
+
mattr_accessor :active_storage_attachments, default: true
|
7
|
+
mattr_accessor :domain, default: 'localhost:3000'
|
8
|
+
|
9
|
+
def self.configure
|
10
|
+
yield self
|
11
|
+
end
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rest_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergio Rivas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-12-23 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: 6.0.2
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 6.0.2.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 6.0.2
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 6.0.2.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: sqlite3
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
description: Build a Full Rails REST API in 10 seconds
|
48
|
+
email:
|
49
|
+
- sergiorivas@aliyun.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- MIT-LICENSE
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- app/assets/config/rest_rails_manifest.js
|
58
|
+
- app/assets/stylesheets/rest_rails/application.css
|
59
|
+
- app/controllers/rest_rails/application_controller.rb
|
60
|
+
- app/controllers/rest_rails/data_controller.rb
|
61
|
+
- app/helpers/rest_rails/application_helper.rb
|
62
|
+
- config/routes.rb
|
63
|
+
- lib/rest_rails.rb
|
64
|
+
- lib/rest_rails/engine.rb
|
65
|
+
- lib/rest_rails/error.rb
|
66
|
+
- lib/rest_rails/version.rb
|
67
|
+
- lib/tasks/rest_rails_tasks.rake
|
68
|
+
homepage: http://rubygems.org/gems/rest_rails
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.7.6
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Simple, Mountable, rails REST API
|
92
|
+
test_files: []
|