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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +96 -29
  4. data/demo-app/.dockerignore +1 -0
  5. data/demo-app/Dockerfile +26 -0
  6. data/demo-app/Gemfile +12 -1
  7. data/demo-app/README.md +39 -24
  8. data/demo-app/Rakefile +36 -0
  9. data/demo-app/app.rb +3 -10
  10. data/demo-app/boot.rb +0 -4
  11. data/demo-app/classes/author.rb +3 -4
  12. data/demo-app/{base.rb → classes/base.rb} +2 -1
  13. data/demo-app/classes/comment.rb +1 -2
  14. data/demo-app/classes/post.rb +17 -10
  15. data/demo-app/classes/tag.rb +7 -3
  16. data/extensions/sequel/Gemfile +4 -0
  17. data/extensions/sequel/LICENSE.txt +21 -0
  18. data/extensions/sequel/README.md +274 -0
  19. data/extensions/sequel/Rakefile +10 -0
  20. data/extensions/sequel/bin/console +14 -0
  21. data/extensions/sequel/bin/setup +8 -0
  22. data/extensions/sequel/lib/sinatra/jsonapi/sequel.rb +7 -0
  23. data/extensions/sequel/lib/sinja-sequel.rb +2 -0
  24. data/extensions/sequel/lib/sinja/sequel.rb +110 -0
  25. data/extensions/sequel/lib/sinja/sequel/core.rb +72 -0
  26. data/extensions/sequel/lib/sinja/sequel/helpers.rb +78 -0
  27. data/extensions/sequel/lib/sinja/sequel/version.rb +6 -0
  28. data/extensions/sequel/sinja-sequel.gemspec +29 -0
  29. data/extensions/sequel/test/test_helper.rb +3 -0
  30. data/lib/sinja.rb +40 -18
  31. data/lib/sinja/config.rb +4 -3
  32. data/lib/sinja/helpers/serializers.rb +2 -1
  33. data/lib/sinja/relationship_routes/has_many.rb +8 -9
  34. data/lib/sinja/relationship_routes/has_one.rb +1 -1
  35. data/lib/sinja/resource.rb +2 -1
  36. data/lib/sinja/resource_routes.rb +2 -2
  37. data/lib/sinja/version.rb +1 -1
  38. data/sinja.gemspec +5 -7
  39. metadata +39 -11
  40. data/.rspec +0 -2
  41. data/lib/sinja/extensions/sequel.rb +0 -53
  42. data/lib/sinja/helpers/sequel.rb +0 -101
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a86013c139ad0c6cd3555443076a4c813c8cedc6
4
- data.tar.gz: 7c3dc7d285fb817bb9e4c6003bc24c0cb8d2b1f2
3
+ metadata.gz: 7194e1502968ad1c77f29a86eba2142a02e9fab0
4
+ data.tar.gz: d60c872b2a8b8d5555f18eb2a3064fd748ab4ec8
5
5
  SHA512:
6
- metadata.gz: 86a0909d1e859b4f2177de1d71c91b60fa5bc0160c8b1568f94acc100ce84c01157439633e89124eed2e09318a3b4ffb0aa6596fc7bae3a09ee88a4e9132ca43
7
- data.tar.gz: 21f0f20bda31d9a6954437f66848eb47f7c13dd8e8250992bb259c9791f7cb3fa7b39f6ba8291101f7128bf8b7add9b8e87b32c768d95d3924a839fee90627c6
6
+ metadata.gz: a42b7e9f8c15e748145b731f9329c7bcce307fb4224ba1f33c2172faacb41fd75dcebe02374e9aa6101fef422f8d12bf09f1c32fdfb4b2a45239e97bd28643c1
7
+ data.tar.gz: ec35d6bd75b8b47b03ad9a6803407f03ca5c89593389962820de22c1a63de6c7ce7309b592264e8ac961ad552547658ff8723eeac22f8a0f1b8b628cd3c8a9da
data/Gemfile CHANGED
@@ -1,5 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
- gem 'munson', '~> 0.3',
4
+ gem 'sinja-sequel', :require=>false, :path=>'extensions/sequel'
5
+ gem 'munson', '~> 0.3', :require=>false,
5
6
  :git=>'https://github.com/mwpastore/munson', :branch=>'develop'
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
- [![Chat](https://badges.gitter.im/sinja-rb/Lobby.svg)](https://gitter.im/sinja-rb/Lobby)
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&mdash;for
661
+ performance reasons, especially with large collections and/or complex
662
+ constraints&mdash;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) { |attr| .. }
839
- update(roles: :owner) { |attr| .. }
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 { |k, v| Sequel.send(v, k) })
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 helpers](/lib/sinja/helpers/sequel.rb) in this
1004
- repository for a detailed, working example.
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 only two action helpers that trigger sideloading;
1178
- `graft`, `merge`, and `clear` are the only action helpers invoked by
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. (Note that if you want to sideload `merge`
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 { |attr| .. }
1191
- update { |attr| .. }
1217
+ create {|attr| .. }
1192
1218
 
1193
1219
  has_one :photographer do
1194
- # Allow `create' to sideload the Photographer
1195
- graft(sideload_on: :create) { |rio| .. }
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' and `update' to sideload Tags
1200
- merge(sideload_on: [:create, :update]) { |rios| .. }
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 dependent `graft`
1275
- and `merge` action helpers), so this deferred validation pattern is only
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
@@ -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
- gemspec :path=>'..'
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, used as an example of and for testing Sinja. It
4
- is a very simplistic blog-like application with database tables, models,
5
- serializers, and controllers for authors, posts, comments, and tags. It uses
6
- [Sequel ORM](http://sequel.jeremyevans.net) (and the [Sequel
7
- helpers](/lib/sinja/helpers/sequel.rb) provided with Sinja) with an in-memory
8
- SQLite database, and it works under both MRI/YARV 2.3+ and JRuby 9.1+.
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 environment, simply clone
13
- this repo, `cd` into the `demo-app` subdirectory, and run the following
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, or you can specify a
22
- port with the `-p` option. It will respond to {json:api}-compliant requests
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
- **This is clearly extremely insecure and should not be used as-is in production.
29
- Caveat emptor.**
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&iuml;vely) migrates the database at
35
- startup.
47
+ for more information. It (rather na&iuml;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 the migrations, models, serializers, and Sinja controllers
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 middleware and rewrite the `role` helper to enable
48
- the authorization scheme. You can use the existing roles as defined or
49
- rename them (e.g. use `:admin` instead of `:superuser`)
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
- configure_jsonapi do |c|
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