rest_rails 0.1.0 → 0.8.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 +334 -7
- data/app/controllers/rest_rails/data_controller.rb +24 -14
- data/app/helpers/rest_rails/application_helper.rb +28 -7
- data/config/routes.rb +8 -10
- data/lib/generators/rest_rails/USAGE +2 -0
- data/lib/generators/rest_rails/install_generator.rb +24 -0
- data/lib/generators/rest_rails/templates/README +27 -0
- data/lib/generators/rest_rails/templates/rest_rails.rb +29 -0
- data/lib/rest_rails/version.rb +1 -1
- data/lib/rest_rails.rb +3 -1
- metadata +8 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b126ebf0d0ee509d040b57b6ff35dd7bb3ab837c09e499159f369a8d56df21ee
|
4
|
+
data.tar.gz: 91cbf7f438cfa373ba2c9d61f2d1f44f8e3eda84da4244dae1da01e384d898e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6ca726a3603a6ed9ce3ceec63379e266a64c993677c063c9c693940e95d08105b311a9becfdc4380f12ad411e29088f1d7b58462afa0bc3810be8b29ae99483
|
7
|
+
data.tar.gz: dc96c4175867bfc18c1fe059421e0613ee3ab0145ba7910953e62fe5d0ce8595096928ee869d448473ee70487f76679564298c45248b0d0ca1697bf9df09aa9c
|
data/README.md
CHANGED
@@ -1,16 +1,343 @@
|
|
1
1
|
# RestRails
|
2
2
|
Rails Plugin for quick intelligent API Creation by Tuitu Technology Solutions
|
3
3
|
|
4
|
-
## How To
|
4
|
+
## How To Start
|
5
5
|
|
6
|
-
Add To Gemfile:
|
6
|
+
1. Add To Gemfile: `gem 'rest_rails'`
|
7
|
+
2. Bundle Install: `bundle install`
|
8
|
+
3. Install RestRails: `rails g rest_rails:install`
|
9
|
+
4. Modify initializer and/or mounted route.
|
7
10
|
|
8
|
-
|
11
|
+
## The Basics
|
12
|
+
|
13
|
+
RestRails will automatically create a base API for all standard CRUD actions.
|
14
|
+
Just one line of code to implement a powerful REST API.
|
15
|
+
|
16
|
+
For Example's sake, let's take the following schema:
|
17
|
+
|
18
|
+
- **articles:** *title, description, content*
|
19
|
+
- **comments:** *article_id, content*
|
20
|
+
|
21
|
+
Further more, as per activestorage convention, **Article** *has_one_attached :feature_image* & *has_many_attached :content_images*
|
22
|
+
|
23
|
+
Let's say we mount RestRails at `/api/v1`, the Following routes are included for articles:
|
24
|
+
|
25
|
+
### Articles
|
26
|
+
|
27
|
+
REST action | method | route | notes
|
28
|
+
------------ | ------ | -------------------------------------------- | ----------------------
|
29
|
+
index | GET | `/api/v1/articles` | index paginated by 100
|
30
|
+
show | GET | `/api/v1/articles/:id` | show for one article
|
31
|
+
create | POST | `/api/v1/articles` | create new article
|
32
|
+
update | GET | `/api/v1/articles/:id` | update an article
|
33
|
+
destroy | DELETE | `/api/v1/articles/:id` | destroy an article
|
34
|
+
fetch_column | GET | `/api/v1/articles/:id/title` | fetch title of article
|
35
|
+
fetch_column | GET | `/api/v1/articles/:id/description` | fetch description of article
|
36
|
+
fetch_column | GET | `/api/v1/articles/:id/content` | fetch content of article
|
37
|
+
attach | POST | `/api/v1/articles/:id/attach/feature_image` | attach file to feature_image
|
38
|
+
attach | POST | `/api/v1/articles/:id/attach/content_images` | attach file to content_images
|
39
|
+
|
40
|
+
|
41
|
+
And the following for comments:
|
42
|
+
|
43
|
+
### Comments
|
44
|
+
|
45
|
+
REST action | method | route | notes
|
46
|
+
------------ | ------ | -------------------------------------------- | ----------------------
|
47
|
+
index | GET | `/api/v1/comments` | index paginated by 100
|
48
|
+
show | GET | `/api/v1/comments/:id` | show for one comment
|
49
|
+
create | POST | `/api/v1/comments` | create new comment
|
50
|
+
update | GET | `/api/v1/comments/:id` | update an comment
|
51
|
+
destroy | DELETE | `/api/v1/comments/:id` | destroy an comment
|
52
|
+
fetch_column | GET | `/api/v1/comments/:id/article_id` | fetch article_id of comment
|
53
|
+
fetch_column | GET | `/api/v1/comments/:id/content` | fetch content of comment
|
54
|
+
|
55
|
+
# HOW TO USE THE REST API
|
56
|
+
|
57
|
+
## INDEX: GET '/table_name'
|
58
|
+
GET '/articles' will return a JSON response as follows:
|
59
|
+
```
|
60
|
+
{
|
61
|
+
"code": 200,
|
62
|
+
"objects": [
|
63
|
+
{
|
64
|
+
"id": 1,
|
65
|
+
"created_at": "2019-08-27T08:22:19.357Z",
|
66
|
+
"updated_at": "2019-08-27T08:22:19.499Z",
|
67
|
+
"title": "Discourse on Dystopian Non Fiction",
|
68
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
69
|
+
"content": "Wow, the reader actually clicked! Now let me brainwash him with this heavily opinionated article based on a myriad of unverified sources with the credibility of a personified M&M's...",
|
70
|
+
"feature_image": {
|
71
|
+
"attachment_id": 1,
|
72
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsib--f573ab9452c272881fb/jopmqH0.jpg"
|
73
|
+
},
|
74
|
+
"content_images": [
|
75
|
+
{
|
76
|
+
"attachment_id": 3,
|
77
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/sjfioadifo-8fdjsfaj/fjso.jpg"
|
78
|
+
}, {
|
79
|
+
"attachment_id": 12,
|
80
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/fjiods--k0f09fs/jfdsjk.jpg"
|
81
|
+
}
|
82
|
+
]
|
83
|
+
},
|
84
|
+
{...},
|
85
|
+
{...},
|
86
|
+
...
|
87
|
+
],
|
88
|
+
"count": 100,
|
89
|
+
"total": 1300
|
90
|
+
}
|
91
|
+
```
|
92
|
+
|
93
|
+
The index REST API is by *default* paginated by 100. To go through pages, add the following params to the GET path:
|
94
|
+
|
95
|
+
`page=<number>`
|
96
|
+
|
97
|
+
ex: '/api/v1/articles?page=2'
|
98
|
+
|
99
|
+
Models can also be filtered by a very basic WHERE query param structure.
|
100
|
+
|
101
|
+
For Article, the index API point can receive the following paramters:
|
102
|
+
|
103
|
+
param | type | example | notes
|
104
|
+
-------------------------- | --------- | ---------------- | --------------------
|
105
|
+
page | *Integer* | page=2 | Will paginate by 100 per page.
|
106
|
+
article[title] | *String* | article[title]=Some+Title | Will match articles with titles same as the value.
|
107
|
+
article\[title\]\[\] | *Array* | article\[title\]\[\]=SomeTitle&article\[title\]\[\]=SomeOtherTitle | Will match articles with title of 'SomeTitle' OR 'SomeOtherTitle'
|
108
|
+
article[description] | *String* | article[description]=Some+Description | Will match articles with descriptions same as the value.
|
109
|
+
article\[description\]\[\] | *Array* | article\[description\]\[\]=SomeDescription&article\[description\]\[\]=SomeOtherDescription | Will match articles with description of 'SomeDescription' OR 'SomeOtherDescription'
|
110
|
+
article[content] | *String* | article[content]=Some+Content | Will match articles with contents same as the value.
|
111
|
+
article\[content\]\[\] | *Array* | article\[content\]\[\]=SomeContent&article\[content\]\[\]=SomeOtherContent | Will match articles with content of 'SomeContent' OR 'SomeOtherContent'
|
112
|
+
|
113
|
+
## SHOW: GET '/table_name/:id'
|
114
|
+
GET '/articles/1' will return a JSON response as follows:
|
115
|
+
```
|
116
|
+
{
|
117
|
+
"code": 200,
|
118
|
+
"object": {
|
119
|
+
"id": 1,
|
120
|
+
"created_at": "2019-08-27T08:22:19.357Z",
|
121
|
+
"updated_at": "2019-08-27T08:22:19.499Z",
|
122
|
+
"title": "Discourse on Dystopian Non Fiction",
|
123
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
124
|
+
"content": "Wow, the reader actually clicked! Now let me brainwash him with this heavily opinionated article based on a myriad of unverified sources with the credibility of a personified M&M's...",
|
125
|
+
"feature_image": {
|
126
|
+
"attachment_id": 1,
|
127
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsib--f573ab9452c272881fb/jopmqH0.jpg"
|
128
|
+
},
|
129
|
+
"content_images": [
|
130
|
+
{
|
131
|
+
"attachment_id": 3,
|
132
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/sjfioadifo-8fdjsfaj/fjso.jpg"
|
133
|
+
}, {
|
134
|
+
"attachment_id": 12,
|
135
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/fjiods--k0f09fs/jfdsjk.jpg"
|
136
|
+
}
|
137
|
+
]
|
138
|
+
}
|
139
|
+
}
|
140
|
+
```
|
141
|
+
|
142
|
+
## CREATE: POST '/table_name'
|
143
|
+
|
144
|
+
The create paths enforce Rails **strong params**. So only properly structured requests will be allowed.
|
145
|
+
POST '/articles' can accept a payload in the following structure:
|
146
|
+
|
147
|
+
```
|
148
|
+
{
|
149
|
+
"article" {
|
150
|
+
"title": "Discourse on Dystopian Non Fiction",
|
151
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
152
|
+
"content": "Wow, the reader actually clicked! Now let me brainwash him with this heavily opinionated article based on a myriad of unverified sources with the credibility of a personified M&M's..."
|
153
|
+
}
|
154
|
+
}
|
155
|
+
```
|
156
|
+
|
157
|
+
If successful (and passes your ActiveRecord validations), the response will be as follows:
|
158
|
+
|
159
|
+
```
|
160
|
+
{
|
161
|
+
"code": 200,
|
162
|
+
"msg": "success",
|
163
|
+
"object": {
|
164
|
+
"id": 1,
|
165
|
+
"created_at": "2019-08-27T08:22:19.357Z",
|
166
|
+
"updated_at": "2019-08-27T08:22:19.357Z",
|
167
|
+
"title": "Discourse on Dystopian Non Fiction",
|
168
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
169
|
+
"content": "Wow, the reader actually clicked! Now let me brainwash him with this heavily opinionated article based on a myriad of unverified sources with the credibility of a personified M&M's...",
|
170
|
+
"feature_image": null,
|
171
|
+
"content_images": []
|
172
|
+
}
|
173
|
+
}
|
174
|
+
```
|
175
|
+
|
176
|
+
**Note:** If you are using forms to submit data w/ attachments via activestorage, you can also add attachments to the payload sent, as long as it matches the naming of your activestorage attachment, and the form submission content-type is multipart/form_data.
|
177
|
+
|
178
|
+
```
|
179
|
+
{
|
180
|
+
"article" {
|
181
|
+
"title": "Discourse on Dystopian Non Fiction",
|
182
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
183
|
+
"feature_image": <uploaded_file>
|
184
|
+
}
|
185
|
+
}
|
186
|
+
```
|
187
|
+
|
188
|
+
## UPDATE: PATCH '/table_name/:id'
|
189
|
+
|
190
|
+
The update paths enforce Rails **strong params**. So only properly structured requests will be allowed.
|
191
|
+
PATCH '/articles/1' can accept a payload in the following structure (with one or more columns to be updated):
|
192
|
+
|
193
|
+
```
|
194
|
+
{
|
195
|
+
"article" {
|
196
|
+
"title": "Discourse on Dystopian Non Fiction",
|
197
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
198
|
+
"content": "Wow, the reader actually clicked! Now let me brainwash him with this heavily opinionated article based on a myriad of unverified sources with the credibility of a personified M&M's..."
|
199
|
+
}
|
200
|
+
}
|
201
|
+
```
|
202
|
+
|
203
|
+
If successful (and passes your ActiveRecord validations), the response will be as follows:
|
204
|
+
|
205
|
+
```
|
206
|
+
{
|
207
|
+
"code": 200,
|
208
|
+
"msg": "success",
|
209
|
+
"object": {
|
210
|
+
"id": 1,
|
211
|
+
"created_at": "2019-08-27T08:22:19.357Z",
|
212
|
+
"updated_at": "2019-08-27T08:22:19.357Z",
|
213
|
+
"title": "Discourse on Dystopian Non Fiction",
|
214
|
+
"description": "This is an abstract description used to mislead readers into clicking on the article and take a deeper read.",
|
215
|
+
"content": "Wow, the reader actually clicked! Now let me brainwash him with this heavily opinionated article based on a myriad of unverified sources with the credibility of a personified M&M's...",
|
216
|
+
"feature_image": null,
|
217
|
+
"content_images": []
|
218
|
+
}
|
219
|
+
}
|
220
|
+
```
|
221
|
+
|
222
|
+
**Note:** If you are using forms to submit data w/ attachments via activestorage, you can also add attachments to the payload sent, as long as it matches the naming of your activestorage attachment, and the form submission content-type is multipart/form_data.
|
223
|
+
|
224
|
+
```
|
225
|
+
{
|
226
|
+
"article" {
|
227
|
+
"title": "Discourse on Dystopian Non Fiction",
|
228
|
+
"feature_image": <uploaded_file>
|
229
|
+
}
|
230
|
+
}
|
231
|
+
```
|
232
|
+
|
233
|
+
## DESTROY: DELETE '/table_name'
|
234
|
+
|
235
|
+
DELETE '/articles/1' only needs the ID number.
|
236
|
+
|
237
|
+
If successful (and passes your ActiveRecord validations), the response will be as follows:
|
9
238
|
|
10
239
|
```
|
11
|
-
|
240
|
+
{
|
241
|
+
"code": 200,
|
242
|
+
"msg": "success"
|
243
|
+
}
|
12
244
|
```
|
13
|
-
## TODO
|
14
245
|
|
15
|
-
|
16
|
-
|
246
|
+
**Note:** If you are using activestorage, the destroy process will also automatically destroy attachments from your bucket.
|
247
|
+
|
248
|
+
## FETCH_COLUMN: GET '/table_name/:id/:column_name'
|
249
|
+
|
250
|
+
GET '/articles/1/title'
|
251
|
+
|
252
|
+
If column exists, the response will be as follows:
|
253
|
+
|
254
|
+
```
|
255
|
+
{
|
256
|
+
"code": 200,
|
257
|
+
"msg": "success",
|
258
|
+
"value": "Discourse on Dystopian Non Fiction"
|
259
|
+
}
|
260
|
+
```
|
261
|
+
|
262
|
+
**Note:** If you are using activestorage, you will return the following for has_one_attached:
|
263
|
+
|
264
|
+
```
|
265
|
+
{
|
266
|
+
"code": 200,
|
267
|
+
"msg": "success",
|
268
|
+
"value": {
|
269
|
+
"attachment_id": 1,
|
270
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/eyJfcmFpbHMiOnsib--f573ab9452c272881fb/jopmqH0.jpg"
|
271
|
+
}
|
272
|
+
}
|
273
|
+
```
|
274
|
+
And for has_many_attached:
|
275
|
+
|
276
|
+
```
|
277
|
+
{
|
278
|
+
"code": 200,
|
279
|
+
"msg": "success",
|
280
|
+
"value": [
|
281
|
+
{
|
282
|
+
"attachment_id": 3,
|
283
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/sjfioadifo-8fdjsfaj/fjso.jpg"
|
284
|
+
},
|
285
|
+
{
|
286
|
+
"attachment_id": 12,
|
287
|
+
"url": "http://localhost:3000/rails/active_storage/blobs/fjiods--k0f09fs/jfdsjk.jpg"
|
288
|
+
}
|
289
|
+
]
|
290
|
+
}
|
291
|
+
```
|
292
|
+
|
293
|
+
# ACTIVESTORAGE ATTACHMENTS
|
294
|
+
|
295
|
+
For activestorage attachment support, the following two routes are added to models using activestorage:
|
296
|
+
|
297
|
+
`/table_name/:id/attach/:attachment_name` and `/table_name/:id/unattach/:attachment_id`
|
298
|
+
|
299
|
+
## ATTACH: POST '/table_name/:id/attach/:attachment_name'
|
300
|
+
|
301
|
+
The routes generated for the rest API are based on the naming provided in your ActiveRecord model when using activestorage.
|
302
|
+
|
303
|
+
- Supports both has_one_attached & has_many_attached.
|
304
|
+
|
305
|
+
In the articles example above, this would be: "/api/v1/articles/attach/feature_image"
|
306
|
+
|
307
|
+
The payload structure in this case needs only to be:
|
308
|
+
```
|
309
|
+
{
|
310
|
+
attachment: <file_uploaded>
|
311
|
+
}
|
312
|
+
```
|
313
|
+
|
314
|
+
If successful, the response will be as follows:
|
315
|
+
|
316
|
+
```
|
317
|
+
{
|
318
|
+
"code": 200,
|
319
|
+
"msg": "success"
|
320
|
+
}
|
321
|
+
```
|
322
|
+
|
323
|
+
## UNATTACH: DELETE '/table_name/:id/unattach/:attachment_id'
|
324
|
+
|
325
|
+
*\* Note, Response will fail if the attachment_id provided does not belong to the object.*
|
326
|
+
|
327
|
+
If successful, the response will be as follows:
|
328
|
+
|
329
|
+
```
|
330
|
+
{
|
331
|
+
"code": 200,
|
332
|
+
"msg": "success"
|
333
|
+
}
|
334
|
+
```
|
335
|
+
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
## Contribution
|
340
|
+
Here are some features in need of development.
|
341
|
+
- Add way to "protect columns" (i.e. exclude columns from permitted params for model's update/create API points).
|
342
|
+
- Support different popular attachment gems.
|
343
|
+
- Add Locale fetching based on page-routes.
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'json'
|
2
2
|
module RestRails
|
3
|
-
class DataController <
|
4
|
-
include
|
3
|
+
class DataController < ::ApplicationController
|
4
|
+
include ApplicationHelper
|
5
|
+
skip_before_action :verify_authenticity_token
|
5
6
|
before_action :set_model, only: [:index, :show, :create, :update, :destroy, :fetch_column, :attach, :unattach]
|
6
7
|
before_action :set_object, only: [:show, :update, :destroy, :fetch_column, :attach, :unattach]
|
7
8
|
|
@@ -13,22 +14,29 @@ module RestRails
|
|
13
14
|
|
14
15
|
if params[:page].blank? || (params[:page].to_i < 1)
|
15
16
|
if @objects.empty?
|
16
|
-
|
17
|
+
@objects = []
|
17
18
|
else
|
18
|
-
|
19
|
+
@objects = @objects[0].reject{|x|x.nil?}.map{|x| standardize_json(x) }
|
19
20
|
end
|
20
21
|
else
|
21
22
|
i = params[:page].to_i - 1
|
22
|
-
|
23
|
+
objs = @objects[i]
|
24
|
+
if objs.nil?
|
25
|
+
@objects = []
|
26
|
+
else
|
27
|
+
@objects = objs.reject{|x|x.nil?}.map{|x| standardize_json(x) }
|
28
|
+
end
|
23
29
|
end
|
30
|
+
|
31
|
+
render json: {code: 200, objects: @objects, count: @objects.count, total: @model.count}
|
24
32
|
end
|
25
33
|
|
26
34
|
def show
|
27
|
-
render json: {code: 200
|
35
|
+
render json: {code: 200, object: standardize_json(@object)}
|
28
36
|
end
|
29
37
|
|
30
38
|
def create
|
31
|
-
@object = @
|
39
|
+
@object = @empty_obj(model_params)
|
32
40
|
|
33
41
|
attach_files
|
34
42
|
if @object.save
|
@@ -56,18 +64,19 @@ module RestRails
|
|
56
64
|
end
|
57
65
|
|
58
66
|
def fetch_column
|
59
|
-
raise RestRails::Error.new "Column '#{params[:column]}' does not exist for #{params[:table_name]} table!" unless @
|
67
|
+
raise RestRails::Error.new "Column '#{params[:column]}' does not exist for #{params[:table_name]} table!" unless columns_for(@object).include?(params[:column])
|
60
68
|
|
61
|
-
|
69
|
+
col_value = @object.public_send(params[:column])
|
70
|
+
render json: {code: 200, msg: "success", value: prepare_column(col_value)}
|
62
71
|
end
|
63
72
|
|
64
73
|
def attach
|
65
74
|
# post '/:table_name/:id/attach/:attachment_name' => 'data#attach'
|
66
75
|
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(@
|
76
|
+
raise RestRails::Error.new "Attachment '#{params[:attachment_name]}' does not exist for #{params[:table_name]} table!" unless attachments_for(@empty_obj).include?(params[:attachment_name].to_sym)
|
68
77
|
|
69
78
|
@object.public_send(params[:attachment_name].to_sym).attach(params[:attachment])
|
70
|
-
render json: {code: 200, msg: "
|
79
|
+
render json: {code: 200, msg: "success"}
|
71
80
|
end
|
72
81
|
|
73
82
|
def unattach
|
@@ -89,6 +98,7 @@ module RestRails
|
|
89
98
|
|
90
99
|
# Take the tablename, and make the Model of the relative table_name
|
91
100
|
@model = model_for(params[:table_name])
|
101
|
+
@empty_obj = @model.new
|
92
102
|
end
|
93
103
|
|
94
104
|
def set_object
|
@@ -116,7 +126,7 @@ module RestRails
|
|
116
126
|
# BASED ON ACTIVE STORAGE
|
117
127
|
mn = @model.model_name.singular.to_sym # /users => user
|
118
128
|
#
|
119
|
-
file_set = attachments_for(@
|
129
|
+
file_set = attachments_for(@empty_obj)
|
120
130
|
file_set.each do |fs|
|
121
131
|
next if params[mn].blank? || params[mn][fs].blank?
|
122
132
|
attachment = params[mn][fs]
|
@@ -145,7 +155,7 @@ module RestRails
|
|
145
155
|
|
146
156
|
def permit_array?(attr)
|
147
157
|
permitable_classes = [ActiveStorage::Attached::Many, Array]
|
148
|
-
permitable_classes.include?(@
|
158
|
+
permitable_classes.include?(@empty_obj.send(attr).class)
|
149
159
|
end
|
150
160
|
|
151
161
|
def permitted_columns
|
@@ -162,7 +172,7 @@ module RestRails
|
|
162
172
|
end
|
163
173
|
|
164
174
|
def permitted_attachments
|
165
|
-
file_set = attachments_for(@
|
175
|
+
file_set = attachments_for(@empty_obj)
|
166
176
|
file_set += file_set.select{|x| permit_array?(x)}.map do |attr|
|
167
177
|
{attr=>[]}
|
168
178
|
end
|
@@ -14,24 +14,40 @@ module RestRails
|
|
14
14
|
h = {}
|
15
15
|
attachment_types = attachments_for(ar_object)
|
16
16
|
attachment_types.each do |att|
|
17
|
-
attached =
|
18
|
-
|
19
|
-
h[att] =
|
17
|
+
attached = ar_object.public_send(att)
|
18
|
+
next if attached.nil?
|
19
|
+
h[att] = prepare_attachment(attached)
|
20
20
|
end
|
21
21
|
return h
|
22
22
|
end
|
23
23
|
|
24
|
+
def attachment_hash(attached)
|
25
|
+
{attachment_id: attached.id, url: blob_link(attached)}
|
26
|
+
end
|
27
|
+
|
24
28
|
def blob_link(x)
|
25
|
-
|
29
|
+
if Rails.env == "production"
|
30
|
+
host = RestRails.production_domain || ""
|
31
|
+
else
|
32
|
+
host = RestRails.development_domain || "http://localhost:3000"
|
33
|
+
end
|
26
34
|
Rails.application.routes.url_helpers.rails_blob_url(x, host: host)
|
27
35
|
end
|
28
36
|
|
29
|
-
def
|
37
|
+
def prepare_column(col_value)
|
38
|
+
if [ActiveStorage::Attached::Many, ActiveStorage::Attached::One].include?(col_value.class)
|
39
|
+
return prepare_attachment(col_value)
|
40
|
+
else
|
41
|
+
return col_value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def prepare_attachment(attached)
|
30
46
|
if attached.class == ActiveStorage::Attached::Many
|
31
|
-
return attached.map{|x|
|
47
|
+
return attached.map{|x| attachment_hash(x) }
|
32
48
|
elsif attached.class == ActiveStorage::Attached::One
|
33
49
|
x = attached.attachment
|
34
|
-
return
|
50
|
+
return attachment_hash(x) unless x.nil?
|
35
51
|
end
|
36
52
|
end
|
37
53
|
|
@@ -41,6 +57,11 @@ module RestRails
|
|
41
57
|
attach_meths.map{|x| x[14..-1].to_sym}
|
42
58
|
end
|
43
59
|
|
60
|
+
def columns_for(ar_object)
|
61
|
+
cols = ar_object.class.attribute_names.map(&:to_sym)
|
62
|
+
cols += attachments_for(ar_object)
|
63
|
+
end
|
64
|
+
|
44
65
|
# ==========================================================================
|
45
66
|
# OTHER HELPERS
|
46
67
|
# ==========================================================================
|
data/config/routes.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
RestRails::Engine.routes.draw do
|
2
|
-
|
3
|
-
|
4
|
-
post '/:table_name' => 'data#create'
|
2
|
+
get '/:table_name' => 'data#index', as: 'data_index'
|
3
|
+
post '/:table_name' => 'data#create'
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
get '/:table_name/:id' => 'data#show', as: 'data_show'
|
6
|
+
patch '/:table_name/:id' => 'data#update'
|
7
|
+
delete '/:table_name/:id' => 'data#destroy', as: 'data_destroy'
|
9
8
|
|
10
|
-
|
11
|
-
|
9
|
+
post '/:table_name/:id/attach/:attachment_name' => 'data#attach'
|
10
|
+
delete '/:table_name/:id/unattach/:attachment_id' => 'data#unattach'
|
12
11
|
|
13
|
-
|
14
|
-
end
|
12
|
+
get '/:table_name/:id/:column' => 'data#fetch_column'
|
15
13
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RestRails
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
namespace "rest_rails:install"
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
# argument :name, :type => :string, :default => "en"
|
9
|
+
def basic_setup
|
10
|
+
# Setup Initializer
|
11
|
+
template "rest_rails.rb", "config/initializers/rest_rails.rb"
|
12
|
+
end
|
13
|
+
def setup_routes
|
14
|
+
route "mount RestRails::Engine => '/api/v1', as: 'rest'"
|
15
|
+
route "# For more information, check out the gem repo: https://github.com/sergio-rivas/rest-rails"
|
16
|
+
route "# Note: Make sure RestRails engine is at the BOTTOM of routes"
|
17
|
+
route "# RestRails standard REST API for all models"
|
18
|
+
end
|
19
|
+
def completed
|
20
|
+
readme "README"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
========================================================================
|
2
|
+
|
3
|
+
_-====-__-======-__-========-_____-============-__
|
4
|
+
_( All aboard! Now hopping on... _)
|
5
|
+
OO( ╦═╗┌─┐┌─┐┌┬┐╦═╗┌─┐┬┬ ┌─┐ )_
|
6
|
+
0 (_ ╠╦╝├┤ └─┐ │ ╠╦╝├─┤││ └─┐ _)
|
7
|
+
o0 (_ ╩╚═└─┘└─┘ ┴ ╩╚═┴ ┴┴┴─┘└─┘ _)
|
8
|
+
o '=-___-===-_____-========-___________-===-dwb-='
|
9
|
+
.o _________
|
10
|
+
. ______ ______________ | | _____
|
11
|
+
_()_||__|| ________ | by | |_________| __||___||__
|
12
|
+
( R.R. | | | | Tuitu | __Y______00_| |_ _|
|
13
|
+
/-OO----OO""="OO--OO"="OO--------OO"="OO-------OO"="OO-------OO"=P
|
14
|
+
|
15
|
+
========================================================================
|
16
|
+
|
17
|
+
Next Steps:
|
18
|
+
|
19
|
+
1) Modify the initializer in /config/initializers/rest_rails.rb
|
20
|
+
2) Read the documentation at: https://github.com/sergio-rivas/rest-rails
|
21
|
+
3) experiment and have fun!
|
22
|
+
|
23
|
+
---*Bonus*---
|
24
|
+
make sure to send feedback and feature requests!
|
25
|
+
And issues too, if you encounter strange errors.
|
26
|
+
|
27
|
+
Pull Requests welcome~
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Here's the configuration setup for RestRails!
|
2
|
+
|
3
|
+
RestRails.configure do |config|
|
4
|
+
# set debug to true if you want to see loud errors in the server logs.
|
5
|
+
config.debug = false
|
6
|
+
|
7
|
+
# if you are using devise or another authentication system and want to
|
8
|
+
# enforce the before_action `authenticate_user!`
|
9
|
+
#
|
10
|
+
# Note: take a look at `simple_token_authentication` or `tiddle` gems to setup
|
11
|
+
# token-based authentication for devise.
|
12
|
+
config.authenticatable = false
|
13
|
+
|
14
|
+
|
15
|
+
# ===============================================
|
16
|
+
# ACTIVE STORAGE SETTINGS FOR ATTACHMENTS
|
17
|
+
# ===============================================
|
18
|
+
# to enable REST attachments via active storage
|
19
|
+
config.active_storage_attachments = false
|
20
|
+
|
21
|
+
# to setup domains to attach to urls returned from activestorage blob_url.
|
22
|
+
# if used for WEB, you can simply put "/"
|
23
|
+
# if using for Native Apps, or WeChat/AliPay Mini Programs,
|
24
|
+
# you should have this be the domain of your API host. e.g.: 'https://api.fakeurl.com'
|
25
|
+
config.production_domain = nil
|
26
|
+
|
27
|
+
# Set development domain if needed.
|
28
|
+
config.development_domain = "http://localhost:3000"
|
29
|
+
end
|
data/lib/rest_rails/version.rb
CHANGED
data/lib/rest_rails.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
require "rest_rails/engine"
|
2
|
+
require "rest_rails/error"
|
2
3
|
|
3
4
|
module RestRails
|
4
5
|
mattr_accessor :debug, default: false
|
5
6
|
mattr_accessor :authenticatable, default: false
|
6
7
|
mattr_accessor :active_storage_attachments, default: true
|
7
|
-
mattr_accessor :
|
8
|
+
mattr_accessor :production_domain, default: nil
|
9
|
+
mattr_accessor :development_domain, default: 'localhost:3000'
|
8
10
|
|
9
11
|
def self.configure
|
10
12
|
yield self
|
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergio Rivas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 6.0.2
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
19
|
+
version: 5.2.1
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 6.0.2
|
30
24
|
- - ">="
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
26
|
+
version: 5.2.1
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: sqlite3
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,6 +54,10 @@ files:
|
|
60
54
|
- app/controllers/rest_rails/data_controller.rb
|
61
55
|
- app/helpers/rest_rails/application_helper.rb
|
62
56
|
- config/routes.rb
|
57
|
+
- lib/generators/rest_rails/USAGE
|
58
|
+
- lib/generators/rest_rails/install_generator.rb
|
59
|
+
- lib/generators/rest_rails/templates/README
|
60
|
+
- lib/generators/rest_rails/templates/rest_rails.rb
|
63
61
|
- lib/rest_rails.rb
|
64
62
|
- lib/rest_rails/engine.rb
|
65
63
|
- lib/rest_rails/error.rb
|