sinja 0.1.0.beta1 → 0.1.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -1
- data/lib/sinatra/jsonapi/helpers/sequel.rb +21 -19
- data/lib/sinatra/jsonapi/helpers/serializers.rb +22 -2
- data/lib/sinatra/jsonapi/resource.rb +1 -1
- data/lib/sinatra/jsonapi/resource_routes.rb +3 -3
- data/lib/sinatra/jsonapi.rb +9 -2
- data/lib/sinja/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56256224f31086937e46be0e727db8ec8ae05cc7
|
4
|
+
data.tar.gz: a9216fc46b80a2d4aede971848d749859f7358f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6045cbbca2b859e33bc66730139b1e8fc6fe3fa5a95004c138c4d1f739a876148ea0eff2da525ab9a064fccee2e8d5aa0be5452d084f99b9fb2a9b5cb233ea6
|
7
|
+
data.tar.gz: e2bc9f2014b3ebc582705f636943f543a6e5ce096ca3916d631a77f8b7c1fe3582499deebc096504872ad9732f996027f954fd676e11e565049c2cab11a998af
|
data/README.md
CHANGED
@@ -81,6 +81,9 @@ resource :posts do
|
|
81
81
|
create do |attr|
|
82
82
|
Post.create(attr)
|
83
83
|
end
|
84
|
+
|
85
|
+
has_one :author
|
86
|
+
has_many :comments
|
84
87
|
end
|
85
88
|
|
86
89
|
freeze_jsonapi
|
@@ -92,6 +95,10 @@ all other JSON:API endpoints returning 404 or 405):
|
|
92
95
|
|
93
96
|
* `GET /posts`
|
94
97
|
* `GET /posts/<id>`
|
98
|
+
* `GET /posts/<id>/author`
|
99
|
+
* `GET /posts/<id>/comments`
|
100
|
+
* `GET /posts/<id>/relationships/author`
|
101
|
+
* `GET /posts/<id>/relationships/comments`
|
95
102
|
* `POST /posts`
|
96
103
|
|
97
104
|
Of course, "modular"-style Sinatra aplications require you to register the
|
@@ -267,6 +274,15 @@ end
|
|
267
274
|
and returns a serialized collection if non-empty, or the root metadata if
|
268
275
|
present, or a HTTP status 204.
|
269
276
|
|
277
|
+
**dedasherize**
|
278
|
+
: Takes a string or symbol and returns the string or symbol with any and all
|
279
|
+
dashes transliterated to underscores.
|
280
|
+
|
281
|
+
**dedasherize_names**
|
282
|
+
: Takes a hash and returns the hash with its keys dedasherized (deeply).
|
283
|
+
Useful for fixing up the hashes of attributes passed to the `create` and
|
284
|
+
`update` action helpers before they are passed on to ORM methods.
|
285
|
+
|
270
286
|
### Performance
|
271
287
|
|
272
288
|
Although there is some heavy metaprogramming happening at boot time, the end
|
@@ -384,7 +400,8 @@ below. Implicitly return the expected values as described below (as an array if
|
|
384
400
|
necessary) or use the `next` keyword (instead of `return` or `break`) to exit
|
385
401
|
the action helper. Return values marked with a question mark below may be
|
386
402
|
omitted entirely. Any helper may additionally return an options hash to pass
|
387
|
-
along to JSONAPI::
|
403
|
+
along to JSONAPI::Serializer.serialize (will be merged into the global
|
404
|
+
`serializer_opts` described above).
|
388
405
|
|
389
406
|
The `:include` and `:fields` query parameters are automatically passed through
|
390
407
|
to JSONAPI::Serializers. You may also use the special `:exclude` option to
|
@@ -26,36 +26,38 @@ module Sinatra::JSONAPI
|
|
26
26
|
[resource.pk, resource, opts]
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
29
|
+
# <= association, rios, extra_keys
|
30
|
+
def add_missing(*args)
|
31
|
+
add_remove(:add, :-, *args)
|
32
|
+
end
|
33
|
+
|
34
|
+
# <= association, rios, extra_keys
|
35
|
+
def remove_present(*args)
|
36
|
+
add_remove(:remove, :&, *args)
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
|
39
|
+
private
|
40
|
+
|
41
|
+
def add_remove(meth_prefix, operator, association, rios)
|
42
|
+
meth = "#{meth_prefix}_#{singularize(association)}".to_sym
|
42
43
|
transaction do
|
43
44
|
resource.lock!
|
44
|
-
venn(
|
45
|
-
|
45
|
+
venn(operator, association, rios) do |subresource, rio|
|
46
|
+
args = [subresource]
|
47
|
+
args.push(yield(rio)) if block_given?
|
48
|
+
resource.send(meth, *args)
|
46
49
|
end
|
47
50
|
resource.reload
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
51
|
-
private
|
52
|
-
|
53
54
|
def venn(operator, association, rios)
|
54
|
-
klass = resource.class.association_reflection(association) # get e.g. ProductType for :types
|
55
55
|
dataset = resource.send("#{association}_dataset")
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
klass = resource.class.association_reflection(association)
|
57
|
+
rios = rios.map { |rio| [rio[:id], rio] }.to_h
|
58
|
+
rios.keys.send(operator, dataset.select_map(klass.primary_key)).each do |id|
|
59
|
+
yield klass.with_pk!(id), rios[id]
|
60
|
+
end
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
@@ -6,8 +6,24 @@ require 'set'
|
|
6
6
|
module Sinatra::JSONAPI
|
7
7
|
module Helpers
|
8
8
|
module Serializers
|
9
|
+
def dedasherize(s=nil)
|
10
|
+
s.to_s.tr('-', '_').send(Symbol === s ? :to_sym : :itself)
|
11
|
+
end
|
12
|
+
|
13
|
+
def dedasherize_names(*args)
|
14
|
+
_dedasherize_names(*args).to_h
|
15
|
+
end
|
16
|
+
|
17
|
+
private def _dedasherize_names(hash={})
|
18
|
+
return enum_for(__callee__) unless block_given?
|
19
|
+
|
20
|
+
hash.each do |k, v|
|
21
|
+
yield dasherize(k), Hash === v ? dedasherize_names(v) : v
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
9
25
|
def deserialized_request_body
|
10
|
-
return {} unless
|
26
|
+
return {} unless content?
|
11
27
|
|
12
28
|
request.body.rewind
|
13
29
|
JSON.parse(request.body.read, :symbolize_names=>true)
|
@@ -40,6 +56,8 @@ module Sinatra::JSONAPI
|
|
40
56
|
def serialize_model(model=nil, options={})
|
41
57
|
options[:is_collection] = false
|
42
58
|
options[:skip_collection_check] = defined?(::Sequel) && model.is_a?(::Sequel::Model)
|
59
|
+
# TODO: This should allow a default include, take the param value if
|
60
|
+
# present, and support disabling passthru.
|
43
61
|
options[:include] ||= params[:include] unless params[:include].empty?
|
44
62
|
options[:fields] ||= params[:fields] unless params[:fields].empty?
|
45
63
|
|
@@ -61,6 +79,8 @@ module Sinatra::JSONAPI
|
|
61
79
|
|
62
80
|
def serialize_models(models=[], options={})
|
63
81
|
options[:is_collection] = true
|
82
|
+
# TODO: This should allow a default include, take the param value if
|
83
|
+
# present, and support disabling passthru.
|
64
84
|
options[:include] ||= params[:include] unless params[:include].empty?
|
65
85
|
options[:fields] ||= params[:fields] unless params[:fields].empty?
|
66
86
|
|
@@ -108,7 +128,7 @@ module Sinatra::JSONAPI
|
|
108
128
|
elsif detail = [*body].first
|
109
129
|
end
|
110
130
|
|
111
|
-
{
|
131
|
+
{ :title=>title, :detail=>detail }
|
112
132
|
end
|
113
133
|
|
114
134
|
def error_hash(title: nil, detail: nil, source: nil)
|
@@ -13,7 +13,7 @@ module Sinatra::JSONAPI
|
|
13
13
|
|
14
14
|
app.get '/:id', :actions=>:show do |id|
|
15
15
|
self.resource, opts = show(id)
|
16
|
-
not_found unless resource
|
16
|
+
not_found "Resource '#{id}' not found" unless resource
|
17
17
|
serialize_model(resource, opts)
|
18
18
|
end
|
19
19
|
|
@@ -44,7 +44,7 @@ module Sinatra::JSONAPI
|
|
44
44
|
app.patch '/:id', :actions=>%i[show update] do |id|
|
45
45
|
sanity_check!(id)
|
46
46
|
self.resource, = show(id)
|
47
|
-
not_found unless resource
|
47
|
+
not_found "Resource '#{id}' not found" unless resource
|
48
48
|
serialize_model?(transaction do
|
49
49
|
update(data.fetch(attributes, {})).tap do
|
50
50
|
dispatch_relationship_requests!(id, :method=>:patch)
|
@@ -54,7 +54,7 @@ module Sinatra::JSONAPI
|
|
54
54
|
|
55
55
|
app.delete '/:id', :actions=>%i[show destroy] do |id|
|
56
56
|
self.resource, = show(id)
|
57
|
-
not_found unless resource
|
57
|
+
not_found "Resource '#{id}' not found" unless resource
|
58
58
|
_, opts = destroy
|
59
59
|
serialize_model?(nil, opts)
|
60
60
|
end
|
data/lib/sinatra/jsonapi.rb
CHANGED
@@ -78,6 +78,10 @@ module Sinatra::JSONAPI
|
|
78
78
|
roles.nil? || roles.empty? || Set[*role].intersect?(roles)
|
79
79
|
end
|
80
80
|
|
81
|
+
def content?
|
82
|
+
request.body.respond_to?(:size) && request.body.size > 0
|
83
|
+
end
|
84
|
+
|
81
85
|
def data
|
82
86
|
@data ||= deserialized_request_body[:data]
|
83
87
|
end
|
@@ -104,8 +108,11 @@ module Sinatra::JSONAPI
|
|
104
108
|
|
105
109
|
app.before do
|
106
110
|
halt 406 unless request.preferred_type.entry == MIME_TYPE
|
107
|
-
|
108
|
-
|
111
|
+
|
112
|
+
if content?
|
113
|
+
halt 415 unless request.media_type == MIME_TYPE
|
114
|
+
halt 415 if request.media_type_params.keys.any? { |k| k != 'charset' }
|
115
|
+
end
|
109
116
|
|
110
117
|
content_type :api_json
|
111
118
|
|
data/lib/sinja/version.rb
CHANGED
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: 0.1.0.
|
4
|
+
version: 0.1.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Pastore
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|