jsonapi-resources 0.9.12 → 0.10.7

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +34 -11
  4. data/lib/bug_report_templates/rails_5_latest.rb +125 -0
  5. data/lib/bug_report_templates/rails_5_master.rb +140 -0
  6. data/lib/jsonapi/active_relation/adapters/join_left_active_record_adapter.rb +27 -0
  7. data/lib/jsonapi/active_relation/join_manager.rb +303 -0
  8. data/lib/jsonapi/active_relation_resource.rb +884 -0
  9. data/lib/jsonapi/acts_as_resource_controller.rb +122 -106
  10. data/lib/jsonapi/basic_resource.rb +1162 -0
  11. data/lib/jsonapi/cached_response_fragment.rb +127 -0
  12. data/lib/jsonapi/compiled_json.rb +11 -1
  13. data/lib/jsonapi/configuration.rb +57 -8
  14. data/lib/jsonapi/error.rb +27 -0
  15. data/lib/jsonapi/error_codes.rb +2 -0
  16. data/lib/jsonapi/exceptions.rb +63 -40
  17. data/lib/jsonapi/formatter.rb +3 -3
  18. data/lib/jsonapi/include_directives.rb +18 -75
  19. data/lib/jsonapi/link_builder.rb +18 -25
  20. data/lib/jsonapi/operation.rb +16 -5
  21. data/lib/jsonapi/operation_result.rb +73 -15
  22. data/lib/jsonapi/paginator.rb +17 -0
  23. data/lib/jsonapi/path.rb +43 -0
  24. data/lib/jsonapi/path_segment.rb +76 -0
  25. data/lib/jsonapi/processor.rb +246 -111
  26. data/lib/jsonapi/relationship.rb +117 -24
  27. data/lib/jsonapi/request_parser.rb +383 -396
  28. data/lib/jsonapi/resource.rb +3 -1376
  29. data/lib/jsonapi/resource_controller_metal.rb +3 -0
  30. data/lib/jsonapi/resource_fragment.rb +47 -0
  31. data/lib/jsonapi/resource_id_tree.rb +112 -0
  32. data/lib/jsonapi/resource_identity.rb +42 -0
  33. data/lib/jsonapi/resource_serializer.rb +124 -286
  34. data/lib/jsonapi/resource_set.rb +176 -0
  35. data/lib/jsonapi/resources/railtie.rb +9 -0
  36. data/lib/jsonapi/resources/version.rb +1 -1
  37. data/lib/jsonapi/response_document.rb +104 -87
  38. data/lib/jsonapi/routing_ext.rb +19 -21
  39. data/lib/jsonapi-resources.rb +20 -4
  40. data/lib/tasks/check_upgrade.rake +52 -0
  41. metadata +34 -31
  42. data/lib/jsonapi/cached_resource_fragment.rb +0 -127
  43. data/lib/jsonapi/operation_dispatcher.rb +0 -88
  44. data/lib/jsonapi/operation_results.rb +0 -35
  45. data/lib/jsonapi/relationship_builder.rb +0 -167
@@ -10,6 +10,9 @@ module JSONAPI
10
10
  JSONAPI::ActsAsResourceController
11
11
  ].compact.freeze
12
12
 
13
+ # Note, the url_helpers are not loaded. This will prevent links from being generated for resources, and warnings
14
+ # will be emitted. Link support can be added by including `Rails.application.routes.url_helpers`, and links
15
+ # can be disabled, and warning suppressed, for a resource with `exclude_links :default`
13
16
  MODULES.each do |mod|
14
17
  include mod
15
18
  end
@@ -0,0 +1,47 @@
1
+ module JSONAPI
2
+
3
+ # A ResourceFragment holds a ResourceIdentity and associated partial resource data.
4
+ #
5
+ # The following partial resource data may be stored
6
+ # cache - the value of the cache field for the resource instance
7
+ # related - a hash of arrays of related resource identities, grouped by relationship name
8
+ # related_from - a set of related resource identities that loaded the fragment
9
+ #
10
+ # Todo: optionally use these for faster responses by bypassing model instantiation)
11
+ # attributes - resource attributes
12
+
13
+ class ResourceFragment
14
+ attr_reader :identity, :attributes, :related_from, :related
15
+
16
+ attr_accessor :primary, :cache
17
+
18
+ alias :cache_field :cache #ToDo: Rename one or the other
19
+
20
+ def initialize(identity)
21
+ @identity = identity
22
+ @cache = nil
23
+ @attributes = {}
24
+ @related = {}
25
+ @primary = false
26
+ @related_from = Set.new
27
+ end
28
+
29
+ def initialize_related(relationship_name)
30
+ @related ||= {}
31
+ @related[relationship_name.to_sym] ||= Set.new
32
+ end
33
+
34
+ def add_related_identity(relationship_name, identity)
35
+ initialize_related(relationship_name)
36
+ @related[relationship_name.to_sym] << identity
37
+ end
38
+
39
+ def add_related_from(identity)
40
+ @related_from << identity
41
+ end
42
+
43
+ def add_attribute(name, value)
44
+ @attributes[name] = value
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,112 @@
1
+ module JSONAPI
2
+
3
+ # A tree structure representing the resource structure of the requested resource(s). This is an intermediate structure
4
+ # used to keep track of the resources, by identity, found at different included relationships. It will be flattened and
5
+ # the resource instances will be fetched from the cache or the record store.
6
+ class ResourceIdTree
7
+
8
+ attr_reader :fragments, :related_resource_id_trees
9
+
10
+ # Gets the related Resource Id Tree for a relationship, and creates it first if it does not exist
11
+ #
12
+ # @param relationship [JSONAPI::Relationship]
13
+ #
14
+ # @return [JSONAPI::RelatedResourceIdTree] the new or existing resource id tree for the requested relationship
15
+ def fetch_related_resource_id_tree(relationship)
16
+ relationship_name = relationship.name.to_sym
17
+ @related_resource_id_trees[relationship_name] ||= RelatedResourceIdTree.new(relationship, self)
18
+ end
19
+
20
+ private
21
+
22
+ def init_included_relationships(fragment, include_related)
23
+ include_related && include_related.each_key do |relationship_name|
24
+ fragment.initialize_related(relationship_name)
25
+ end
26
+ end
27
+ end
28
+
29
+ class PrimaryResourceIdTree < ResourceIdTree
30
+
31
+ # Creates a PrimaryResourceIdTree with no resources and no related ResourceIdTrees
32
+ def initialize
33
+ @fragments ||= {}
34
+ @related_resource_id_trees ||= {}
35
+ end
36
+
37
+ # Adds each Resource Fragment to the Resources hash
38
+ #
39
+ # @param fragments [Hash]
40
+ # @param include_related [Hash]
41
+ #
42
+ # @return [null]
43
+ def add_resource_fragments(fragments, include_related)
44
+ fragments.each_value do |fragment|
45
+ add_resource_fragment(fragment, include_related)
46
+ end
47
+ end
48
+
49
+ # Adds a Resource Fragment to the Resources hash
50
+ #
51
+ # @param fragment [JSONAPI::ResourceFragment]
52
+ # @param include_related [Hash]
53
+ #
54
+ # @return [null]
55
+ def add_resource_fragment(fragment, include_related)
56
+ fragment.primary = true
57
+
58
+ init_included_relationships(fragment, include_related)
59
+
60
+ @fragments[fragment.identity] = fragment
61
+ end
62
+ end
63
+
64
+ class RelatedResourceIdTree < ResourceIdTree
65
+
66
+ attr_reader :parent_relationship, :source_resource_id_tree
67
+
68
+ # Creates a RelatedResourceIdTree with no resources and no related ResourceIdTrees. A connection to the parent
69
+ # ResourceIdTree is maintained.
70
+ #
71
+ # @param parent_relationship [JSONAPI::Relationship]
72
+ # @param source_resource_id_tree [JSONAPI::ResourceIdTree]
73
+ #
74
+ # @return [JSONAPI::RelatedResourceIdTree] the new or existing resource id tree for the requested relationship
75
+ def initialize(parent_relationship, source_resource_id_tree)
76
+ @fragments ||= {}
77
+ @related_resource_id_trees ||= {}
78
+
79
+ @parent_relationship = parent_relationship
80
+ @parent_relationship_name = parent_relationship.name.to_sym
81
+ @source_resource_id_tree = source_resource_id_tree
82
+ end
83
+
84
+ # Adds each Resource Fragment to the Resources hash
85
+ #
86
+ # @param fragments [Hash]
87
+ # @param include_related [Hash]
88
+ #
89
+ # @return [null]
90
+ def add_resource_fragments(fragments, include_related)
91
+ fragments.each_value do |fragment|
92
+ add_resource_fragment(fragment, include_related)
93
+ end
94
+ end
95
+
96
+ # Adds a Resource Fragment to the fragments hash
97
+ #
98
+ # @param fragment [JSONAPI::ResourceFragment]
99
+ # @param include_related [Hash]
100
+ #
101
+ # @return [null]
102
+ def add_resource_fragment(fragment, include_related)
103
+ init_included_relationships(fragment, include_related)
104
+
105
+ fragment.related_from.each do |rid|
106
+ @source_resource_id_tree.fragments[rid].add_related_identity(parent_relationship.name, fragment.identity)
107
+ end
108
+
109
+ @fragments[fragment.identity] = fragment
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,42 @@
1
+ module JSONAPI
2
+
3
+ # ResourceIdentity describes a unique identity of a resource in the system.
4
+ # This consists of a Resource class and an identifier that is unique within
5
+ # that Resource class. ResourceIdentities are intended to be used as hash
6
+ # keys to provide ordered mixing of resource types in result sets.
7
+ #
8
+ #
9
+ # == Creating a ResourceIdentity
10
+ #
11
+ # rid = ResourceIdentity.new(PostResource, 12)
12
+ #
13
+ class ResourceIdentity
14
+ attr_reader :resource_klass, :id
15
+
16
+ def initialize(resource_klass, id)
17
+ @resource_klass = resource_klass
18
+ @id = id
19
+ end
20
+
21
+ def ==(other)
22
+ # :nocov:
23
+ eql?(other)
24
+ # :nocov:
25
+ end
26
+
27
+ def eql?(other)
28
+ other.is_a?(ResourceIdentity) && other.resource_klass == @resource_klass && other.id == @id
29
+ end
30
+
31
+ def hash
32
+ [@resource_klass, @id].hash
33
+ end
34
+
35
+ # Creates a string representation of the identifier.
36
+ def to_s
37
+ # :nocov:
38
+ "#{resource_klass}:#{id}"
39
+ # :nocov:
40
+ end
41
+ end
42
+ end