graphiti-activegraph 1.3.1 → 1.3.2

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/specs.yml +58 -59
  3. data/.gitignore +59 -59
  4. data/.hound.yml +4 -0
  5. data/.rspec +1 -1
  6. data/.rubocop.yml +3 -0
  7. data/CHANGELOG.md +58 -54
  8. data/CHANGELOG_PRE_1.0.0.md +70 -70
  9. data/Gemfile +3 -3
  10. data/LICENSE.txt +21 -21
  11. data/README.md +130 -130
  12. data/docs/deserializer.md +40 -40
  13. data/graphiti-activegraph.gemspec +34 -34
  14. data/lib/graphiti/active_graph/adapters/active_graph/function_sideload.rb +7 -7
  15. data/lib/graphiti/active_graph/adapters/active_graph/has_many_sideload.rb +7 -7
  16. data/lib/graphiti/active_graph/adapters/active_graph/has_one_sideload.rb +7 -7
  17. data/lib/graphiti/active_graph/adapters/active_graph/polymorphic_belongs_to.rb +11 -11
  18. data/lib/graphiti/active_graph/adapters/active_graph/sideload.rb +26 -26
  19. data/lib/graphiti/active_graph/adapters/active_graph.rb +183 -183
  20. data/lib/graphiti/active_graph/concerns/path_relationships.rb +44 -44
  21. data/lib/graphiti/active_graph/concerns/relationships.rb +15 -15
  22. data/lib/graphiti/active_graph/deserializer.rb +138 -138
  23. data/lib/graphiti/active_graph/extensions/context.rb +17 -17
  24. data/lib/graphiti/active_graph/extensions/grouping/params.rb +101 -52
  25. data/lib/graphiti/active_graph/extensions/query_dsl/performer.rb +38 -38
  26. data/lib/graphiti/active_graph/extensions/query_dsl/query_generator.rb +20 -20
  27. data/lib/graphiti/active_graph/extensions/query_params.rb +27 -27
  28. data/lib/graphiti/active_graph/extensions/resources/authorizationable.rb +29 -29
  29. data/lib/graphiti/active_graph/extensions/resources/payload_combinable.rb +24 -24
  30. data/lib/graphiti/active_graph/extensions/resources/preloadable.rb +19 -19
  31. data/lib/graphiti/active_graph/extensions/resources/rel.rb +19 -19
  32. data/lib/graphiti/active_graph/jsonapi_ext/include_directive.rb +66 -66
  33. data/lib/graphiti/active_graph/jsonapi_ext/serializable/resource_ext.rb +8 -8
  34. data/lib/graphiti/active_graph/query.rb +76 -76
  35. data/lib/graphiti/active_graph/request_validators/validator.rb +9 -9
  36. data/lib/graphiti/active_graph/resource.rb +103 -103
  37. data/lib/graphiti/active_graph/resource_proxy.rb +86 -86
  38. data/lib/graphiti/active_graph/resources/interface.rb +14 -14
  39. data/lib/graphiti/active_graph/resources/persistence.rb +25 -25
  40. data/lib/graphiti/active_graph/runner.rb +39 -39
  41. data/lib/graphiti/active_graph/scope.rb +28 -28
  42. data/lib/graphiti/active_graph/scoping/association_eager_load.rb +34 -34
  43. data/lib/graphiti/active_graph/scoping/filter.rb +49 -49
  44. data/lib/graphiti/active_graph/scoping/filterable.rb +12 -12
  45. data/lib/graphiti/active_graph/scoping/include.rb +48 -48
  46. data/lib/graphiti/active_graph/scoping/internal/extra_field_normalizer.rb +76 -76
  47. data/lib/graphiti/active_graph/scoping/internal/include_normalizer.rb +82 -82
  48. data/lib/graphiti/active_graph/scoping/internal/path_descriptor.rb +94 -94
  49. data/lib/graphiti/active_graph/scoping/internal/sort_normalizer.rb +54 -54
  50. data/lib/graphiti/active_graph/scoping/internal/sorting_aliases.rb +35 -35
  51. data/lib/graphiti/active_graph/scoping/internal/sparse_fields_eagerloading.rb +28 -28
  52. data/lib/graphiti/active_graph/serializer.rb +15 -15
  53. data/lib/graphiti/active_graph/sideload_resolve.rb +119 -119
  54. data/lib/graphiti/active_graph/util/parsers/rel_chain.rb +27 -27
  55. data/lib/graphiti/active_graph/util/relationship_payload.rb +33 -33
  56. data/lib/graphiti/active_graph/util/serializer_attribute.rb +17 -17
  57. data/lib/graphiti/active_graph/util/serializer_relationship.rb +28 -28
  58. data/lib/graphiti/active_graph/util/transformers/relation_param.rb +56 -56
  59. data/lib/graphiti/active_graph/version.rb +5 -5
  60. data/lib/graphiti/sidepost_configuration.rb +9 -9
  61. data/lib/graphiti-activegraph.rb +43 -43
  62. metadata +5 -3
@@ -1,29 +1,29 @@
1
- module Graphiti::ActiveGraph::Extensions::Resources
2
- module Authorizationable
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- class << self
7
- attr_reader :authorize_attributes
8
- end
9
- end
10
-
11
- class_methods do
12
- def attribute_authorization
13
- @authorize_attributes = true
14
- end
15
-
16
- def authorize_attributes?
17
- @authorize_attributes
18
- end
19
-
20
- def readable_attributes
21
- attributes.select { |_attr_name, options_map| options_map[:readable] }
22
- end
23
-
24
- def readable_sideloads
25
- sideloads.select { |_sideloads_name, sideload_obj| sideload_obj.readable? }
26
- end
27
- end
28
- end
29
- end
1
+ module Graphiti::ActiveGraph::Extensions::Resources
2
+ module Authorizationable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class << self
7
+ attr_reader :authorize_attributes
8
+ end
9
+ end
10
+
11
+ class_methods do
12
+ def attribute_authorization
13
+ @authorize_attributes = true
14
+ end
15
+
16
+ def authorize_attributes?
17
+ @authorize_attributes
18
+ end
19
+
20
+ def readable_attributes
21
+ attributes.select { |_attr_name, options_map| options_map[:readable] }
22
+ end
23
+
24
+ def readable_sideloads
25
+ sideloads.select { |_sideloads_name, sideload_obj| sideload_obj.readable? }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,24 +1,24 @@
1
- module Graphiti::ActiveGraph::Extensions::Resources
2
- module PayloadCombinable
3
- extend ActiveSupport::Concern
4
-
5
- class_methods do
6
- def combine(attributes, relationships)
7
- attributes.merge(relationship_attributes(relationships))
8
- end
9
-
10
- def relationship_attributes(relationships)
11
- relationships.map { |k, v| [k, extract_ids(v)] }.to_h
12
- end
13
-
14
- def extract_ids(object)
15
- object.is_a?(Array) ? object.map { |o| extract_ids(o) } : object[:attributes][:id]
16
- end
17
-
18
- def remove_undeclared_attributes(attr_map)
19
- permitted_attrs = all_attributes.keys
20
- attr_map.select! { |attr_name, _value| permitted_attrs.include?(attr_name.to_sym) }
21
- end
22
- end
23
- end
24
- end
1
+ module Graphiti::ActiveGraph::Extensions::Resources
2
+ module PayloadCombinable
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def combine(attributes, relationships)
7
+ attributes.merge(relationship_attributes(relationships))
8
+ end
9
+
10
+ def relationship_attributes(relationships)
11
+ relationships.map { |k, v| [k, extract_ids(v)] }.to_h
12
+ end
13
+
14
+ def extract_ids(object)
15
+ object.is_a?(Array) ? object.map { |o| extract_ids(o) } : object[:attributes][:id]
16
+ end
17
+
18
+ def remove_undeclared_attributes(attr_map)
19
+ permitted_attrs = all_attributes.keys
20
+ attr_map.select! { |attr_name, _value| permitted_attrs.include?(attr_name.to_sym) }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,19 +1,19 @@
1
- module Graphiti::ActiveGraph::Extensions::Resources
2
- module Preloadable
3
- extend ActiveSupport::Concern
4
-
5
- class_methods do
6
- def with_preloaded_obj(obj, params)
7
- id = params[:data].try(:[], :id) || params.delete(:id)
8
- params[:filter] ||= {}
9
- params[:filter][:id] = id if id
10
-
11
- build(params, nil, raise_on_missing: false, preloaded: obj)
12
- end
13
-
14
- def all_with_preloaded(obj_arr, params)
15
- build(params, nil, single: false, raise_on_missing: false, preloaded: obj_arr)
16
- end
17
- end
18
- end
19
- end
1
+ module Graphiti::ActiveGraph::Extensions::Resources
2
+ module Preloadable
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def with_preloaded_obj(obj, params)
7
+ id = params[:data].try(:[], :id) || params.delete(:id)
8
+ params[:filter] ||= {}
9
+ params[:filter][:id] = id if id
10
+
11
+ build(params, nil, raise_on_missing: false, preloaded: obj)
12
+ end
13
+
14
+ def all_with_preloaded(obj_arr, params)
15
+ build(params, nil, single: false, raise_on_missing: false, preloaded: obj_arr)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,19 +1,19 @@
1
- module Graphiti::ActiveGraph::Extensions::Resources
2
- module Rel
3
- extend ActiveSupport::Concern
4
-
5
- def relation_resource?
6
- self.class.relation_resource?
7
- end
8
-
9
- class_methods do
10
- def relation_resource?
11
- config[:relation_resource] || false
12
- end
13
-
14
- def relationship_resource=(value)
15
- config[:relation_resource] = value
16
- end
17
- end
18
- end
19
- end
1
+ module Graphiti::ActiveGraph::Extensions::Resources
2
+ module Rel
3
+ extend ActiveSupport::Concern
4
+
5
+ def relation_resource?
6
+ self.class.relation_resource?
7
+ end
8
+
9
+ class_methods do
10
+ def relation_resource?
11
+ config[:relation_resource] || false
12
+ end
13
+
14
+ def relationship_resource=(value)
15
+ config[:relation_resource] = value
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,66 +1,66 @@
1
- module Graphiti::ActiveGraph::JsonapiExt
2
- class IncludeDirective < JSONAPI::IncludeDirective
3
- attr_accessor :length, :retain_rel_limit
4
-
5
- def initialize(include_args, options = {})
6
- include_hash = JSONAPI::IncludeDirective::Parser.parse_include_args(include_args)
7
- @retain_rel_limit = options.delete(:retain_rel_limit)
8
- @hash = formulate_hash(include_hash, options)
9
- @options = options
10
- end
11
-
12
- def keys
13
- super.select(&method(:key?))
14
- end
15
-
16
- alias get []
17
-
18
- def key?(key)
19
- super && get(key).valid_length?
20
- end
21
-
22
- def [](key)
23
- super&.descend(key) || {}
24
- end
25
-
26
- def descend(key)
27
- length && length != '' ? dup.tap { |dup| dup.add_self_reference(key, length.to_i - 1) } : self
28
- end
29
-
30
- def valid_length?
31
- length.nil? || length == '' || length.to_i.positive?
32
- end
33
-
34
- def to_hash
35
- @hash.each_with_object({}) do |(key, value), hash|
36
- key = "#{key}*#{value.length}".to_sym if value.length
37
- hash[key] = value.to_hash unless value == self
38
- end
39
- end
40
-
41
- def add_self_reference(key, length)
42
- @hash = @hash.merge(key => self)
43
- self.length = length
44
- end
45
-
46
- private
47
-
48
- def formulate_hash(include_hash, options)
49
- include_hash.each_with_object({}) do |(key, value), hash|
50
- rel_name, rel_length = extract_rel_meta(key)
51
-
52
- hash[rel_name] = self.class.new(value, options_with_retain_rel_limit(options)).tap do |directive|
53
- directive.add_self_reference(rel_name, rel_length) if key.to_s.match?(/.+\*(\d*)\z/)
54
- end
55
- end
56
- end
57
-
58
- def extract_rel_meta(key)
59
- Graphiti::ActiveGraph::Util::Transformers::RelationParam.new(key).split_rel_length(retain_rel_limit)
60
- end
61
-
62
- def options_with_retain_rel_limit(options)
63
- options.merge(retain_rel_limit:)
64
- end
65
- end
66
- end
1
+ module Graphiti::ActiveGraph::JsonapiExt
2
+ class IncludeDirective < JSONAPI::IncludeDirective
3
+ attr_accessor :length, :retain_rel_limit
4
+
5
+ def initialize(include_args, options = {})
6
+ include_hash = JSONAPI::IncludeDirective::Parser.parse_include_args(include_args)
7
+ @retain_rel_limit = options.delete(:retain_rel_limit)
8
+ @hash = formulate_hash(include_hash, options)
9
+ @options = options
10
+ end
11
+
12
+ def keys
13
+ super.select(&method(:key?))
14
+ end
15
+
16
+ alias get []
17
+
18
+ def key?(key)
19
+ super && get(key).valid_length?
20
+ end
21
+
22
+ def [](key)
23
+ super&.descend(key) || {}
24
+ end
25
+
26
+ def descend(key)
27
+ length && length != '' ? dup.tap { |dup| dup.add_self_reference(key, length.to_i - 1) } : self
28
+ end
29
+
30
+ def valid_length?
31
+ length.nil? || length == '' || length.to_i.positive?
32
+ end
33
+
34
+ def to_hash
35
+ @hash.each_with_object({}) do |(key, value), hash|
36
+ key = "#{key}*#{value.length}".to_sym if value.length
37
+ hash[key] = value.to_hash unless value == self
38
+ end
39
+ end
40
+
41
+ def add_self_reference(key, length)
42
+ @hash = @hash.merge(key => self)
43
+ self.length = length
44
+ end
45
+
46
+ private
47
+
48
+ def formulate_hash(include_hash, options)
49
+ include_hash.each_with_object({}) do |(key, value), hash|
50
+ rel_name, rel_length = extract_rel_meta(key)
51
+
52
+ hash[rel_name] = self.class.new(value, options_with_retain_rel_limit(options)).tap do |directive|
53
+ directive.add_self_reference(rel_name, rel_length) if key.to_s.match?(/.+\*(\d*)\z/)
54
+ end
55
+ end
56
+ end
57
+
58
+ def extract_rel_meta(key)
59
+ Graphiti::ActiveGraph::Util::Transformers::RelationParam.new(key).split_rel_length(retain_rel_limit)
60
+ end
61
+
62
+ def options_with_retain_rel_limit(options)
63
+ options.merge(retain_rel_limit:)
64
+ end
65
+ end
66
+ end
@@ -1,8 +1,8 @@
1
- module Graphiti::ActiveGraph::JsonapiExt::Serializable
2
- module ResourceExt
3
- def as_jsonapi(fields: nil, include: [])
4
- include.merge(fields) if fields.present?
5
- super(fields: fields, include: include)
6
- end
7
- end
8
- end
1
+ module Graphiti::ActiveGraph::JsonapiExt::Serializable
2
+ module ResourceExt
3
+ def as_jsonapi(fields: nil, include: [])
4
+ include.merge(fields) if fields.present?
5
+ super(fields: fields, include: include)
6
+ end
7
+ end
8
+ end
@@ -1,76 +1,76 @@
1
- module Graphiti::ActiveGraph
2
- module Query
3
- attr_reader :deep_sort
4
-
5
- def filters
6
- @filters ||= begin
7
- {}.tap do |hash|
8
- (@params[:filter] || {}).each_pair do |name, value|
9
- name = name.to_sym
10
-
11
- if legacy_nested?(name)
12
- value.keys.each do |key|
13
- filter_name = key.to_sym
14
- filter_value = value[key]
15
-
16
- if @resource.get_attr!(filter_name, :filterable, request: true)
17
- hash[filter_name] = filter_value
18
- end
19
- end
20
- elsif nested?(name)
21
- name = name.to_s.split(".").last.to_sym
22
- validate!(name, :filterable)
23
- hash[name] = value
24
- else
25
- hash[name] = value
26
- end
27
- end
28
- end
29
- end
30
- end
31
-
32
- def sorts
33
- return super unless (sort = params[:sort]) && sort.include?('.')
34
-
35
- @deep_sort = sort_criteria(sort)
36
- []
37
- end
38
-
39
- def include_directive
40
- @include_directive ||= Graphiti::ActiveGraph::JsonapiExt::IncludeDirective.new(@include_param, retain_rel_limit: true)
41
- end
42
-
43
- def parse_sort_criteria_hash(hash)
44
- hash.map { |key, value| [key.to_s.split('.').map(&:to_sym), value] }.to_h
45
- end
46
-
47
- def links?
48
- [:json, :xml, 'json', 'xml'].exclude?(params[:format]) && show_resource_links?
49
- end
50
-
51
- def pagination_links?
52
- action != :find && show_pagination_links?
53
- end
54
-
55
- private
56
-
57
- def show_pagination_links?
58
- return @show_pagination_links unless @show_pagination_links.nil?
59
- @show_pagination_links = read_link_params(:pagination_links)
60
- end
61
-
62
- def show_resource_links?
63
- return @show_resource_links unless @show_resource_links.nil?
64
-
65
- @show_resource_links = read_link_params(:links)
66
- end
67
-
68
- def read_link_params(name)
69
- ActiveModel::Type::Boolean.new.cast(params[name]) != false
70
- end
71
-
72
- def sort_criteria(sort)
73
- sort.split(',').map(&method(:sort_hash)).map(&method(:parse_sort_criteria_hash))
74
- end
75
- end
76
- end
1
+ module Graphiti::ActiveGraph
2
+ module Query
3
+ attr_reader :deep_sort
4
+
5
+ def filters
6
+ @filters ||= begin
7
+ {}.tap do |hash|
8
+ (@params[:filter] || {}).each_pair do |name, value|
9
+ name = name.to_sym
10
+
11
+ if legacy_nested?(name)
12
+ value.keys.each do |key|
13
+ filter_name = key.to_sym
14
+ filter_value = value[key]
15
+
16
+ if @resource.get_attr!(filter_name, :filterable, request: true)
17
+ hash[filter_name] = filter_value
18
+ end
19
+ end
20
+ elsif nested?(name)
21
+ name = name.to_s.split(".").last.to_sym
22
+ validate!(name, :filterable)
23
+ hash[name] = value
24
+ else
25
+ hash[name] = value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def sorts
33
+ return super unless (sort = params[:sort]) && sort.include?('.')
34
+
35
+ @deep_sort = sort_criteria(sort)
36
+ []
37
+ end
38
+
39
+ def include_directive
40
+ @include_directive ||= Graphiti::ActiveGraph::JsonapiExt::IncludeDirective.new(@include_param, retain_rel_limit: true)
41
+ end
42
+
43
+ def parse_sort_criteria_hash(hash)
44
+ hash.map { |key, value| [key.to_s.split('.').map(&:to_sym), value] }.to_h
45
+ end
46
+
47
+ def links?
48
+ [:json, :xml, 'json', 'xml'].exclude?(params[:format]) && show_resource_links?
49
+ end
50
+
51
+ def pagination_links?
52
+ action != :find && show_pagination_links?
53
+ end
54
+
55
+ private
56
+
57
+ def show_pagination_links?
58
+ return @show_pagination_links unless @show_pagination_links.nil?
59
+ @show_pagination_links = read_link_params(:pagination_links)
60
+ end
61
+
62
+ def show_resource_links?
63
+ return @show_resource_links unless @show_resource_links.nil?
64
+
65
+ @show_resource_links = read_link_params(:links)
66
+ end
67
+
68
+ def read_link_params(name)
69
+ ActiveModel::Type::Boolean.new.cast(params[name]) != false
70
+ end
71
+
72
+ def sort_criteria(sort)
73
+ sort.split(',').map(&method(:sort_hash)).map(&method(:parse_sort_criteria_hash))
74
+ end
75
+ end
76
+ end
@@ -1,9 +1,9 @@
1
- module Graphiti::ActiveGraph
2
- module RequestValidators
3
- module Validator
4
- def deserialized_payload
5
- @deserialized_payload ||= Graphiti::ActiveGraph::Deserializer.new(@params)
6
- end
7
- end
8
- end
9
- end
1
+ module Graphiti::ActiveGraph
2
+ module RequestValidators
3
+ module Validator
4
+ def deserialized_payload
5
+ @deserialized_payload ||= Graphiti::ActiveGraph::Deserializer.new(@params)
6
+ end
7
+ end
8
+ end
9
+ end