sinja 1.2.4 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 851e8f43eabf59529257a1ef2fcc7a6df84f8ea5
4
- data.tar.gz: b75968556128599080ba71d790d8b1671cbc89e6
3
+ metadata.gz: 9054bed54d4dd7bf2e166d3708c3726ba9c92d89
4
+ data.tar.gz: 1ade5511cf29f452d7f3d4555e1a153ea895c9a7
5
5
  SHA512:
6
- metadata.gz: 0ddd2782e3e63efab5bfee81ace29615708e08cc9a137ba28451724543f98ee3f2f6d59eda0444a0859ebd9f4b8ccdc26ed661ebde0cbdf9b902e97e18f8d23f
7
- data.tar.gz: 1fea65b16d22c9bbb22dc0af0ed4744308eaf5dfe217da0c054da4c57b40ae5d00a36617b06d114ae2a50b324a72ac45a4c17917bd61debed1ed812d35c5e0ef
6
+ metadata.gz: 8cf864d75cf3232f2ab1f2699ea61e02db3a7503a446b07a6d1fe38261625b911f316e8a8851b44f13b7539d39b96a537699964c516918dd9676af0c6cf98ff0
7
+ data.tar.gz: 980b31489e1efd32956b33691bf78eb6c8cd1097a76af04cec58ab03abb567f4dd0d59ee42592079de8aa224b70beb29a3e7b6f7ee7bfb56c6453d33b09c056f
@@ -6,9 +6,6 @@ rvm:
6
6
  - ruby-head
7
7
  - jruby-9.1.7.0
8
8
  - jruby-head
9
- env:
10
- - sinatra=1.4.7 rails=4.2.7.1
11
- - sinatra=2.0.0.beta2 rails=5.0.1
12
9
  jdk:
13
10
  - oraclejdk8
14
11
  before_install:
data/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  [![{json:api} version](https://img.shields.io/badge/%7Bjson%3Aapi%7D%20version-1.0-lightgrey.svg)][7]
14
14
  [![Chat in #sinja-rb on Gitter](https://badges.gitter.im/sinja-rb/Lobby.svg)](https://gitter.im/sinja-rb/Lobby)
15
15
 
16
- Sinja is a [Sinatra][1] [extension][10] for quickly building [RESTful][11],
16
+ Sinja is a [Sinatra 2.0][1] [extension][10] for quickly building [RESTful][11],
17
17
  [{json:api}][2]-compliant web services, leveraging the excellent
18
18
  [JSONAPI::Serializers][3] gem for payload serialization. It enhances Sinatra's
19
19
  DSL to enable resource-, relationship-, and role-centric API development, and
@@ -40,6 +40,7 @@ framework like [Rails][16]. It's lightweight, ORM-agnostic, and
40
40
  - [Configuration](#configuration)
41
41
  - [Sinatra](#sinatra)
42
42
  - [Sinja](#sinja)
43
+ - [Resources](#resources)
43
44
  - [Resource Locators](#resource-locators)
44
45
  - [Action Helpers](#action-helpers)
45
46
  - [`resource`](#resource)
@@ -63,6 +64,7 @@ framework like [Rails][16]. It's lightweight, ORM-agnostic, and
63
64
  - [Transactions](#transactions)
64
65
  - [Side-Unloading Related Resources](#side-unloading-related-resources)
65
66
  - [Side-Loading Relationships](#side-loading-relationships)
67
+ - [Deferring Relationships](#deferring-relationships)
66
68
  - [Avoiding Null Foreign Keys](#avoiding-null-foreign-keys)
67
69
  - [Coalesced Find Requests](#coalesced-find-requests)
68
70
  - [Patchless Clients](#patchless-clients)
@@ -156,6 +158,9 @@ Or install it yourself as:
156
158
  $ gem install sinja
157
159
  ```
158
160
 
161
+ Sinja is not compatible with Sinatra 1.x due to its limitations with nested
162
+ regexp-style namespaces and routes.
163
+
159
164
  ## Ol' Blue Eyes is Back
160
165
 
161
166
  The "power" so to speak of implementing this functionality as a Sinatra
@@ -341,6 +346,36 @@ FooError` and `c.serializer_opts[:meta] = { foo: 'bar' }`) until you call
341
346
  `freeze_jsonapi` to freeze the configuration store. **You should always freeze
342
347
  the store after Sinja is configured and all your resources are defined.**
343
348
 
349
+ ### Resources
350
+
351
+ Resources declared with the `resource` keyword (and relationships declared with
352
+ the `has_many` and `has_one` keywords) are dasherized and pluralized to match
353
+ the "type" property of JSONAPI::Serializers. For example, `resource :foo_bar`
354
+ would instruct Sinja to draw the appropriate routes under `/foo-bars`. Your
355
+ serializer type(s) should always match your resource (and relationship) names;
356
+ see the relevant [documentation][33] for more information.
357
+
358
+ The primary key portion of the route is extracted using a regular expression,
359
+ `\d+` by default. To use a different pattern, pass the `:pkre` resource route
360
+ option:
361
+
362
+ ```ruby
363
+ resource :foo_bar, pkre: /\d+-\d+/ do
364
+ helpers do
365
+ def find(id)
366
+ # Look up a FooBar with a composite primary key of two integers.
367
+ FooBar[id.split('-', 2).map!(&:to_i)]
368
+ end
369
+ end
370
+
371
+ # ..
372
+ end
373
+ ```
374
+
375
+ This helps Sinja (and Sinatra) disambiguate between standard {json:api} routes
376
+ used to fetch resources (e.g. `GET /foos/1`) and similarly-structured custom
377
+ routes (e.g. `GET /foos/recent`).
378
+
344
379
  ### Resource Locators
345
380
 
346
381
  Much of Sinja's advanced functionality (e.g. updating and destroying resources,
@@ -1537,7 +1572,7 @@ logic.
1537
1572
  | Feature | JR | Sinja |
1538
1573
  | :-------------- | :------------------------------- | :------------------------------------------------ |
1539
1574
  | Serializer | Built-in | [JSONAPI::Serializers][3] |
1540
- | Framework | Rails | Sinatra, but easy to mount within others |
1575
+ | Framework | Rails | Sinatra 2.0, but easy to mount within others |
1541
1576
  | Routing | ActionDispatch::Routing | Mustermann |
1542
1577
  | Caching | ActiveSupport::Cache | BYO |
1543
1578
  | ORM | ActiveRecord/ActiveModel | BYO |
@@ -1614,3 +1649,4 @@ License](http://opensource.org/licenses/MIT).
1614
1649
  [30]: https://github.com/mwpastore/sinja-sequel
1615
1650
  [31]: http://jsonapi.org/implementations/#server-libraries-ruby
1616
1651
  [32]: http://emberjs.com
1652
+ [33]: https://github.com/fotinakis/jsonapi-serializers#more-customizations
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'jdbc-sqlite3', '~> 3.8', :platform=>:jruby
4
4
  gem 'json', '~> 2.0'
5
- gem 'sequel', '~> 4.43'
5
+ gem 'sequel', '~> 4.44'
6
6
  gem 'sinatra', '>= 2.0.0.beta2', '< 3'
7
7
  gem 'sinatra-contrib', '>= 2.0.0.beta2', '< 3'
8
8
  gem 'sinja',
@@ -10,7 +10,9 @@ require_relative 'classes/comment'
10
10
  require_relative 'classes/post'
11
11
  require_relative 'classes/tag'
12
12
 
13
- # Freeze database after creating tables and loading models
13
+ Sequel::Model.finalize_associations
14
+ Sequel::Model.freeze
15
+
14
16
  DB.freeze
15
17
 
16
18
  configure :development do
@@ -34,7 +36,7 @@ end
34
36
 
35
37
  resource :authors, &AuthorController
36
38
  resource :comments, &CommentController
37
- resource :posts, &PostController
39
+ resource :posts, :pkre=>/[\w-]+/, &PostController
38
40
  resource :tags, &TagController
39
41
 
40
42
  freeze_jsonapi
@@ -55,7 +55,7 @@ AuthorController = proc do
55
55
  show
56
56
 
57
57
  show_many do |ids|
58
- Author.where(id: ids.map!(&:to_i)).all
58
+ Author.where_all(id: ids.map!(&:to_i))
59
59
  end
60
60
 
61
61
  index do
@@ -64,7 +64,7 @@ PostController = proc do
64
64
  end
65
65
 
66
66
  show_many do |slugs|
67
- next Post.where(slug: slugs.map!(&:to_s)).all, include: %i[author tags]
67
+ next Post.where_all(slug: slugs.map!(&:to_s)), include: %i[author tags]
68
68
  end
69
69
 
70
70
  index do
@@ -2,7 +2,6 @@
2
2
  require 'set'
3
3
 
4
4
  require 'active_support/inflector'
5
- require 'mustermann'
6
5
  require 'sinatra/base'
7
6
  require 'sinatra/namespace'
8
7
 
@@ -22,7 +21,6 @@ module Sinja
22
21
  .to_h.freeze
23
22
 
24
23
  def self.registered(app)
25
- app.register Mustermann if Sinatra::VERSION[/^\d+/].to_i < 2
26
24
  app.register Sinatra::Namespace
27
25
 
28
26
  app.disable :protection, :show_exceptions, :static
@@ -102,9 +100,9 @@ module Sinja
102
100
  end
103
101
  end
104
102
 
105
- # Sinatra 2.0 re-initializes `params' at namespace boundaries, but
106
- # Sinatra 1.4 does not, so we'll reference its object_id in the flag
107
- # to make sure we only re-normalize the parameters when necessary.
103
+ # Sinatra re-initializes `params' at namespace boundaries, so we'll
104
+ # reference its object_id in the flag to make sure we only re-normalize
105
+ # the parameters when necessary.
108
106
  env['sinja.normalized'] = params.object_id
109
107
  end
110
108
  end
@@ -313,7 +311,7 @@ module Sinja
313
311
  end
314
312
  end
315
313
 
316
- def resource(resource_name, konst=nil, &block)
314
+ def resource(resource_name, konst=nil, **opts, &block)
317
315
  abort "Must supply proc constant or block for `resource'" \
318
316
  unless block = (konst if konst.instance_of?(Proc)) || block
319
317
 
@@ -328,6 +326,9 @@ module Sinja
328
326
  # trigger default procs
329
327
  config = _sinja.resource_config[resource_name]
330
328
 
329
+ # incorporate route options
330
+ config[:route_opts].merge!(opts)
331
+
331
332
  namespace %r{/#{resource_name}(?![^/])} do
332
333
  define_singleton_method(:_resource_config) { config }
333
334
  define_singleton_method(:resource_config) { config[:resource] }
@@ -338,12 +339,14 @@ module Sinja
338
339
  end
339
340
  end
340
341
 
341
- before %r{/(?<id>[^/]+)(?:/.+)?} do |id|
342
+ before %r{/(#{config[:route_opts][:pkre]})(?:/.*)?} do |id|
342
343
  self.resource =
343
344
  if env.key?('sinja.resource')
344
345
  env['sinja.resource']
345
346
  elsif respond_to?(:find)
346
347
  find(id)
348
+ else
349
+ raise SinjaError, 'Resource locator not defined!'
347
350
  end
348
351
 
349
352
  raise NotFoundError, "Resource '#{id}' not found" unless resource
@@ -83,6 +83,7 @@ module Sinja
83
83
  }}.curry
84
84
 
85
85
  @resource_config = Hash.new { |h, k| h[k] = {
86
+ :route_opts=>{ :pkre=>/\d+/ },
86
87
  :resource=>Hash.new(&action_proc[:resource]),
87
88
  :has_many=>Hash.new { |rh, rk| rh[rk] = Hash.new(&action_proc[:has_many]) },
88
89
  :has_one=>Hash.new { |rh, rk| rh[rk] = Hash.new(&action_proc[:has_one]) }
@@ -36,7 +36,12 @@ module Sinja
36
36
  end
37
37
 
38
38
  def serialize_response_body
39
- JSON.send settings._sinja.json_generator, response.body
39
+ case response.content_type[/^[^;]+/]
40
+ when *[mime_type(:api_json), mime_type(:json), mime_type(:javascript)].freeze
41
+ JSON.send(settings._sinja.json_generator, response.body)
42
+ else
43
+ Array(response.body).map!(&:to_s)
44
+ end
40
45
  rescue JSON::GeneratorError
41
46
  raise BadRequestError, 'Unserializable entities in the response body'
42
47
  end
@@ -89,7 +89,7 @@ module Sinja
89
89
 
90
90
  config = _resource_config[rel_type][rel] # trigger default proc
91
91
 
92
- namespace %r{/[^/]+(?<r>/relationships)?/#{rel}(?![^/])} do
92
+ namespace %r{/#{_resource_config[:route_opts][:pkre]}(?<r>/relationships)?/#{rel}(?![^/])} do
93
93
  define_singleton_method(:resource_config) { config }
94
94
 
95
95
  helpers Helpers::Nested do
@@ -82,17 +82,19 @@ module Sinja
82
82
  end
83
83
  end
84
84
 
85
- app.options '/:id' do
85
+ pkre = app._resource_config[:route_opts][:pkre]
86
+
87
+ app.options %r{/#{pkre}} do
86
88
  allow :get=>:show, :patch=>:update, :delete=>:destroy
87
89
  end
88
90
 
89
- app.get '/:id', :qparams=>%i[include fields], :actions=>:show do |id|
91
+ app.get %r{/(#{pkre})}, :qparams=>%i[include fields], :actions=>:show do |id|
90
92
  tmp, opts = show(*[].tap { |a| a << id unless respond_to?(:find) })
91
93
  raise NotFoundError, "Resource '#{id}' not found" unless tmp
92
94
  serialize_model(tmp, opts)
93
95
  end
94
96
 
95
- app.patch '/:id', :qparams=>%i[include fields], :actions=>:update do |id|
97
+ app.patch %r{/(#{pkre})}, :qparams=>%i[include fields], :actions=>:update do |id|
96
98
  sanity_check!(id)
97
99
  tmp, opts = transaction do
98
100
  update(attributes).tap do
@@ -103,7 +105,7 @@ module Sinja
103
105
  serialize_model?(tmp, opts)
104
106
  end
105
107
 
106
- app.delete '/:id', :actions=>:destroy do |id|
108
+ app.delete %r{/#{pkre}}, :actions=>:destroy do
107
109
  _, opts = destroy
108
110
  serialize_model?(nil, opts)
109
111
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Sinja
3
- VERSION = '1.2.4'
3
+ VERSION = '1.2.5'
4
4
  end
@@ -37,18 +37,18 @@ Gem::Specification.new do |spec|
37
37
 
38
38
  spec.required_ruby_version = '>= 2.3.0'
39
39
 
40
- spec.add_dependency 'activesupport', ">= #{ENV.fetch('rails', '4.2.7.1')}", '< 6'
40
+ spec.add_dependency 'activesupport', '>= 4.2.8', '< 6'
41
41
  spec.add_dependency 'json', '>= 1.8.3', '< 3'
42
- spec.add_dependency 'jsonapi-serializers', '~> 0.16'
43
- spec.add_dependency 'mustermann', '>= 1.0.0.beta2', '< 2'
44
- spec.add_dependency 'sinatra', ">= #{ENV.fetch('sinatra', '1.4.7')}", '< 3'
45
- spec.add_dependency 'sinatra-contrib', ">= #{ENV.fetch('sinatra', '1.4.7')}", '< 3'
42
+ spec.add_dependency 'jsonapi-serializers', '>= 0.16.2', '< 2'
43
+ spec.add_dependency 'sinatra', '>= 2.0.0.rc1', '< 3'
44
+ spec.add_dependency 'sinatra-contrib', '>= 2.0.0.rc1', '< 3'
46
45
 
47
46
  spec.add_development_dependency 'bundler', '~> 1.11'
48
47
  spec.add_development_dependency 'jdbc-sqlite3', '~> 3.8' if defined?(JRUBY_VERSION)
49
48
  spec.add_development_dependency 'minitest', '~> 5.9'
50
49
  spec.add_development_dependency 'minitest-hooks', '~> 1.4'
51
50
  #spec.add_development_dependency 'munson', '~> 0.4' # in Gemfile
51
+ spec.add_development_dependency 'rack-test', '~> 0.6'
52
52
  spec.add_development_dependency 'rake', '~> 12.0'
53
53
  spec.add_development_dependency 'sequel', '~> 4.41'
54
54
  #spec.add_development_dependency 'sinja-sequel', '~> 0.1' # in Gemfile
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinja
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Pastore
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-13 00:00:00.000000000 Z
11
+ date: 2017-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.7.1
19
+ version: 4.2.8
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '6'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 4.2.7.1
29
+ version: 4.2.8
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '6'
@@ -52,25 +52,11 @@ dependencies:
52
52
  version: '3'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: jsonapi-serializers
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: '0.16'
60
- type: :runtime
61
- prerelease: false
62
- version_requirements: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - "~>"
65
- - !ruby/object:Gem::Version
66
- version: '0.16'
67
- - !ruby/object:Gem::Dependency
68
- name: mustermann
69
55
  requirement: !ruby/object:Gem::Requirement
70
56
  requirements:
71
57
  - - ">="
72
58
  - !ruby/object:Gem::Version
73
- version: 1.0.0.beta2
59
+ version: 0.16.2
74
60
  - - "<"
75
61
  - !ruby/object:Gem::Version
76
62
  version: '2'
@@ -80,7 +66,7 @@ dependencies:
80
66
  requirements:
81
67
  - - ">="
82
68
  - !ruby/object:Gem::Version
83
- version: 1.0.0.beta2
69
+ version: 0.16.2
84
70
  - - "<"
85
71
  - !ruby/object:Gem::Version
86
72
  version: '2'
@@ -90,7 +76,7 @@ dependencies:
90
76
  requirements:
91
77
  - - ">="
92
78
  - !ruby/object:Gem::Version
93
- version: 1.4.7
79
+ version: 2.0.0.rc1
94
80
  - - "<"
95
81
  - !ruby/object:Gem::Version
96
82
  version: '3'
@@ -100,7 +86,7 @@ dependencies:
100
86
  requirements:
101
87
  - - ">="
102
88
  - !ruby/object:Gem::Version
103
- version: 1.4.7
89
+ version: 2.0.0.rc1
104
90
  - - "<"
105
91
  - !ruby/object:Gem::Version
106
92
  version: '3'
@@ -110,7 +96,7 @@ dependencies:
110
96
  requirements:
111
97
  - - ">="
112
98
  - !ruby/object:Gem::Version
113
- version: 1.4.7
99
+ version: 2.0.0.rc1
114
100
  - - "<"
115
101
  - !ruby/object:Gem::Version
116
102
  version: '3'
@@ -120,7 +106,7 @@ dependencies:
120
106
  requirements:
121
107
  - - ">="
122
108
  - !ruby/object:Gem::Version
123
- version: 1.4.7
109
+ version: 2.0.0.rc1
124
110
  - - "<"
125
111
  - !ruby/object:Gem::Version
126
112
  version: '3'
@@ -166,6 +152,20 @@ dependencies:
166
152
  - - "~>"
167
153
  - !ruby/object:Gem::Version
168
154
  version: '1.4'
155
+ - !ruby/object:Gem::Dependency
156
+ name: rack-test
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - "~>"
160
+ - !ruby/object:Gem::Version
161
+ version: '0.6'
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - "~>"
167
+ - !ruby/object:Gem::Version
168
+ version: '0.6'
169
169
  - !ruby/object:Gem::Dependency
170
170
  name: rake
171
171
  requirement: !ruby/object:Gem::Requirement