jsonapi-resources 0.9.0 → 0.10.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  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 -105
  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 +71 -8
  14. data/lib/jsonapi/error.rb +27 -0
  15. data/lib/jsonapi/error_codes.rb +2 -0
  16. data/lib/jsonapi/exceptions.rb +80 -50
  17. data/lib/jsonapi/formatter.rb +3 -3
  18. data/lib/jsonapi/include_directives.rb +18 -65
  19. data/lib/jsonapi/link_builder.rb +74 -80
  20. data/lib/jsonapi/operation.rb +16 -5
  21. data/lib/jsonapi/operation_result.rb +74 -16
  22. data/lib/jsonapi/path.rb +43 -0
  23. data/lib/jsonapi/path_segment.rb +76 -0
  24. data/lib/jsonapi/processor.rb +239 -111
  25. data/lib/jsonapi/relationship.rb +153 -15
  26. data/lib/jsonapi/request_parser.rb +430 -367
  27. data/lib/jsonapi/resource.rb +3 -1253
  28. data/lib/jsonapi/resource_controller_metal.rb +5 -2
  29. data/lib/jsonapi/resource_fragment.rb +47 -0
  30. data/lib/jsonapi/resource_id_tree.rb +112 -0
  31. data/lib/jsonapi/resource_identity.rb +42 -0
  32. data/lib/jsonapi/resource_serializer.rb +143 -285
  33. data/lib/jsonapi/resource_set.rb +176 -0
  34. data/lib/jsonapi/resources/railtie.rb +9 -0
  35. data/lib/jsonapi/resources/version.rb +1 -1
  36. data/lib/jsonapi/response_document.rb +105 -83
  37. data/lib/jsonapi/routing_ext.rb +48 -26
  38. data/lib/jsonapi-resources.rb +20 -4
  39. data/lib/tasks/check_upgrade.rake +52 -0
  40. metadata +50 -20
  41. data/lib/jsonapi/cached_resource_fragment.rb +0 -127
  42. data/lib/jsonapi/operation_dispatcher.rb +0 -88
  43. data/lib/jsonapi/operation_results.rb +0 -35
  44. data/lib/jsonapi/relationship_builder.rb +0 -167
@@ -5,11 +5,14 @@ module JSONAPI
5
5
  ActionController::Rendering,
6
6
  ActionController::Renderers::All,
7
7
  ActionController::StrongParameters,
8
- ActionController::ForceSSL,
8
+ Gem::Requirement.new('< 6.1').satisfied_by?(ActionPack.gem_version) ? ActionController::ForceSSL : nil,
9
9
  ActionController::Instrumentation,
10
10
  JSONAPI::ActsAsResourceController
11
- ].freeze
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