jsonapionify 0.12.2 → 0.12.3

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZmQ3YjE5OTkyNWI2NmNhMGYxNzUzMGI0ZjRiMGYyYzM4M2QzYzE1Nw==
4
+ MWNlMTA2NTM0YmE2ODY1NjgxYzZkZDdkZWI1YTI5NTA5ZjA4YmM0OA==
5
5
  data.tar.gz: !binary |-
6
- NWJlZmI1N2Q5ZmY4MTk0ZmFlOTE5MGZjYzQwYjA1OWZhNDc1NDA0Mg==
6
+ MjllZmNlOGU1NmU1Nzk1YjZlZDYxODMxNThiZWQyYzA5NTVhMDc2Yg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MDc2YjgxMjIwZDQ5YTI4ZDdhNjAwZGM3NDdiODA0NDk4YTM5MjI0NDM0YzVl
10
- MjZmNjdlNTkwYzIzY2VhZjVjNDdhN2I5NDE5ZmYzYWZmZGI3NDJlZDQxOWQ2
11
- ZGUxN2QwNWExZDdhNThlNmRiNTcyNTE5MGU2NjJiMzBiY2Q1NmY=
9
+ Y2RlOTA5MDI3MGQ5M2U2MjAwZGJjMTNiOGNjMjFiOTU2ZmM5YzFlOTRiMDc0
10
+ MGRjMGJiN2NhZDkyODI2Y2VmNmUxNzE2MThmNjcxOWIzZDE0YjllZTFkYTFj
11
+ N2Q0YTQ3NTQyY2FkMDQxN2Y2YTE3NTI2OTIwNThhNGVjNjk1YjE=
12
12
  data.tar.gz: !binary |-
13
- YWRjZTIwNTYyNjk5ZGMzMjRiZDM1OGNkZTgzMmVmOWFlZjE5NTQwYTM0NmJj
14
- NTVmM2U1NjNhZDAwNmI0ZGJlYzZlZGY1NDU1ODk3MTczZDFhMjQ1NDZlOWQx
15
- YjkzN2ViYzEzZDRlMjA1NTFmZDc1OTM3ZmQwZTQ1N2RkNjk2YzU=
13
+ Y2FmODhmNzdhOTAwNjVmNWMzNDU4MDdlNDZiNzQ3YzlkNDY2NjQyYzRjNmE0
14
+ NDEyNTU1MzRiN2FkMzZkNGE2NzAyODVkZjNlMDJmNDlmMzg4ODA2ZDUzYWRm
15
+ OTZkMmYxZjVmOTVkYjliYWZlOWMwNmEyZGYwNzRmODgxZjA4N2I=
@@ -61,11 +61,11 @@ module JSONAPIonify::Api
61
61
  collection_context = proc do |context|
62
62
  3.times.map { resource.example_instance_for_action(action.name, context) }
63
63
  end
64
- defs[:_is_example_] = Context.new(readonly: true) { true }
65
- defs[:collection] = Context.new(&collection_context)
66
- defs[:paginated_collection] = Context.new { |collection:| collection }
67
- defs[:instance] = Context.new(readonly: true) { |collection:| collection.first }
68
- defs[:owner_context] = Context.new(readonly: true) { ContextDelegate::Mock.new } if defs.has_key? :owner_context
64
+ defs[:_is_example_] = Context.new(:_is_example_, readonly: true) { true }
65
+ defs[:collection] = Context.new(:collection, &collection_context)
66
+ defs[:paginated_collection] = Context.new(:paginated_collection) { |collection:| collection }
67
+ defs[:instance] = Context.new(:instance, readonly: true) { |collection:| collection.first }
68
+ defs[:owner_context] = Context.new(:owner_context, readonly: true) { ContextDelegate::Mock.new } if defs.has_key? :owner_context
69
69
  end
70
70
  end
71
71
 
@@ -3,6 +3,7 @@ require 'active_support/core_ext/module/delegation'
3
3
 
4
4
  module JSONAPIonify::Api
5
5
  class Base
6
+ extend ActiveSupport::DescendantsTracker
6
7
  extend JSONAPIonify::Autoload
7
8
  autoload_all
8
9
  extend AppBuilder
@@ -38,7 +38,7 @@ module JSONAPIonify::Api
38
38
  map "/" do
39
39
  use Rack::MethodOverride
40
40
  api.middleware.each do |args, block|
41
- use *args, &block
41
+ use(*args, &block)
42
42
  end
43
43
  run JSONAPIonify::Api::Server.new(api)
44
44
  end
@@ -2,7 +2,8 @@ module JSONAPIonify::Api
2
2
  class Context
3
3
  using JSONAPIonify::DestructuredProc
4
4
 
5
- def initialize(readonly: false, persisted: false, existing_context: nil, &block)
5
+ def initialize(name, readonly: false, persisted: false, existing_context: nil, &block)
6
+ @name = name.to_sym
6
7
  @readonly = readonly
7
8
  @persisted = persisted
8
9
  @existing_context = existing_context
@@ -12,11 +13,8 @@ module JSONAPIonify::Api
12
13
  def call(instance, delegate)
13
14
  existing_context = @existing_context || proc {}
14
15
  existing_block = proc { existing_context.call(instance, delegate) }
15
- begin
16
+ JSONAPIonify::CustomRescue.perform(remove: __FILE__, source: @block, formatter: ->(meta) { meta.source_location.join(':') + ":in context: `#{@name}''" }) do
16
17
  instance.instance_exec(delegate, existing_block, &@block.destructure(0))
17
- rescue => e
18
- e.backtrace.unshift @block.source_location.join(':') + ":in (context)"
19
- raise e
20
18
  end
21
19
  end
22
20
 
@@ -100,6 +100,7 @@ module JSONAPIonify::Api
100
100
  end
101
101
  end
102
102
 
103
+ list
103
104
  show
104
105
  end
105
106
  end
@@ -5,56 +5,11 @@ module JSONAPIonify::Api
5
5
  extend ActiveSupport::Concern
6
6
  using JSONAPIonify::DestructuredProc
7
7
  included do
8
+ include JSONAPIonify::Callbacks
8
9
 
9
- def self.define_callbacks(*names)
10
- names.each do |name|
11
- chains = {
12
- main: "__#{name}_callback_chain",
13
- before: "__#{name}_before_callback_chain",
14
- after: "__#{name}_after_callback_chain"
15
- }
16
- define_method chains[:main] do |*args, &block|
17
- block ||= proc {}
18
- if send(chains[:before], *args) != false
19
- value = begin
20
- instance_exec(*args, @__context, &block&.destructure)
21
- rescue => e
22
- e.backtrace.unshift block.source_location.join(':') + ":in `(callback)`"
23
- raise e
24
- end
25
- value if send(chains[:after], *args) != false
26
- end
27
- end unless method_defined? chains[:main]
28
-
29
- # Define before and after chains
30
- %i{after before}.each do |timing|
31
- define_method chains[timing] { |*| } unless method_defined? chains[timing]
32
- callback_name = "#{timing}_#{name}"
33
- define_singleton_method callback_name do |sym = nil, &outer_block|
34
- outer_block = (outer_block || sym).to_proc
35
- prev_chain = instance_method(chains[timing])
36
- define_method chains[timing] do |*args, &block|
37
- begin
38
- if prev_chain.bind(self).call(*args, @__context, &block&.destructure) != false
39
- instance_exec(*args, @__context, &outer_block&.destructure)
40
- end
41
- rescue => e
42
- e.backtrace.unshift outer_block.source_location.join(':') + ":in `(callback) #{callback_name}`"
43
- raise e
44
- end
45
- end
46
- end
47
- end
48
-
49
- private(*chains.values)
50
-
51
- end
10
+ define_callback_strategy do |*args, &block|
11
+ instance_exec(*args, @__context, &block.destructure)
52
12
  end
53
13
  end
54
-
55
- def run_callbacks(name, *args, &block)
56
- send("__#{name}_callback_chain", *args, &block)
57
- end
58
-
59
14
  end
60
15
  end
@@ -19,9 +19,15 @@ module JSONAPIonify::Api
19
19
  end
20
20
 
21
21
  def response_definition
22
- action.responses.find { |response| response.accept_with_matcher? @__context } ||
23
- action.responses.find { |response| response.accept_with_header? @__context } ||
24
- error_now(:not_acceptable)
22
+ extension = @__context.request.extension
23
+ responses = action.responses
24
+ response = nil
25
+ @__context.request.accept.each do |accept|
26
+ response = responses.find { |r| r.accept_with_matcher? @__context } ||
27
+ responses.find { |r| r.accept_with_header? accept: accept, extension: extension }
28
+ break if response
29
+ end
30
+ response || error_now(:not_acceptable)
25
31
  end
26
32
 
27
33
  private
@@ -10,6 +10,7 @@ module JSONAPIonify::Api
10
10
 
11
11
  def context(name, **opts, &block)
12
12
  self.context_definitions[name.to_sym] = Context.new(
13
+ name,
13
14
  **opts,
14
15
  existing_context: self.context_definitions[name.to_sym],
15
16
  &block
@@ -1,12 +1,13 @@
1
1
  module JSONAPIonify::Api
2
2
  module Resource::Definitions::Scopes
3
+ using JSONAPIonify::DestructuredProc
3
4
 
4
5
  def scope(&block)
5
6
  define_singleton_method(:current_scope) do
6
- instance_exec(OpenStruct.new, &block)
7
+ instance_exec(OpenStruct.new, &block.destructure)
7
8
  end
8
9
  context :scope do |context|
9
- instance_exec(context, &block)
10
+ instance_exec(context, &block.destructure)
10
11
  end
11
12
  end
12
13
 
@@ -14,16 +15,16 @@ module JSONAPIonify::Api
14
15
 
15
16
  def instance(&block)
16
17
  define_singleton_method(:find_instance) do |id|
17
- instance_exec(current_scope, id, OpenStruct.new, &block)
18
+ instance_exec(current_scope, id, OpenStruct.new, &block.destructure)
18
19
  end
19
20
  context :instance, persisted: true do |context, scope:, id:|
20
- instance_exec(scope, id, context, &block)
21
+ instance_exec(scope, id, context, &block.destructure)
21
22
  end
22
23
  end
23
24
 
24
25
  def collection(&block)
25
26
  context :collection do |context, scope:, includes:|
26
- collection = Object.new.instance_exec(scope, context, &block)
27
+ collection = instance_exec(scope, context, &block.destructure)
27
28
 
28
29
  # Compute includes manipulations
29
30
  self.class.include_definitions.select do |relationship, _|
@@ -40,10 +41,10 @@ module JSONAPIonify::Api
40
41
 
41
42
  def new_instance(&block)
42
43
  define_singleton_method(:build_instance) do
43
- Object.new.instance_exec(current_scope, &block)
44
+ Object.new.instance_exec(current_scope, &block.destructure)
44
45
  end
45
46
  context :new_instance, persisted: true, readonly: true do |context, scope:|
46
- Object.new.instance_exec(scope, context, &block)
47
+ Object.new.instance_exec(scope, context, &block.destructure)
47
48
  end
48
49
  end
49
50
  end
@@ -79,7 +79,7 @@ module JSONAPIonify::Api
79
79
  klass = self.class.const_get(klass_name) rescue nil
80
80
  klass ||= klass_name.constantize rescue nil
81
81
  klass
82
- end
82
+ end.compact
83
83
 
84
84
  # Loop until things are ordered
85
85
  while (result = out_of_order_class[klasses])
@@ -65,12 +65,8 @@ module JSONAPIonify::Api
65
65
  end
66
66
  end
67
67
 
68
- def accept_with_header?(context)
69
- context.request.accept.any? do |accept|
70
- self.accept == accept ||
71
- (self.accept == '*/*' && !context.request.extension) ||
72
- (accept == '*/*' && !context.request.extension)
73
- end
68
+ def accept_with_header?(accept:, extension:)
69
+ self.accept == accept || (self.accept == '*/*' && !extension) || (accept == '*/*' && !extension)
74
70
  end
75
71
 
76
72
  def accept_with_matcher?(context)
@@ -1,11 +1,16 @@
1
1
  require 'active_support/concern'
2
+ require 'unstrict_proc'
2
3
 
3
4
  module JSONAPIonify
4
5
  module Callbacks
5
6
  extend ActiveSupport::Concern
6
- included do
7
7
 
8
- def self.define_callbacks(*names)
8
+ module ClassMethods
9
+ def define_callback_strategy(&strategy)
10
+ define_method(:__callback_strategy, &strategy)
11
+ end
12
+
13
+ def define_callbacks(*names)
9
14
  names.each do |name|
10
15
  chains = {
11
16
  main: "__#{name}_callback_chain",
@@ -14,10 +19,12 @@ module JSONAPIonify
14
19
  }
15
20
  define_method chains[:main] do |*args, **, &block|
16
21
  block ||= proc {}
17
- if send(chains[:before], *args) != false
18
- value = instance_exec(*args, &block)
19
- value if send(chains[:after], *args) != false
20
- end
22
+ false != send(chains[:before], *args) &&
23
+ (value = JSONAPIonify::CustomRescue.perform(remove: __FILE__, source: block, formatter: ->(meta) { meta.source_location.join(':') + ":in callback: `run'" }) do
24
+ __callback_strategy(*args, &block) || true
25
+ end) &&
26
+ false != send(chains[:after], *args) &&
27
+ value
21
28
  end unless method_defined? chains[:main]
22
29
 
23
30
  # Define before and after chains
@@ -27,13 +34,11 @@ module JSONAPIonify
27
34
  define_singleton_method callback_name do |sym = nil, &outer_block|
28
35
  outer_block = (outer_block || sym).to_proc
29
36
  prev_chain = instance_method(chains[timing])
30
- define_method chains[timing] do |*args, **, &block|
31
- begin
32
- instance_exec(*args, &outer_block) if prev_chain.bind(self).call(*args, &block) != false
33
- rescue => e
34
- e.backtrace.unshift outer_block.source_location.join(':') + ":in `(callback) #{callback_name}`"
35
- raise e
36
- end
37
+ define_method chains[timing] do |*args, &block|
38
+ false != prev_chain.bind(self).call(*args, &block) &&
39
+ JSONAPIonify::CustomRescue.perform(remove: __FILE__, source: outer_block, formatter: ->(meta) { meta.source_location.join(':') + ":in callback: `#{timing}_#{name}'" }) do
40
+ __callback_strategy(*args, &outer_block)
41
+ end
37
42
  end
38
43
  end
39
44
  end
@@ -44,6 +49,12 @@ module JSONAPIonify
44
49
  end
45
50
  end
46
51
 
52
+ included do
53
+ define_callback_strategy do |*args, &block|
54
+ instance_exec(*args, &block)
55
+ end
56
+ end
57
+
47
58
  def run_callbacks(name, *args, &block)
48
59
  send("__#{name}_callback_chain", *args, &block)
49
60
  end
@@ -0,0 +1,38 @@
1
+ require 'unstrict_proc'
2
+
3
+ class JSONAPIonify::CustomRescue
4
+ using UnstrictProc
5
+
6
+ def self.perform(**opts, &block)
7
+ new(**opts, &block).perform
8
+ end
9
+
10
+ def initialize(remove: [], source: nil, formatter:, &block)
11
+ @block = block
12
+ @formatter = formatter
13
+ @source = source || block
14
+ @locs = Array.wrap remove
15
+ f, l = self.class.method(:perform).source_location
16
+ @locs << [f, l+1].join(':')
17
+ end
18
+
19
+ def source_location
20
+ source.source_location
21
+ end
22
+
23
+ def perform
24
+ @block.call
25
+ rescue => e
26
+ loc = [__FILE__, __LINE__-2].join(':')
27
+ formatted_value = @formatter.unstrict.call(Error.new(e, @source))
28
+ index = e.backtrace.index { |l| l.include? loc }
29
+ e.backtrace[index] = formatted_value if index && formatted_value
30
+ e.backtrace.delete_if { |l| @locs.any? { |rl| l.include? rl } }
31
+ raise e
32
+ end
33
+
34
+ class Error < Struct.new :error, :source
35
+ delegate :source_location, to: :source
36
+ end
37
+
38
+ end
@@ -5,16 +5,18 @@ module JSONAPIonify::DestructuredProc
5
5
  original = self
6
6
  Proc.new do |*args|
7
7
  kwargs = original.kwargs_destructured(args[at_index])
8
- instance_exec(*args, **kwargs, &original)
8
+ JSONAPIonify::CustomRescue.perform(remove: __FILE__, source: original, formatter: ->(meta) { meta.source_location.join(':') + ":in `block (destructured)'" }) do
9
+ instance_exec(*args, **kwargs, &original)
10
+ end
9
11
  end
10
12
  end
11
13
 
12
14
  def kwargs
13
- parameters.select { |t, k| t.to_s.start_with? 'key' }
15
+ parameters.select { |t, k| t.to_s.start_with?('key') && !t.to_s.end_with?('rest') }
14
16
  end
15
17
 
16
18
  def arguments
17
- parameters.reject { |t, k| t.to_s.start_with? 'key' }
19
+ parameters.reject { |t, k| t.to_s.start_with?('key') || t.to_s.end_with?('rest') }
18
20
  end
19
21
 
20
22
  def kwargs_destructured(target)
@@ -1,3 +1,3 @@
1
1
  module JSONAPIonify
2
- VERSION = "0.12.2"
2
+ VERSION = "0.12.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapionify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
4
+ version: 0.12.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Waldrip
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-05 00:00:00.000000000 Z
11
+ date: 2016-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -608,6 +608,7 @@ files:
608
608
  - lib/jsonapionify/callbacks.rb
609
609
  - lib/jsonapionify/character_range.rb
610
610
  - lib/jsonapionify/continuation.rb
611
+ - lib/jsonapionify/custom_rescue.rb
611
612
  - lib/jsonapionify/deep_sort_collection.rb
612
613
  - lib/jsonapionify/destructured_proc.rb
613
614
  - lib/jsonapionify/documentation.rb