jsonapionify 0.11.11 → 0.12.0

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.
Files changed (46) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +3 -0
  3. data/examples/example_api.rb +80 -0
  4. data/jsonapionify.gemspec +1 -0
  5. data/lib/jsonapionify/api/action/documentation.rb +2 -2
  6. data/lib/jsonapionify/api/attribute.rb +3 -2
  7. data/lib/jsonapionify/api/context.rb +8 -3
  8. data/lib/jsonapionify/api/context_delegate.rb +6 -0
  9. data/lib/jsonapionify/api/relationship.rb +5 -10
  10. data/lib/jsonapionify/api/relationship/many.rb +46 -14
  11. data/lib/jsonapionify/api/relationship/one.rb +31 -8
  12. data/lib/jsonapionify/api/resource.rb +3 -6
  13. data/lib/jsonapionify/api/resource/builders/fields_builder.rb +2 -2
  14. data/lib/jsonapionify/api/resource/builders/relationship_builder.rb +3 -2
  15. data/lib/jsonapionify/api/resource/builders/relationships_builder.rb +3 -2
  16. data/lib/jsonapionify/api/resource/caching.rb +1 -4
  17. data/lib/jsonapionify/api/resource/callbacks.rb +60 -0
  18. data/lib/jsonapionify/api/resource/caller.rb +8 -7
  19. data/lib/jsonapionify/api/resource/defaults/actions.rb +15 -12
  20. data/lib/jsonapionify/api/resource/defaults/hooks.rb +10 -57
  21. data/lib/jsonapionify/api/resource/defaults/options.rb +3 -8
  22. data/lib/jsonapionify/api/resource/defaults/params.rb +0 -2
  23. data/lib/jsonapionify/api/resource/defaults/request_contexts.rb +24 -29
  24. data/lib/jsonapionify/api/resource/defaults/response_contexts.rb +11 -18
  25. data/lib/jsonapionify/api/resource/definitions/actions.rb +38 -22
  26. data/lib/jsonapionify/api/resource/definitions/attributes.rb +2 -2
  27. data/lib/jsonapionify/api/resource/definitions/helpers.rb +1 -1
  28. data/lib/jsonapionify/api/resource/definitions/includes.rb +16 -0
  29. data/lib/jsonapionify/api/resource/definitions/pagination.rb +7 -11
  30. data/lib/jsonapionify/api/resource/definitions/params.rb +19 -26
  31. data/lib/jsonapionify/api/resource/definitions/relationships.rb +3 -3
  32. data/lib/jsonapionify/api/resource/definitions/request_headers.rb +14 -16
  33. data/lib/jsonapionify/api/resource/definitions/response_headers.rb +2 -1
  34. data/lib/jsonapionify/api/resource/definitions/scopes.rb +17 -6
  35. data/lib/jsonapionify/api/resource/definitions/sorting.rb +8 -7
  36. data/lib/jsonapionify/api/resource/error_handling.rb +3 -2
  37. data/lib/jsonapionify/api/resource/exec.rb +3 -1
  38. data/lib/jsonapionify/api/resource/includer.rb +20 -51
  39. data/lib/jsonapionify/api/response.rb +3 -1
  40. data/lib/jsonapionify/callbacks.rb +10 -7
  41. data/lib/jsonapionify/destructured_proc.rb +27 -0
  42. data/lib/jsonapionify/structure/collections/base.rb +20 -8
  43. data/lib/jsonapionify/structure/objects/base.rb +11 -2
  44. data/lib/jsonapionify/structure/objects/resource_identifier.rb +9 -14
  45. data/lib/jsonapionify/version.rb +1 -1
  46. metadata +20 -2
@@ -1,5 +1,7 @@
1
1
  module JSONAPIonify::Api
2
2
  class Response
3
+ using JSONAPIonify::DestructuredProc
4
+
3
5
  attr_reader :action, :accept, :response_block, :status,
4
6
  :matcher, :content_type, :extension, :example_accept
5
7
 
@@ -39,7 +41,7 @@ module JSONAPIonify::Api
39
41
  status ||= self.status
40
42
  response = self
41
43
  instance.instance_eval do
42
- body = instance_exec(context, &response.response_block)
44
+ body = instance_exec(context, &response.response_block.destructure)
43
45
  Rack::Response.new.tap do |rack_response|
44
46
  rack_response.status = status
45
47
  response_headers.each do |k, v|
@@ -12,7 +12,7 @@ module JSONAPIonify
12
12
  before: "__#{name}_before_callback_chain",
13
13
  after: "__#{name}_after_callback_chain"
14
14
  }
15
- define_method chains[:main] do |*args, &block|
15
+ define_method chains[:main] do |*args, **, &block|
16
16
  block ||= proc {}
17
17
  if send(chains[:before], *args) != false
18
18
  value = instance_exec(*args, &block)
@@ -23,19 +23,22 @@ module JSONAPIonify
23
23
  # Define before and after chains
24
24
  %i{after before}.each do |timing|
25
25
  define_method chains[timing] { |*| } unless method_defined? chains[timing]
26
-
27
- define_singleton_method "#{timing}_#{name}" do |sym = nil, &outer_block|
26
+ callback_name = "#{timing}_#{name}"
27
+ define_singleton_method callback_name do |sym = nil, &outer_block|
28
28
  outer_block = (outer_block || sym).to_proc
29
29
  prev_chain = instance_method(chains[timing])
30
- define_method chains[timing] do |*args, &block|
31
- if prev_chain.bind(self).call(*args, &block) != false
32
- instance_exec(*args, &outer_block)
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
33
36
  end
34
37
  end
35
38
  end
36
39
  end
37
40
 
38
- private *chains.values
41
+ private(*chains.values)
39
42
 
40
43
  end
41
44
  end
@@ -0,0 +1,27 @@
1
+ module JSONAPIonify::DestructuredProc
2
+ refine Proc do
3
+ def destructure(at_index = arguments.length-1)
4
+ return self unless kwargs.present?
5
+ original = self
6
+ Proc.new do |*args|
7
+ kwargs = original.kwargs_destructured(args[at_index])
8
+ instance_exec(*args, **kwargs, &original)
9
+ end
10
+ end
11
+
12
+ def kwargs
13
+ parameters.select { |t, k| t.to_s.start_with? 'key' }
14
+ end
15
+
16
+ def arguments
17
+ parameters.reject { |t, k| t.to_s.start_with? 'key' }
18
+ end
19
+
20
+ def kwargs_destructured(target)
21
+ kwargs.each_with_object({}) do |(_, key), kw|
22
+ next unless target.respond_to? key
23
+ kw[key] = target.public_send(key)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -4,8 +4,7 @@ require 'concurrent'
4
4
 
5
5
  module JSONAPIonify::Structure
6
6
  module Collections
7
- class Base < Concurrent::Array
8
- include EnumerableObserver
7
+ class Base < Array
9
8
  include Helpers::InheritsOrigin
10
9
  attr_reader :parent
11
10
 
@@ -20,11 +19,6 @@ module JSONAPIonify::Structure
20
19
  value_is Objects::Base
21
20
 
22
21
  def initialize(array = [])
23
- observe.added do |items|
24
- items.each do |item|
25
- item.instance_variable_set(:@parent, self) unless item.frozen?
26
- end
27
- end
28
22
  array.each do |instance|
29
23
  self << instance
30
24
  end
@@ -82,7 +76,25 @@ module JSONAPIonify::Structure
82
76
  )
83
77
  end
84
78
  end
85
- super new_instance
79
+ self[length] = new_instance
80
+ end
81
+
82
+ def [] k
83
+ v = super
84
+ v.nil? || v.instance_variable_get(:@parent) == self ? v : self[k] = v
85
+ end
86
+
87
+ def []= k, v
88
+ unless v.nil? || v.instance_variable_get(:@parent) == self
89
+ v = v.dup.tap { |obj| obj.instance_variable_set :@parent, self}
90
+ end
91
+ super(k, v)
92
+ end
93
+
94
+ def each
95
+ length.times do |i|
96
+ yield self[i]
97
+ end
86
98
  end
87
99
 
88
100
  def errors
@@ -54,7 +54,7 @@ module JSONAPIonify::Structure
54
54
 
55
55
  # Initialize the object
56
56
  def initialize(**attributes)
57
- @object = Concurrent::Hash.new
57
+ @object = Hash.new
58
58
  run_callbacks :initialize do
59
59
  attributes.each do |k, v|
60
60
  self[k] = v
@@ -90,7 +90,7 @@ module JSONAPIonify::Structure
90
90
  end
91
91
 
92
92
  def to_json(**opts)
93
- Oj.dump(as_json **opts)
93
+ Oj.dump as_json(**opts)
94
94
  end
95
95
 
96
96
  def signature
@@ -155,6 +155,15 @@ module JSONAPIonify::Structure
155
155
  JSON.pretty_generate as_json
156
156
  end
157
157
 
158
+ def inspect
159
+ hash_inspect = to_h.to_s.gsub(
160
+ /\:([a-zA-Z_-]+)=>/, '\\1: '
161
+ )[1..-2].gsub(
162
+ /\{([^\s])/, '{ \\1').gsub(/([^\s])\}/, '\\1 }'
163
+ )
164
+ to_s.sub(/>$/, " #{hash_inspect}>")
165
+ end
166
+
158
167
  private
159
168
 
160
169
  def collect_child_errors
@@ -1,7 +1,8 @@
1
1
  module JSONAPIonify::Structure
2
2
  module Objects
3
3
  class ResourceIdentifier < Base
4
- define_order *%i{type id}
4
+
5
+ define_order :type, :id
5
6
 
6
7
  # A resource object **MUST** contain at least the following top-level members:
7
8
  must_contain! :id, :type # Describes ResourceObjects that share common attributes and relationships.
@@ -22,25 +23,19 @@ module JSONAPIonify::Structure
22
23
 
23
24
  def duplicate_exists?
24
25
  return false unless parent.is_a?(Array)
25
- peers = parent - [self]
26
- !!peers.index(self)
27
- end
28
-
29
- def ==(other)
30
- same_as? other
26
+ parent.select { |peer| peer.eql? self }.length > 1
31
27
  end
32
28
 
33
29
  def duplicate_does_not_exist?
34
30
  !duplicate_exists?
35
31
  end
36
32
 
37
- def same_as?(other)
38
- return false unless other.is_a? ResourceIdentifier
39
- other_type, other_id = other.values_at :type, :id
40
- local_type, local_id = values_at :type, :id
41
- other_type == local_type &&
42
- !(other_id || local_id).nil? &&
43
- other_id == local_id
33
+ def hash
34
+ { type: self[:type], id: self[:id] }.hash
35
+ end
36
+
37
+ def eql?(other)
38
+ other.hash == self.hash
44
39
  end
45
40
 
46
41
  end
@@ -1,3 +1,3 @@
1
1
  module JSONAPIonify
2
- VERSION = "0.11.11"
2
+ VERSION = "0.12.0"
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.11.11
4
+ version: 0.12.0
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-01 00:00:00.000000000 Z
11
+ date: 2016-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -206,6 +206,20 @@ dependencies:
206
206
  - - ! '>='
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: yard
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ! '>='
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ! '>='
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
209
223
  - !ruby/object:Gem::Dependency
210
224
  name: pry-byebug
211
225
  requirement: !ruby/object:Gem::Requirement
@@ -511,6 +525,7 @@ files:
511
525
  - bin/console
512
526
  - bin/setup
513
527
  - config.ru
528
+ - examples/example_api.rb
514
529
  - index.html
515
530
  - jsonapionify.gemspec
516
531
  - lib/core_ext/boolean.rb
@@ -552,6 +567,7 @@ files:
552
567
  - lib/jsonapionify/api/resource/builders/resource_builder.rb
553
568
  - lib/jsonapionify/api/resource/builders/resource_identifer_builder.rb
554
569
  - lib/jsonapionify/api/resource/caching.rb
570
+ - lib/jsonapionify/api/resource/callbacks.rb
555
571
  - lib/jsonapionify/api/resource/caller.rb
556
572
  - lib/jsonapionify/api/resource/class_methods.rb
557
573
  - lib/jsonapionify/api/resource/defaults.rb
@@ -567,6 +583,7 @@ files:
567
583
  - lib/jsonapionify/api/resource/definitions/attributes.rb
568
584
  - lib/jsonapionify/api/resource/definitions/contexts.rb
569
585
  - lib/jsonapionify/api/resource/definitions/helpers.rb
586
+ - lib/jsonapionify/api/resource/definitions/includes.rb
570
587
  - lib/jsonapionify/api/resource/definitions/pagination.rb
571
588
  - lib/jsonapionify/api/resource/definitions/params.rb
572
589
  - lib/jsonapionify/api/resource/definitions/relationships.rb
@@ -591,6 +608,7 @@ files:
591
608
  - lib/jsonapionify/character_range.rb
592
609
  - lib/jsonapionify/continuation.rb
593
610
  - lib/jsonapionify/deep_sort_collection.rb
611
+ - lib/jsonapionify/destructured_proc.rb
594
612
  - lib/jsonapionify/documentation.rb
595
613
  - lib/jsonapionify/documentation/template.erb
596
614
  - lib/jsonapionify/indented_string.rb