graphiti-activegraph 0.1.25 → 0.1.26

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91f9eb76f0b56c276cf1ec4fbef4d535e768c85dbee0d503c3bf9e47c492b509
4
- data.tar.gz: 9ead092210d92a237fed63c396cf302730fffe601d1fcb0a00a1265563cc0c66
3
+ metadata.gz: 4e2e06c991422f868705fa49e812c51af9c537366fac6246ebfc882969e7bdae
4
+ data.tar.gz: 7fc80649e1455f255450e00dcf6c66fe0ff889d1d74e16ebe123dc70362e8266
5
5
  SHA512:
6
- metadata.gz: 48334374bd34917e110d55156847d8cc3ba389e45dc76bb7d3db1df2ca8cc59cda5a46ff23c79aff298e0700201d743d3ca04d53b0bb4ae843a3db037c13bff9
7
- data.tar.gz: cb3ee1de2754dcd3ddfcccc84970aaffc21fa8c2c05e6518299c6bd55c7a4f52830462a9a092152eeb93ece42e3476532094d41bf41d57683eb43d34cf9b1f64
6
+ metadata.gz: 3db8cee492d4ac415bddc3a44cf755cfa4f32a0b3865f90821c62a681838776d48c6e12dff4fd30fafce88f204c56884c37bc016bc4b71166fe572ec725ab1df
7
+ data.tar.gz: 8d7f27a547460a725247b4b28ea629fec384f20e0255f29771c6f805e096063f8bfb5138e576f7ef7d6c7eb1acfe4cfca735940d2852dee41fee3042462ca604
@@ -0,0 +1,44 @@
1
+ module Graphiti::ActiveGraph::Concerns
2
+ module PathRelationships
3
+ def add_path_id_to_relationships!(params)
4
+ return params if path_relationships_updated?
5
+ detect_conflict(:id, @params[:id]&.to_s, attributes[:id]&.to_s)
6
+ path_map.each do |rel_name, path_value|
7
+ body_value = relationships.dig(rel_name, :attributes, :id)
8
+ if body_value
9
+ detect_conflict(rel_name, path_value&.to_s, body_value&.to_s)
10
+ else
11
+ update_params(params, rel_name, path_value)
12
+ update_realationships(rel_name, path_value)
13
+ end
14
+ end
15
+ path_relationships_updated!
16
+ params
17
+ end
18
+
19
+ private
20
+
21
+ def path_relationships_updated!
22
+ @path_relationships_updated = true
23
+ end
24
+
25
+ def path_relationships_updated?
26
+ @path_relationships_updated.present?
27
+ end
28
+
29
+ def update_params(params, rel_name, path_value)
30
+ params[:data] ||= {}
31
+ params[:data][:relationships] ||= {}
32
+ params[:data][:relationships][rel_name] = {
33
+ data: {
34
+ type: derive_resource_type(rel_name),
35
+ id: path_value
36
+ }
37
+ }
38
+ end
39
+
40
+ def update_realationships(rel_name, path_value)
41
+ relationships[rel_name] = { meta: {}, attributes: { id: path_value } }
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,7 @@
1
1
  module Graphiti::ActiveGraph
2
- module Deserializer
2
+ class Deserializer < Graphiti::Deserializer
3
+ include Concerns::PathRelationships
4
+
3
5
  class Conflict < StandardError
4
6
  attr_reader :key, :path_value, :body_value
5
7
 
@@ -14,13 +16,33 @@ module Graphiti::ActiveGraph
14
16
  end
15
17
  end
16
18
 
17
- def initialize(payload, env=nil, model=nil, parent_map=nil)
19
+ def initialize(payload, env = nil, model = nil, parent_map = nil)
18
20
  super(payload)
19
21
 
20
22
  @params = payload
21
23
  @model = model
22
24
  @parent_map = parent_map || {}
23
25
  @env = env
26
+
27
+ return unless data.blank? && env && parsable_content?
28
+
29
+ raise ArgumentError, "JSON API payload must contain the 'data' key"
30
+ end
31
+
32
+ def process_relationship_datum(datum)
33
+ {
34
+ meta: {
35
+ jsonapi_type: datum[:type],
36
+ temp_id: datum[:'temp-id'],
37
+ method: datum[:method]&.to_sym
38
+ },
39
+ attributes: datum[:id] ? { id: datum[:id] } : {},
40
+ relationships: {}
41
+ }
42
+ end
43
+
44
+ def meta_params
45
+ data[:meta] || {}
24
46
  end
25
47
 
26
48
  def process_relationships(relationship_hash)
@@ -33,6 +55,10 @@ module Graphiti::ActiveGraph
33
55
  end
34
56
  end
35
57
 
58
+ def relationship?(name)
59
+ relationships[name.to_sym].present?
60
+ end
61
+
36
62
  # change empty relationship as `disassociate` hash so they will be removed
37
63
  def process_nil_relationship(name)
38
64
  attributes = {}
@@ -62,45 +88,6 @@ module Graphiti::ActiveGraph
62
88
  results
63
89
  end
64
90
 
65
- def add_path_id_to_relationships!(params)
66
- return params if path_relationships_updated?
67
- detect_conflict(:id, @params[:id]&.to_s, attributes[:id]&.to_s)
68
- path_map.each do |rel_name, path_value|
69
- body_value = relationships.dig(rel_name, :attributes, :id)
70
- if body_value
71
- detect_conflict(rel_name, path_value&.to_s, body_value&.to_s)
72
- else
73
- update_params(params, rel_name, path_value)
74
- update_realationships(rel_name, path_value)
75
- end
76
- end
77
- path_relationships_updated!
78
- params
79
- end
80
-
81
- def path_relationships_updated!
82
- @path_relationships_updated = true
83
- end
84
-
85
- def path_relationships_updated?
86
- @path_relationships_updated.present?
87
- end
88
-
89
- def update_params(params, rel_name, path_value)
90
- params[:data] ||= {}
91
- params[:data][:relationships] ||= {}
92
- params[:data][:relationships][rel_name] = {
93
- data: {
94
- type: derive_resource_type(rel_name),
95
- id: path_value
96
- }
97
- }
98
- end
99
-
100
- def update_realationships(rel_name, path_value)
101
- relationships[rel_name] = { meta: {}, attributes: { id: path_value } }
102
- end
103
-
104
91
  def path_map
105
92
  map = @params.select { |key, _| key =~ /_id$/ }.permit!.to_h
106
93
  map = filter_keys(map) { |key| key.gsub(/_id$/, '').to_sym }
@@ -127,6 +114,10 @@ module Graphiti::ActiveGraph
127
114
 
128
115
  private
129
116
 
117
+ def parsable_content?
118
+ true
119
+ end
120
+
130
121
  def derive_resource_type(rel_name)
131
122
  if @model.include?(ActiveGraph::Node)
132
123
  @model.associations[rel_name].target_class.model_name.plural.to_s
@@ -0,0 +1,52 @@
1
+ module Graphiti::ActiveGraph::Extensions::Grouping
2
+ class Params
3
+ attr_reader :params, :grouping_criteria_list, :resource_class
4
+ def initialize(params, resource_class)
5
+ @params = params
6
+ @grouping_criteria_list = params.fetch(:group_by, nil)&.split(',') || []
7
+ @resource_class = resource_class
8
+ end
9
+
10
+ def single_grouping_criteria?
11
+ grouping_criteria_list.size < 2
12
+ end
13
+
14
+ def grouping_criteria_on_attribute?
15
+ grouping_criteria_list.any? { |criteria| ends_with_attribute?(resource_class.model, criteria) }
16
+ end
17
+
18
+ def empty?
19
+ grouping_criteria_list.empty?
20
+ end
21
+
22
+ def ends_with_attribute?(model, criteria)
23
+ return false if criteria.blank?
24
+
25
+ last_segment_attribute?(model, criteria.split('.'))
26
+ end
27
+
28
+ private
29
+
30
+ def last_segment_attribute?(model, segments)
31
+ last_segment = segments.last
32
+ intermediate_model = traverse_to_last_associated_model(model, segments[0...-1])
33
+
34
+ intermediate_model && attribute?(intermediate_model, last_segment)
35
+ end
36
+
37
+ def traverse_to_last_associated_model(model, intermediate_segments)
38
+ intermediate_segments.each do |segment|
39
+ return false unless(model = associated_model(model, segment))
40
+ end
41
+ model
42
+ end
43
+
44
+ def attribute?(model, segment)
45
+ model.attribute_names.include?(segment)
46
+ end
47
+
48
+ def associated_model(model, segment)
49
+ model.associations[segment.to_sym]&.target_class
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ module Graphiti::ActiveGraph::Extensions
2
+ class QueryParams
3
+ attr_reader :params, :grouping_extra_params, :resource_class
4
+
5
+ def initialize(params, resource_class, grouping_extra_params: {})
6
+ @params = params
7
+ @resource_class = resource_class
8
+ @grouping_extra_params = grouping_extra_params
9
+ end
10
+
11
+ def group_by
12
+ Grouping::Params.new(params, resource_class)
13
+ end
14
+
15
+ def group_by_params
16
+ group_by_params_hash unless group_by.empty?
17
+ end
18
+
19
+ def group_by_params_hash
20
+ { group_by: group_by.grouping_criteria_list }.merge(grouping_extra_params)
21
+ end
22
+
23
+ def extra_field?(type, name)
24
+ params.dig(:extra_fields, type)&.include?(name.to_s)
25
+ end
26
+ end
27
+ end
@@ -0,0 +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,5 +1,5 @@
1
1
  module Graphiti
2
2
  module ActiveGraph
3
- VERSION = '0.1.25'
3
+ VERSION = '0.1.26'
4
4
  end
5
5
  end
@@ -27,7 +27,6 @@ Graphiti::Scoping::Filter.prepend Graphiti::ActiveGraph::Scoping::Filter
27
27
  Graphiti::Util::SerializerRelationship.prepend Graphiti::ActiveGraph::Util::SerializerRelationship
28
28
  Graphiti::Util::SerializerAttribute.prepend Graphiti::ActiveGraph::Util::SerializerAttribute
29
29
  Graphiti::Util::RelationshipPayload.prepend Graphiti::ActiveGraph::Util::RelationshipPayload
30
- Graphiti::Deserializer.prepend Graphiti::ActiveGraph::Deserializer
31
30
  Graphiti::Query.prepend Graphiti::ActiveGraph::Query
32
31
  Graphiti::Resource.prepend Graphiti::ActiveGraph::ResourceInstanceMethods
33
32
  Graphiti::Resource.extend Graphiti::ActiveGraph::Resource
@@ -35,6 +34,7 @@ Graphiti::ResourceProxy.prepend Graphiti::ActiveGraph::ResourceProxy
35
34
  Graphiti::Runner.prepend Graphiti::ActiveGraph::Runner
36
35
  Graphiti::Scope.prepend Graphiti::ActiveGraph::SideloadResolve
37
36
  Graphiti::Configuration.include Graphiti::SidepostConfiguration
37
+ Graphiti::RequestValidators::Validator.prepend Graphiti::ActiveGraph::RequestValidators::Validator
38
38
 
39
39
  # JSONAPI extensions
40
40
  JSONAPI::Serializable::Resource.prepend Graphiti::ActiveGraph::JsonapiExt::Serializable::ResourceExt
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiti-activegraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.25
4
+ version: 0.1.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hardik Joshi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-05 00:00:00.000000000 Z
11
+ date: 2025-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -213,9 +213,13 @@ files:
213
213
  - lib/graphiti/active_graph/adapters/active_graph/has_one_sideload.rb
214
214
  - lib/graphiti/active_graph/adapters/active_graph/polymorphic_belongs_to.rb
215
215
  - lib/graphiti/active_graph/adapters/active_graph/sideload.rb
216
+ - lib/graphiti/active_graph/concerns/path_relationships.rb
216
217
  - lib/graphiti/active_graph/deserializer.rb
218
+ - lib/graphiti/active_graph/extensions/grouping/params.rb
219
+ - lib/graphiti/active_graph/extensions/query_params.rb
217
220
  - lib/graphiti/active_graph/jsonapi_ext/serializable/resource_ext.rb
218
221
  - lib/graphiti/active_graph/query.rb
222
+ - lib/graphiti/active_graph/request_validators/validator.rb
219
223
  - lib/graphiti/active_graph/resource.rb
220
224
  - lib/graphiti/active_graph/resource/interface.rb
221
225
  - lib/graphiti/active_graph/resource/persistence.rb