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,103 +1,103 @@
1
- module Graphiti
2
- module ActiveGraph
3
- class Resource < Graphiti::Resource
4
- include Extensions::Resources::Authorizationable
5
- include Extensions::Resources::PayloadCombinable
6
- include Extensions::Resources::Preloadable
7
- include Extensions::Resources::Rel
8
-
9
- self.adapter = Adapters::ActiveGraph
10
- self.abstract_class = true
11
-
12
- def self.use_uuid
13
- define_singleton_method(:inherited) do |klass|
14
- super(klass)
15
- klass.attribute :id, :uuid
16
- end
17
- end
18
-
19
- def self.guard_nil_id!(params)
20
- end
21
-
22
- def self.extra_attribute?(name)
23
- extra_attributes.has_key?(name)
24
- end
25
-
26
- def self.sideload_config(sideload_name)
27
- config[:sideloads][sideload_name]
28
- end
29
-
30
- def self.sideload_resource_class(sideload_name)
31
- sideload_config(sideload_name)&.resource_class
32
- end
33
-
34
- def self.custom_eagerload(sideload_name)
35
- sideload_config(sideload_name)&.custom_eagerload
36
- end
37
-
38
- def extra_attribute?(name)
39
- self.class.extra_attribute?(name)
40
- end
41
-
42
- def build_scope(base, query, opts = {})
43
- scoping_class.new(base, self, query, opts)
44
- end
45
-
46
- def handle_includes(scope, includes, sorts, **opts)
47
- includes_str = JSONAPI::IncludeDirective.new(includes, retain_rel_limit: true).to_string.split(',')
48
- extra_includes_str = opts.delete(:extra_fields_includes) || []
49
- options = opts.merge(max_page_size:).merge!(authorize_scope_params)
50
- scope.with_ordered_associations(includes_str.union(extra_includes_str), sorts, options)
51
- end
52
-
53
- def sideload_name_arr(query)
54
- query.sideloads.keys.map(&:to_sym)
55
- end
56
-
57
- def resolve(scope)
58
- adapter.resolve(scope, relation_resource?)
59
- end
60
-
61
- def typecast(name, value, flag)
62
- att = get_attr!(name, flag, request: true)
63
-
64
- # in case of attribute is not declared on resource
65
- # do not throw error, return original value without typecast
66
- return value unless att
67
-
68
- type_name = att[:type]
69
- if flag == :filterable
70
- type_name = filters[name][:type]
71
- end
72
- type = Graphiti::Types[type_name]
73
- return if value.nil? && type[:kind] != "array"
74
- begin
75
- flag = :read if flag == :readable
76
- flag = :write if flag == :writable
77
- flag = :params if [:sortable, :filterable].include?(flag)
78
- type[flag][value]
79
- rescue => e
80
- raise Errors::TypecastFailed.new(self, name, value, e, type_name)
81
- end
82
- end
83
-
84
- def authorize_scope_params
85
- {}
86
- end
87
-
88
- def all_models
89
- polymorphic? ? self.class.children.map(&:model) : [model]
90
- end
91
-
92
- private
93
-
94
- def scoping_class
95
- Scope
96
- end
97
-
98
- def update_foreign_key(*)
99
- true
100
- end
101
- end
102
- end
103
- end
1
+ module Graphiti
2
+ module ActiveGraph
3
+ class Resource < Graphiti::Resource
4
+ include Extensions::Resources::Authorizationable
5
+ include Extensions::Resources::PayloadCombinable
6
+ include Extensions::Resources::Preloadable
7
+ include Extensions::Resources::Rel
8
+
9
+ self.adapter = Adapters::ActiveGraph
10
+ self.abstract_class = true
11
+
12
+ def self.use_uuid
13
+ define_singleton_method(:inherited) do |klass|
14
+ super(klass)
15
+ klass.attribute :id, :uuid
16
+ end
17
+ end
18
+
19
+ def self.guard_nil_id!(params)
20
+ end
21
+
22
+ def self.extra_attribute?(name)
23
+ extra_attributes.has_key?(name)
24
+ end
25
+
26
+ def self.sideload_config(sideload_name)
27
+ config[:sideloads][sideload_name]
28
+ end
29
+
30
+ def self.sideload_resource_class(sideload_name)
31
+ sideload_config(sideload_name)&.resource_class
32
+ end
33
+
34
+ def self.custom_eagerload(sideload_name)
35
+ sideload_config(sideload_name)&.custom_eagerload
36
+ end
37
+
38
+ def extra_attribute?(name)
39
+ self.class.extra_attribute?(name)
40
+ end
41
+
42
+ def build_scope(base, query, opts = {})
43
+ scoping_class.new(base, self, query, opts)
44
+ end
45
+
46
+ def handle_includes(scope, includes, sorts, **opts)
47
+ includes_str = JSONAPI::IncludeDirective.new(includes, retain_rel_limit: true).to_string.split(',')
48
+ extra_includes_str = opts.delete(:extra_fields_includes) || []
49
+ options = opts.merge(max_page_size:).merge!(authorize_scope_params)
50
+ scope.with_ordered_associations(includes_str.union(extra_includes_str), sorts, options)
51
+ end
52
+
53
+ def sideload_name_arr(query)
54
+ query.sideloads.keys.map(&:to_sym)
55
+ end
56
+
57
+ def resolve(scope)
58
+ adapter.resolve(scope, relation_resource?)
59
+ end
60
+
61
+ def typecast(name, value, flag)
62
+ att = get_attr!(name, flag, request: true)
63
+
64
+ # in case of attribute is not declared on resource
65
+ # do not throw error, return original value without typecast
66
+ return value unless att
67
+
68
+ type_name = att[:type]
69
+ if flag == :filterable
70
+ type_name = filters[name][:type]
71
+ end
72
+ type = Graphiti::Types[type_name]
73
+ return if value.nil? && type[:kind] != "array"
74
+ begin
75
+ flag = :read if flag == :readable
76
+ flag = :write if flag == :writable
77
+ flag = :params if [:sortable, :filterable].include?(flag)
78
+ type[flag][value]
79
+ rescue => e
80
+ raise Errors::TypecastFailed.new(self, name, value, e, type_name)
81
+ end
82
+ end
83
+
84
+ def authorize_scope_params
85
+ {}
86
+ end
87
+
88
+ def all_models
89
+ polymorphic? ? self.class.children.map(&:model) : [model]
90
+ end
91
+
92
+ private
93
+
94
+ def scoping_class
95
+ Scope
96
+ end
97
+
98
+ def update_foreign_key(*)
99
+ true
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,86 +1,86 @@
1
- module Graphiti::ActiveGraph
2
- module ResourceProxy
3
- include Graphiti::ActiveGraph::SideloadResolve
4
- attr_reader :preloaded
5
-
6
- def initialize(resource, scope, query,
7
- payload: nil,
8
- single: false,
9
- raise_on_missing: false,
10
- preloaded: false)
11
- @resource = resource
12
- @scope = scope
13
- @query = query
14
- @payload = payload
15
- @single = single
16
- @raise_on_missing = raise_on_missing
17
- @preloaded = preloaded
18
- end
19
-
20
- def data
21
- return @data if @data
22
-
23
- return super unless @preloaded
24
-
25
- resolve_sideloads(@preloaded)
26
- @single ? data_for_preloaded_record : data_for_preloaded_records
27
- end
28
-
29
- alias_method :resolve_data, :data
30
-
31
- def data_for_preloaded_record
32
- @preloaded = @preloaded.is_a?(Array) ? @preloaded[0] : @preloaded
33
- @resource.decorate_record(@preloaded)
34
- @data = @preloaded
35
- end
36
-
37
- def data_for_preloaded_records
38
- @preloaded.each do |r|
39
- @resource.decorate_record(r)
40
- end
41
- @data = @preloaded
42
- end
43
-
44
- def stats
45
- @stats ||= if @query.stats && !resource.relation_resource?
46
- payload = ::Graphiti::Stats::Payload.new @resource,
47
- @query,
48
- @scope.unpaginated_object,
49
- data
50
- payload.generate
51
- else
52
- {}
53
- end
54
- end
55
-
56
- def save(action: :create)
57
- # TODO: remove this. Only used for persisting many-to-many with AR
58
- # (see activerecord adapter)
59
- original = Graphiti.context[:namespace]
60
- begin
61
- Graphiti.context[:namespace] = action
62
- ::Graphiti::RequestValidator.new(@resource, @payload.params, action).validate!
63
- validator = persist {
64
- @resource.persist_with_relationships \
65
- @payload.meta(action: action),
66
- @payload.attributes,
67
- @payload.relationships
68
- }
69
- ensure
70
- Graphiti.context[:namespace] = original
71
- end
72
- @data, success = validator.to_a
73
-
74
- if success && !resource.relation_resource?
75
- # If the context namespace is `update` or `create`, certain
76
- # adapters will cause N+1 validation calls, so lets explicitly
77
- # switch to a lookup context.
78
- Graphiti.with_context(Graphiti.context[:object], :show) do
79
- @scope.resolve_sideloads([@data])
80
- end
81
- end
82
-
83
- success
84
- end
85
- end
86
- end
1
+ module Graphiti::ActiveGraph
2
+ module ResourceProxy
3
+ include Graphiti::ActiveGraph::SideloadResolve
4
+ attr_reader :preloaded
5
+
6
+ def initialize(resource, scope, query,
7
+ payload: nil,
8
+ single: false,
9
+ raise_on_missing: false,
10
+ preloaded: false)
11
+ @resource = resource
12
+ @scope = scope
13
+ @query = query
14
+ @payload = payload
15
+ @single = single
16
+ @raise_on_missing = raise_on_missing
17
+ @preloaded = preloaded
18
+ end
19
+
20
+ def data
21
+ return @data if @data
22
+
23
+ return super unless @preloaded
24
+
25
+ resolve_sideloads(@preloaded)
26
+ @single ? data_for_preloaded_record : data_for_preloaded_records
27
+ end
28
+
29
+ alias_method :resolve_data, :data
30
+
31
+ def data_for_preloaded_record
32
+ @preloaded = @preloaded.is_a?(Array) ? @preloaded[0] : @preloaded
33
+ @resource.decorate_record(@preloaded)
34
+ @data = @preloaded
35
+ end
36
+
37
+ def data_for_preloaded_records
38
+ @preloaded.each do |r|
39
+ @resource.decorate_record(r)
40
+ end
41
+ @data = @preloaded
42
+ end
43
+
44
+ def stats
45
+ @stats ||= if @query.stats && !resource.relation_resource?
46
+ payload = ::Graphiti::Stats::Payload.new @resource,
47
+ @query,
48
+ @scope.unpaginated_object,
49
+ data
50
+ payload.generate
51
+ else
52
+ {}
53
+ end
54
+ end
55
+
56
+ def save(action: :create)
57
+ # TODO: remove this. Only used for persisting many-to-many with AR
58
+ # (see activerecord adapter)
59
+ original = Graphiti.context[:namespace]
60
+ begin
61
+ Graphiti.context[:namespace] = action
62
+ ::Graphiti::RequestValidator.new(@resource, @payload.params, action).validate!
63
+ validator = persist {
64
+ @resource.persist_with_relationships \
65
+ @payload.meta(action: action),
66
+ @payload.attributes,
67
+ @payload.relationships
68
+ }
69
+ ensure
70
+ Graphiti.context[:namespace] = original
71
+ end
72
+ @data, success = validator.to_a
73
+
74
+ if success && !resource.relation_resource?
75
+ # If the context namespace is `update` or `create`, certain
76
+ # adapters will cause N+1 validation calls, so lets explicitly
77
+ # switch to a lookup context.
78
+ Graphiti.with_context(Graphiti.context[:object], :show) do
79
+ @scope.resolve_sideloads([@data])
80
+ end
81
+ end
82
+
83
+ success
84
+ end
85
+ end
86
+ end
@@ -1,14 +1,14 @@
1
- module Graphiti::ActiveGraph
2
- module Resources
3
- module Interface
4
- extend ActiveSupport::Concern
5
- class_methods do
6
- def build(params, base_scope = nil, opts = {})
7
- validate_request!(params)
8
- runner = ::Graphiti::Runner.new(self, params)
9
- runner.proxy(base_scope, { single: true, raise_on_missing: true }.merge(opts) )
10
- end
11
- end
12
- end
13
- end
14
- end
1
+ module Graphiti::ActiveGraph
2
+ module Resources
3
+ module Interface
4
+ extend ActiveSupport::Concern
5
+ class_methods do
6
+ def build(params, base_scope = nil, opts = {})
7
+ validate_request!(params)
8
+ runner = ::Graphiti::Runner.new(self, params)
9
+ runner.proxy(base_scope, { single: true, raise_on_missing: true }.merge(opts) )
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,25 +1,25 @@
1
- module Graphiti::ActiveGraph
2
- module Resources
3
- module Persistence
4
- def update(update_params, meta = nil)
5
- model_instance = nil
6
- id = update_params[:id]
7
- update_params = update_params.except(:id)
8
-
9
- run_callbacks :persistence, :update, update_params, meta do
10
- run_callbacks :attributes, :update, update_params, meta do |params|
11
- model_instance = id ? model.find(id) : self.class._find(id: id).data
12
- call_with_meta(:assign_attributes, model_instance, params, meta)
13
- model_instance
14
- end
15
-
16
- run_callbacks :save, :update, model_instance, meta do
17
- model_instance = call_with_meta(:save, model_instance, meta)
18
- end
19
- end
20
-
21
- model_instance
22
- end
23
- end
24
- end
25
- end
1
+ module Graphiti::ActiveGraph
2
+ module Resources
3
+ module Persistence
4
+ def update(update_params, meta = nil)
5
+ model_instance = nil
6
+ id = update_params[:id]
7
+ update_params = update_params.except(:id)
8
+
9
+ run_callbacks :persistence, :update, update_params, meta do
10
+ run_callbacks :attributes, :update, update_params, meta do |params|
11
+ model_instance = id ? model.find(id) : self.class._find(id: id).data
12
+ call_with_meta(:assign_attributes, model_instance, params, meta)
13
+ model_instance
14
+ end
15
+
16
+ run_callbacks :save, :update, model_instance, meta do
17
+ model_instance = call_with_meta(:save, model_instance, meta)
18
+ end
19
+ end
20
+
21
+ model_instance
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,39 +1,39 @@
1
- module Graphiti::ActiveGraph
2
- module Runner
3
- def initialize(resource_class, params, query = nil, action = nil)
4
- @resource_class = resource_class
5
- @params = params
6
- @query = query
7
- @action = action
8
-
9
- validator = ::Graphiti::RequestValidator.new(jsonapi_resource, params, action)
10
-
11
- validator.validate! unless params[:skip_render_val]
12
-
13
- @deserialized_payload = validator.deserialized_payload
14
- end
15
-
16
- def proxy(base = nil, opts = {})
17
- base ||= jsonapi_resource.base_scope
18
- scope_opts = opts.slice(:sideload_parent_length,
19
- :default_paginate,
20
- :after_resolve,
21
- :sideload,
22
- :parent,
23
- :params,
24
- :preloaded).merge(unpaginated_query: params[:unpaginated_query])
25
- scope = jsonapi_scope(base, scope_opts)
26
- preloaded = opts[:preloaded]
27
- options = { payload: deserialized_payload,
28
- single: opts[:single],
29
- raise_on_missing: opts[:raise_on_missing],
30
- preloaded: preloaded
31
- }
32
- ::Graphiti::ResourceProxy.new jsonapi_resource,
33
- scope,
34
- query,
35
- **options
36
- end
37
- end
38
- end
39
-
1
+ module Graphiti::ActiveGraph
2
+ module Runner
3
+ def initialize(resource_class, params, query = nil, action = nil)
4
+ @resource_class = resource_class
5
+ @params = params
6
+ @query = query
7
+ @action = action
8
+
9
+ validator = ::Graphiti::RequestValidator.new(jsonapi_resource, params, action)
10
+
11
+ validator.validate! unless params[:skip_render_val]
12
+
13
+ @deserialized_payload = validator.deserialized_payload
14
+ end
15
+
16
+ def proxy(base = nil, opts = {})
17
+ base ||= jsonapi_resource.base_scope
18
+ scope_opts = opts.slice(:sideload_parent_length,
19
+ :default_paginate,
20
+ :after_resolve,
21
+ :sideload,
22
+ :parent,
23
+ :params,
24
+ :preloaded).merge(unpaginated_query: params[:unpaginated_query])
25
+ scope = jsonapi_scope(base, scope_opts)
26
+ preloaded = opts[:preloaded]
27
+ options = { payload: deserialized_payload,
28
+ single: opts[:single],
29
+ raise_on_missing: opts[:raise_on_missing],
30
+ preloaded: preloaded
31
+ }
32
+ ::Graphiti::ResourceProxy.new jsonapi_resource,
33
+ scope,
34
+ query,
35
+ **options
36
+ end
37
+ end
38
+ end
39
+
@@ -1,28 +1,28 @@
1
- module Graphiti
2
- module ActiveGraph
3
- class Scope < Graphiti::Scope
4
- def non_applicable_for_unpaginated
5
- %i[association_eagerload]
6
- end
7
-
8
- def apply_scoping(scope, opts)
9
- opts[:query_obj] = @query
10
- super
11
-
12
- append_scopings(opts) unless @resource.remote?
13
- @object
14
- end
15
-
16
- def append_scopings(opts)
17
- add_scoping(:include, Scoping::Include, opts)
18
- add_scoping(:association_eagerload, Scoping::AssociationEagerLoad, opts)
19
- end
20
-
21
- def add_scoping(key, scoping_class, opts, _ = {})
22
- @object = scoping_class.new(@resource, @query.hash, @object, opts).apply
23
- return if non_applicable_for_unpaginated.include?(key)
24
- @unpaginated_object = scoping_class.new(@resource, @query.hash, @unpaginated_object, opts.merge(unpaginated_query: true)).apply
25
- end
26
- end
27
- end
28
- end
1
+ module Graphiti
2
+ module ActiveGraph
3
+ class Scope < Graphiti::Scope
4
+ def non_applicable_for_unpaginated
5
+ %i[association_eagerload]
6
+ end
7
+
8
+ def apply_scoping(scope, opts)
9
+ opts[:query_obj] = @query
10
+ super
11
+
12
+ append_scopings(opts) unless @resource.remote?
13
+ @object
14
+ end
15
+
16
+ def append_scopings(opts)
17
+ add_scoping(:include, Scoping::Include, opts)
18
+ add_scoping(:association_eagerload, Scoping::AssociationEagerLoad, opts)
19
+ end
20
+
21
+ def add_scoping(key, scoping_class, opts, _ = {})
22
+ @object = scoping_class.new(@resource, @query.hash, @object, opts).apply
23
+ return if non_applicable_for_unpaginated.include?(key)
24
+ @unpaginated_object = scoping_class.new(@resource, @query.hash, @unpaginated_object, opts.merge(unpaginated_query: true)).apply
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,34 +1,34 @@
1
- module Graphiti::ActiveGraph
2
- module Scoping
3
- class AssociationEagerLoad < Graphiti::Scoping::Base
4
- def custom_scope
5
- nil
6
- end
7
-
8
- def apply_standard_scope
9
- return @scope unless eagerload_associations?
10
- if (ids = @scope.collect(&:id)).present?
11
- @opts[:query_obj].include_hash.each_key do |key|
12
- eagerload_association(key, ids)
13
- end
14
- end
15
- @scope
16
- end
17
-
18
- def eagerload_associations?
19
- @opts[:query_obj].include_hash.present? && @resource.model.include?(ActiveGraph::Node) &&
20
- @resource.model.associations_to_eagerload.present?
21
- end
22
-
23
- def eagerload_association(key, ids)
24
- return unless @resource.model.eagerload_association?(key)
25
- nodes = @resource.model.association_nodes(key, ids, @resource.context.send(:association_filter_params))
26
- @scope.each { |node| node.send("#{key}=", nodes[node.id] || nil_or_empty(key)) }
27
- end
28
-
29
- def nil_or_empty(key)
30
- @resource.class.config[:sideloads][key].type == :has_one ? nil : []
31
- end
32
- end
33
- end
34
- end
1
+ module Graphiti::ActiveGraph
2
+ module Scoping
3
+ class AssociationEagerLoad < Graphiti::Scoping::Base
4
+ def custom_scope
5
+ nil
6
+ end
7
+
8
+ def apply_standard_scope
9
+ return @scope unless eagerload_associations?
10
+ if (ids = @scope.collect(&:id)).present?
11
+ @opts[:query_obj].include_hash.each_key do |key|
12
+ eagerload_association(key, ids)
13
+ end
14
+ end
15
+ @scope
16
+ end
17
+
18
+ def eagerload_associations?
19
+ @opts[:query_obj].include_hash.present? && @resource.model.include?(ActiveGraph::Node) &&
20
+ @resource.model.associations_to_eagerload.present?
21
+ end
22
+
23
+ def eagerload_association(key, ids)
24
+ return unless @resource.model.eagerload_association?(key)
25
+ nodes = @resource.model.association_nodes(key, ids, @resource.context.send(:association_filter_params))
26
+ @scope.each { |node| node.send("#{key}=", nodes[node.id] || nil_or_empty(key)) }
27
+ end
28
+
29
+ def nil_or_empty(key)
30
+ @resource.class.config[:sideloads][key].type == :has_one ? nil : []
31
+ end
32
+ end
33
+ end
34
+ end