sinja 1.1.0.pre4 → 1.2.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/README.md +96 -29
- data/demo-app/.dockerignore +1 -0
- data/demo-app/Dockerfile +26 -0
- data/demo-app/Gemfile +12 -1
- data/demo-app/README.md +39 -24
- data/demo-app/Rakefile +36 -0
- data/demo-app/app.rb +3 -10
- data/demo-app/boot.rb +0 -4
- data/demo-app/classes/author.rb +3 -4
- data/demo-app/{base.rb → classes/base.rb} +2 -1
- data/demo-app/classes/comment.rb +1 -2
- data/demo-app/classes/post.rb +17 -10
- data/demo-app/classes/tag.rb +7 -3
- data/extensions/sequel/Gemfile +4 -0
- data/extensions/sequel/LICENSE.txt +21 -0
- data/extensions/sequel/README.md +274 -0
- data/extensions/sequel/Rakefile +10 -0
- data/extensions/sequel/bin/console +14 -0
- data/extensions/sequel/bin/setup +8 -0
- data/extensions/sequel/lib/sinatra/jsonapi/sequel.rb +7 -0
- data/extensions/sequel/lib/sinja-sequel.rb +2 -0
- data/extensions/sequel/lib/sinja/sequel.rb +110 -0
- data/extensions/sequel/lib/sinja/sequel/core.rb +72 -0
- data/extensions/sequel/lib/sinja/sequel/helpers.rb +78 -0
- data/extensions/sequel/lib/sinja/sequel/version.rb +6 -0
- data/extensions/sequel/sinja-sequel.gemspec +29 -0
- data/extensions/sequel/test/test_helper.rb +3 -0
- data/lib/sinja.rb +40 -18
- data/lib/sinja/config.rb +4 -3
- data/lib/sinja/helpers/serializers.rb +2 -1
- data/lib/sinja/relationship_routes/has_many.rb +8 -9
- data/lib/sinja/relationship_routes/has_one.rb +1 -1
- data/lib/sinja/resource.rb +2 -1
- data/lib/sinja/resource_routes.rb +2 -2
- data/lib/sinja/version.rb +1 -1
- data/sinja.gemspec +5 -7
- metadata +39 -11
- data/.rspec +0 -2
- data/lib/sinja/extensions/sequel.rb +0 -53
- data/lib/sinja/helpers/sequel.rb +0 -101
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7194e1502968ad1c77f29a86eba2142a02e9fab0
|
4
|
+
data.tar.gz: d60c872b2a8b8d5555f18eb2a3064fd748ab4ec8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a42b7e9f8c15e748145b731f9329c7bcce307fb4224ba1f33c2172faacb41fd75dcebe02374e9aa6101fef422f8d12bf09f1c32fdfb4b2a45239e97bd28643c1
|
7
|
+
data.tar.gz: ec35d6bd75b8b47b03ad9a6803407f03ca5c89593389962820de22c1a63de6c7ce7309b592264e8ac961ad552547658ff8723eeac22f8a0f1b8b628cd3c8a9da
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
# Sinja (Sinatra::JSONAPI)
|
2
2
|
|
3
|
+
<!--
|
4
|
+
Title: Sinja
|
5
|
+
Description: RESTful, {json:api}-compliant web services in Sinatra
|
6
|
+
Author: Mike Pastore
|
7
|
+
Keywords: JSON, API, JSONAPI, JSON:API, {json:api}, Ruby, Sinatra, JSONAPI::Serializers, jsonapi-serializers
|
8
|
+
-->
|
9
|
+
|
3
10
|
[![Gem Version](https://badge.fury.io/rb/sinja.svg)](https://badge.fury.io/rb/sinja)
|
11
|
+
[![Dependency Status](https://gemnasium.com/badges/github.com/mwpastore/sinja.svg)](https://gemnasium.com/github.com/mwpastore/sinja)
|
4
12
|
[![Build Status](https://travis-ci.org/mwpastore/sinja.svg?branch=master)](https://travis-ci.org/mwpastore/sinja)
|
5
|
-
|
13
|
+
|
14
|
+
[![Chat in #sinja-rb on Gitter](https://badges.gitter.im/sinja-rb/Lobby.svg)](https://gitter.im/sinja-rb/Lobby)
|
15
|
+
[![Chat in #-ember-data on Slack](https://ember-community-slackin.herokuapp.com/badge.svg)](https://ember-community-slackin.herokuapp.com/?channel=-ember-data)
|
6
16
|
|
7
17
|
Sinja is a [Sinatra][1] [extension][10] for quickly building [RESTful][11],
|
8
18
|
[{json:api}][2]-[compliant][7] web services, leveraging the excellent
|
@@ -26,6 +36,7 @@ the {json:api} specification is).
|
|
26
36
|
- [Commonly Used](#commonly-used)
|
27
37
|
- [Less-Commonly Used](#less-commonly-used)
|
28
38
|
- [Performance](#performance)
|
39
|
+
- [Extensions](#extensions)
|
29
40
|
- [Comparison with JSONAPI::Resources](#comparison-with-jsonapiresources)
|
30
41
|
- [Basic Usage](#basic-usage)
|
31
42
|
- [Configuration](#configuration)
|
@@ -48,6 +59,7 @@ the {json:api} specification is).
|
|
48
59
|
- [`has_many`](#has_many)
|
49
60
|
- [`fetch {..}` => Array](#fetch---array)
|
50
61
|
- [`clear {..}` => TrueClass?](#clear---trueclass)
|
62
|
+
- [`replace {|rios| ..}` => TrueClass?](#replace-rios---trueclass)
|
51
63
|
- [`merge {|rios| ..}` => TrueClass?](#merge-rios---trueclass)
|
52
64
|
- [`subtract {|rios| ..}` => TrueClass?](#subtract-rios---trueclass)
|
53
65
|
- [Advanced Usage](#advanced-usage)
|
@@ -346,6 +358,13 @@ written them verbosely. The main caveat is that there are quite a few block
|
|
346
358
|
closures, which don't perform as well as normal methods in Ruby. Feedback
|
347
359
|
welcome.
|
348
360
|
|
361
|
+
### Extensions
|
362
|
+
|
363
|
+
Sinja extensions provide additional helpers, DSL, and configuration, packaging
|
364
|
+
ORM-specific boilerplate as separate gems. At the moment, the only available
|
365
|
+
extension is for [Sequel](/extensions/sequel), but community contributions are
|
366
|
+
welcome!
|
367
|
+
|
349
368
|
### Comparison with JSONAPI::Resources
|
350
369
|
|
351
370
|
| Feature | JR | Sinja |
|
@@ -436,7 +455,7 @@ configure_jsonapi do |c|
|
|
436
455
|
|
437
456
|
# You can't set this directly; see "Query Parameters" below
|
438
457
|
#c.query_params = {
|
439
|
-
# :include=>[], :fields=>{}, :filter=>{}, :page=>{}, :sort=>
|
458
|
+
# :include=>[], :fields=>{}, :filter=>{}, :page=>{}, :sort=>[]
|
440
459
|
#}
|
441
460
|
|
442
461
|
#c.page_using = {} # see "Paging" below
|
@@ -630,6 +649,18 @@ has_many :bars do
|
|
630
649
|
end
|
631
650
|
```
|
632
651
|
|
652
|
+
##### `replace {|rios| ..}` => TrueClass?
|
653
|
+
|
654
|
+
Take an array of [resource identifier object][22] hashes and update
|
655
|
+
(add/remove) the relationships on `resource`. To serialize the updated linkage
|
656
|
+
on the response, refresh or reload `resource` (if necessary) and return a
|
657
|
+
truthy value.
|
658
|
+
|
659
|
+
In principle, `replace` should delete all members of the existing collection
|
660
|
+
and insert all members of a new collection, but in practice—for
|
661
|
+
performance reasons, especially with large collections and/or complex
|
662
|
+
constraints—it may be prudent to simply apply a delta.
|
663
|
+
|
633
664
|
##### `merge {|rios| ..}` => TrueClass?
|
634
665
|
|
635
666
|
Take an array of [resource identifier object][22] hashes and update (add unless
|
@@ -735,6 +766,7 @@ configure_jsonapi do |c|
|
|
735
766
|
c.default_has_many_roles = {
|
736
767
|
fetch: :user,
|
737
768
|
clear: :admin,
|
769
|
+
replace: :admin,
|
738
770
|
merge: :admin,
|
739
771
|
subtract: :admin
|
740
772
|
}
|
@@ -835,8 +867,8 @@ resource :foos do
|
|
835
867
|
end
|
836
868
|
end
|
837
869
|
|
838
|
-
create(roles: :user) {
|
839
|
-
update(roles: :owner) {
|
870
|
+
create(roles: :user) {|attr| .. }
|
871
|
+
update(roles: :owner) {|attr| .. }
|
840
872
|
end
|
841
873
|
```
|
842
874
|
|
@@ -934,7 +966,7 @@ For example, to implement sorting using Sequel:
|
|
934
966
|
```ruby
|
935
967
|
helpers do
|
936
968
|
def sort(collection, fields={})
|
937
|
-
collection.order(*fields.map {
|
969
|
+
collection.order(*fields.map {|k, v| Sequel.send(v, k) })
|
938
970
|
end
|
939
971
|
end
|
940
972
|
|
@@ -968,7 +1000,7 @@ Allow clients to page the collections returned by the `index` and `fetch`
|
|
968
1000
|
action helpers by defining a `page` helper in the appropriate scope that takes
|
969
1001
|
a collection and a hash of `page` query parameters (with its top-level keys
|
970
1002
|
dedasherized and symbolized) and returns the paged collection along with a
|
971
|
-
special nested hash used to build the paging links.
|
1003
|
+
special nested hash used as root metadata and to build the paging links.
|
972
1004
|
|
973
1005
|
The top-level keys of the hash returned by this method must be members of the
|
974
1006
|
set: {`:self`, `:first`, `:prev`, `:next`, `:last`}. The values of the hash are
|
@@ -1000,8 +1032,8 @@ Could be used to build the following top-level links in the response document:
|
|
1000
1032
|
You must also set the `page_using` configurable to a hash of symbols
|
1001
1033
|
representing the paging fields used in your application (for example, `:number`
|
1002
1034
|
and `:size` for the above example) along with their default values (or `nil`).
|
1003
|
-
Please see the [Sequel
|
1004
|
-
|
1035
|
+
Please see the [Sequel extension](/extensions/sequel) in this repository for a
|
1036
|
+
detailed, working example.
|
1005
1037
|
|
1006
1038
|
The easiest way to page a collection by default is to tweak the post-processed
|
1007
1039
|
query parameter(s) in a `before_<action>` hook:
|
@@ -1036,10 +1068,6 @@ helpers do
|
|
1036
1068
|
end
|
1037
1069
|
```
|
1038
1070
|
|
1039
|
-
(Note that in addition to finalizing Sequel datasets with `#all`, you should
|
1040
|
-
also enable the `:tactical_eager_loading` plugin for the best compatibility
|
1041
|
-
with JSONAPI::Serializers.)
|
1042
|
-
|
1043
1071
|
### Conflicts
|
1044
1072
|
|
1045
1073
|
If your database driver raises exceptions on constraint violations, you should
|
@@ -1174,12 +1202,11 @@ request will fail and any database changes will be rolled back (given a
|
|
1174
1202
|
`transaction` helper). Note that the user's role must grant them access to call
|
1175
1203
|
either `graft` or `create`.
|
1176
1204
|
|
1177
|
-
`create` and `update` are the
|
1178
|
-
`graft
|
1205
|
+
`create` and `update` are the resource action helpers that trigger sideloading;
|
1206
|
+
`graft` and `prune` are the to-one action helpers invoked by sideloading; and
|
1207
|
+
`replace`, `merge`, and `clear` are the to-many action helpers invoked by
|
1179
1208
|
sideloading. You must indicate which combinations are valid using the
|
1180
|
-
`:sideload_on` action helper option.
|
1181
|
-
on `update`, you must define a `clear` action helper and allow it to sideload
|
1182
|
-
on `update` as well.) For example:
|
1209
|
+
`:sideload_on` action helper option. For example:
|
1183
1210
|
|
1184
1211
|
```ruby
|
1185
1212
|
resource :photos do
|
@@ -1187,24 +1214,64 @@ resource :photos do
|
|
1187
1214
|
def find(id) ..; end
|
1188
1215
|
end
|
1189
1216
|
|
1190
|
-
create {
|
1191
|
-
update { |attr| .. }
|
1217
|
+
create {|attr| .. }
|
1192
1218
|
|
1193
1219
|
has_one :photographer do
|
1194
|
-
# Allow `create' to sideload
|
1195
|
-
graft(sideload_on: :create) {
|
1220
|
+
# Allow `create' to sideload Photographer
|
1221
|
+
graft(sideload_on: :create) {|rio| .. }
|
1196
1222
|
end
|
1197
1223
|
|
1198
1224
|
has_many :tags do
|
1199
|
-
# Allow `create'
|
1200
|
-
merge(sideload_on:
|
1201
|
-
|
1202
|
-
# Allow `update' to clear Tags before sideloading them
|
1203
|
-
clear(sideload_on: :update) { .. }
|
1225
|
+
# Allow `create' to sideload Tags
|
1226
|
+
merge(sideload_on: :create) {|rios| .. }
|
1204
1227
|
end
|
1205
1228
|
end
|
1206
1229
|
```
|
1207
1230
|
|
1231
|
+
The following matrix outlines which combinations of action helpers and
|
1232
|
+
`:sideload_on` options enable which behaviors:
|
1233
|
+
|
1234
|
+
<small>
|
1235
|
+
<table>
|
1236
|
+
<thead>
|
1237
|
+
<tr>
|
1238
|
+
<th rowspan="2">Desired behavior</th>
|
1239
|
+
<th colspan="2">For to-one relationship(s)</th>
|
1240
|
+
<th colspan="2">For to-many relationship(s)</th>
|
1241
|
+
</tr>
|
1242
|
+
<tr>
|
1243
|
+
<th>Define Action Helper</th>
|
1244
|
+
<th>With <code>:sideload_on</code></th>
|
1245
|
+
<th>Define Action Helper</th>
|
1246
|
+
<th>With <code>:sideload_on</code></th>
|
1247
|
+
</tr>
|
1248
|
+
</thead>
|
1249
|
+
<tbody>
|
1250
|
+
<tr>
|
1251
|
+
<td>Set relationship(s) when creating resource</td>
|
1252
|
+
<td><code>graft</code></td>
|
1253
|
+
<td><code>:create</code></td>
|
1254
|
+
<td><code>merge</code></td>
|
1255
|
+
<td><code>:create</code></td>
|
1256
|
+
</tr>
|
1257
|
+
<tr>
|
1258
|
+
<td>Set relationship(s) when updating resource</td>
|
1259
|
+
<td><code>graft</code></td>
|
1260
|
+
<td><code>:update</code></td>
|
1261
|
+
<td><code>replace</code></td>
|
1262
|
+
<td><code>:update</code></td>
|
1263
|
+
</tr>
|
1264
|
+
<tr>
|
1265
|
+
<td>Delete relationship(s) when updating resource</td>
|
1266
|
+
<td><code>prune</code></td>
|
1267
|
+
<td><code>:update</code></td>
|
1268
|
+
<td><code>clear</code></td>
|
1269
|
+
<td><code>:update</code></td>
|
1270
|
+
</tr>
|
1271
|
+
</tbody>
|
1272
|
+
</table>
|
1273
|
+
</small>
|
1274
|
+
|
1208
1275
|
#### Avoiding Null Foreign Keys
|
1209
1276
|
|
1210
1277
|
Now, let's say our DBA is forward-thinking and wants to make the foreign key
|
@@ -1271,9 +1338,9 @@ end
|
|
1271
1338
|
```
|
1272
1339
|
|
1273
1340
|
Note that the `validate!` hook is _only_ invoked from within transactions
|
1274
|
-
involving the `create` and `update` action helpers (and any
|
1275
|
-
|
1276
|
-
appropriate in those cases. You must use immedate validation in all other
|
1341
|
+
involving the `create` and `update` action helpers (and any action helpers
|
1342
|
+
invoked via the sideloading mechanism), so this deferred validation pattern is
|
1343
|
+
only appropriate in those cases. You must use immedate validation in all other
|
1277
1344
|
cases. The `sideloaded?` helper is provided to help disambiguate edge cases.
|
1278
1345
|
|
1279
1346
|
> TODO: The following three sections are a little confusing. Rewrite them.
|
@@ -0,0 +1 @@
|
|
1
|
+
Gemfile.lock
|
data/demo-app/Dockerfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
FROM ruby:2.3-alpine
|
2
|
+
ARG container_port=4567
|
3
|
+
ENV container_port=$container_port
|
4
|
+
|
5
|
+
RUN apk --no-cache upgrade
|
6
|
+
RUN apk --no-cache add \
|
7
|
+
sqlite-libs
|
8
|
+
|
9
|
+
COPY Gemfile /app/
|
10
|
+
RUN apk --no-cache add --virtual build-dependencies \
|
11
|
+
build-base \
|
12
|
+
git \
|
13
|
+
ruby-dev \
|
14
|
+
sqlite-dev \
|
15
|
+
&& cd /app \
|
16
|
+
&& DOCKER_BUILD=true bundle install --jobs=4 \
|
17
|
+
&& apk del build-dependencies
|
18
|
+
|
19
|
+
COPY . /app
|
20
|
+
RUN chown -R nobody:nogroup /app
|
21
|
+
|
22
|
+
USER nobody
|
23
|
+
WORKDIR /app
|
24
|
+
CMD bundle exec ruby app.rb -o 0.0.0.0 -p $container_port
|
25
|
+
|
26
|
+
EXPOSE $container_port
|
data/demo-app/Gemfile
CHANGED
@@ -1,3 +1,14 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
3
|
+
gem 'json', '~> 2.0'
|
4
|
+
gem 'sequel', '~> 4.41'
|
5
|
+
gem 'sinatra', '>= 2.0.0.beta2', '< 3'
|
6
|
+
gem 'sinatra-contrib', '>= 2.0.0.beta2', '< 3'
|
7
|
+
unless ENV.key?('DOCKER_BUILD')
|
8
|
+
gem 'sinja', path: '..'
|
9
|
+
gem 'sinja-sequel', path: '../extensions/sequel'
|
10
|
+
else
|
11
|
+
gem 'sinja'
|
12
|
+
gem 'sinja-sequel'
|
13
|
+
end
|
14
|
+
gem 'sqlite3', '~> 1.3'
|
data/demo-app/README.md
CHANGED
@@ -1,38 +1,51 @@
|
|
1
1
|
## Demo App
|
2
2
|
|
3
|
-
This is the demo app for Sinja,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
This is the demo app for Sinja, provided both as an example of and for testing
|
4
|
+
Sinja. It uses [Sequel ORM](http://sequel.jeremyevans.net) with an in-memory
|
5
|
+
SQLite database and demonstrates the [Sequel extension](/extensions/sequel) for
|
6
|
+
Sinja. It works under both MRI/YARV 2.3+ and JRuby 9.1+. It is a very
|
7
|
+
simplistic blog-like application with [database
|
8
|
+
tables](http://sequel.jeremyevans.net/rdoc/files/doc/schema_modification_rdoc.html),
|
9
|
+
[models](http://sequel.jeremyevans.net/rdoc/files/README_rdoc.html#label-Sequel+Models),
|
10
|
+
[serializers](https://github.com/fotinakis/jsonapi-serializers), and
|
11
|
+
[controllers](/) for [authors](/demo-app/classes/author.rb),
|
12
|
+
[posts](/demo-app/classes/post.rb), [comments](/demo-app/classes/comment.rb),
|
13
|
+
and [tags](/demo-app/classes/tag.rb).
|
9
14
|
|
10
15
|
### Usage
|
11
16
|
|
12
|
-
Assuming you have a working, Bundler-enabled Ruby
|
13
|
-
this repo, `cd` into the `demo-app` subdirectory, and
|
14
|
-
commands:
|
17
|
+
Assuming you have a working, [Bundler](http://bundler.io)-enabled Ruby
|
18
|
+
environment, simply clone this repo, `cd` into the `demo-app` subdirectory, and
|
19
|
+
run the following commands:
|
15
20
|
|
16
21
|
```
|
17
22
|
$ bundle install
|
18
23
|
$ bundle exec ruby app.rb [-p <PORT>]
|
19
24
|
```
|
20
25
|
|
21
|
-
The web server will report the port it's listening on
|
22
|
-
port with the `-p` option.
|
23
|
-
(don't forget to set an `Accept` header) to `/authors`, `/posts`, `/comments`,
|
24
|
-
and `/tags`, although not every endpoint is implemented. Log in by setting the
|
25
|
-
`X-Email` header on the request to the email address of a registered user; the
|
26
|
-
default administrator email address is all@yourbase.com.
|
26
|
+
The web server will report the port it's listening on (most likely 4567), or
|
27
|
+
you can specify a port with the `-p` option.
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
Alternatively, if you don't want to clone this repo and set up a Ruby
|
30
|
+
environment just for a quick demo, it's available on Docker Cloud as
|
31
|
+
[mwpastore/sinja-demo-app](https://cloud.docker.com/app/mwpastore/repository/docker/mwpastore/sinja-demo-app):
|
32
|
+
|
33
|
+
```
|
34
|
+
$ docker run -it -p 4567:4567 --rm mwpastore/sinja-demo-app
|
35
|
+
```
|
36
|
+
|
37
|
+
It will respond to {json:api}-compliant requests (don't forget to set an
|
38
|
+
`Accept` header) to `/authors`, `/posts`, `/comments`, and `/tags`, although
|
39
|
+
not every endpoint is implemented. Log in by setting the `X-Email` header on
|
40
|
+
the request to the email address of a registered user; the email address for
|
41
|
+
the default admin user is all@yourbase.com. **This is clearly extremely
|
42
|
+
insecure and should not be used as-is in production. Caveat emptor.**
|
30
43
|
|
31
44
|
You can point it at a different database by setting `DATABASE_URL` in the
|
32
45
|
environment before executing `app.rb`. See the relevant [Sequel
|
33
46
|
documentation](http://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html)
|
34
|
-
for more information. It (rather naïvely) migrates the database
|
35
|
-
startup.
|
47
|
+
for more information. It (rather naïvely) migrates the database and
|
48
|
+
creates the default admin user at startup.
|
36
49
|
|
37
50
|
### Productionalizing
|
38
51
|
|
@@ -40,18 +53,20 @@ You can certainly use this as a starting point for a production application,
|
|
40
53
|
but you will at least want to:
|
41
54
|
|
42
55
|
- [ ] Use a persistent database
|
56
|
+
- [ ] Remove or change the default admin user
|
43
57
|
- [ ] Separate the class files (e.g. `author.rb`, `post.rb`) into separate
|
44
|
-
files for
|
58
|
+
files for migrations, models, serializers, and Sinja controllers
|
45
59
|
- [ ] Create a Gemfile using the dependencies in the top-level
|
46
60
|
[gemspec](/sinja.gemspec) as a starting point
|
47
|
-
- [ ] Add authentication
|
48
|
-
|
49
|
-
|
61
|
+
- [ ] Add authentication and rewrite the `role` helper to enable the
|
62
|
+
authorization scheme. You can use the existing roles as defined or rename
|
63
|
+
them (e.g. use `:admin` instead of `:superuser`)
|
50
64
|
- [ ] Use a real application server such as [Puma](http://puma.io) or
|
51
65
|
[Passenger](https://www.phusionpassenger.com) instead of Ruby's
|
52
66
|
stdlib (WEBrick)
|
53
67
|
- [ ] Configure Sequel's connection pool (i.e. `:max_connections`) to match the
|
54
|
-
application server's thread pool (if any)
|
68
|
+
application server's thread pool (if any) size, e.g.
|
69
|
+
`Puma.cli_config.options[:max_threads]`
|
55
70
|
- [ ] Add caching directives (i.e. `cache_control`, `expires`, `last_modified`,
|
56
71
|
and `etag`) as appropriate
|
57
72
|
|
data/demo-app/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
namespace :docker do
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
IMAGE = 'mwpastore/sinja-demo-app'
|
6
|
+
NAME = SecureRandom.hex(6)
|
7
|
+
PORT = 4567
|
8
|
+
|
9
|
+
def port
|
10
|
+
%x{
|
11
|
+
docker inspect --format '{{ (index ( index .NetworkSettings.Ports "#{PORT}/tcp") 0).HostPort }}' #{NAME}
|
12
|
+
}.chomp
|
13
|
+
end
|
14
|
+
|
15
|
+
task :build do
|
16
|
+
sh "docker build --build-arg container_port=#{PORT} --no-cache -t #{IMAGE}:latest #{__dir__}"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :test do
|
20
|
+
sh "docker run --rm -d -P --name #{NAME} #{IMAGE}"
|
21
|
+
sleep 5
|
22
|
+
begin
|
23
|
+
sh "curl -sf -H 'Accept: application/vnd.api+json' -I :#{port}/authors"
|
24
|
+
ensure
|
25
|
+
sh "docker stop #{NAME} >/dev/null || true"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
task push: [:build, :test] do
|
30
|
+
sh "docker push #{IMAGE}:latest"
|
31
|
+
end
|
32
|
+
|
33
|
+
task :run do
|
34
|
+
sh "docker run --rm -it -p #{PORT}:#{PORT} #{IMAGE}"
|
35
|
+
end
|
36
|
+
end
|
data/demo-app/app.rb
CHANGED
@@ -1,28 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'sinatra'
|
3
3
|
require 'sinatra/jsonapi'
|
4
|
+
require 'sinja/sequel/helpers'
|
4
5
|
|
5
6
|
require_relative 'classes/author'
|
6
7
|
require_relative 'classes/comment'
|
7
8
|
require_relative 'classes/post'
|
8
9
|
require_relative 'classes/tag'
|
9
10
|
|
10
|
-
require 'sinja/helpers/sequel'
|
11
|
-
|
12
11
|
configure :development do
|
13
12
|
set :server_settings, AccessLog: [] # avoid WEBrick double-logging issue
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
Sinja::Helpers::Sequel.config(c)
|
18
|
-
end
|
19
|
-
|
20
|
-
helpers do
|
21
|
-
prepend Sinja::Helpers::Sequel
|
22
|
-
|
15
|
+
helpers Sinja::Sequel::Helpers do
|
23
16
|
def current_user
|
24
17
|
# TESTING/DEMO PURPOSES ONLY -- DO NOT DO THIS IN PRODUCTION
|
25
|
-
Author.first_by_email(env['HTTP_X_EMAIL']) if env.key?('HTTP_X_EMAIL')
|
18
|
+
@current_user ||= Author.first_by_email(env['HTTP_X_EMAIL']) if env.key?('HTTP_X_EMAIL')
|
26
19
|
end
|
27
20
|
|
28
21
|
def role
|