graphql_includable 0.2.2 → 0.2.3

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
  SHA1:
3
- metadata.gz: 216d0034a2b3d1269aedfe519e49daa37d76295b
4
- data.tar.gz: d75e50c2b1f403d68b96185e9016089b3524fde4
3
+ metadata.gz: 67916fbd68ce3698cbecbc818655408ba89f8f1a
4
+ data.tar.gz: 930edfc340b740528fd689b2bfd196f2f81aeef8
5
5
  SHA512:
6
- metadata.gz: f02a18e427d3e3552d46e77d33837ba87d6af942899b3e8475cd45fffe932003145aa8dacb3fb9ff7378c737434e208a3f8af5c073abd106e0b5ec83020b9b1b
7
- data.tar.gz: 63af52fe0be0ee1aeb1d8418597aa99c950bd25704c4d60c7f6d9a9b5a747b4e74d1f41287a821accc55b24a3cf35a34175ef4a86125e369a00df03c8b5cce20
6
+ metadata.gz: 48fe0a1f6e0bb028e7f643df33ecfcecec7701cfc382f33cb0928305a00fa6b6007e3e71ed5890be67b25d50c41079dfbfdbaece299c18e1c47f85ed116ad8a0
7
+ data.tar.gz: cd524919a412f7e98dff775b2b676d16c6fd30868c8f63f982c44e6a10110cd3cbb7dc2ecf93d0d91034561f3282b47a804e67afd3845cbc538e3c66891839f9
@@ -6,16 +6,18 @@ module GraphQLIncludable
6
6
 
7
7
  module ClassMethods
8
8
  def includes_from_graphql(ctx)
9
- node = GraphQLIncludable::Concern.first_child_by_return_type(ctx.irep_node, model_name.to_s)
10
- generated_includes = Concern.includes_from_graphql_node(node)
9
+ node = Resolver.find_node_by_return_type(ctx.irep_node, model_name)
10
+ generated_includes = Resolver.includes_for_node(node)
11
+ byebug if generated_includes == {}
11
12
  includes(generated_includes)
13
+ rescue => e
14
+ self
12
15
  end
13
16
 
14
17
  def delegate_cache
15
18
  @delegate_cache ||= {}
16
19
  end
17
20
 
18
- # hook ActiveSupport's delegate method to track models and where their delegated methods go
19
21
  def delegate(*methods, args)
20
22
  methods.each do |method|
21
23
  delegate_cache[method] = args[:to]
@@ -23,154 +25,5 @@ module GraphQLIncludable
23
25
  super(*methods, args) if defined?(super)
24
26
  end
25
27
  end
26
-
27
- def self.first_child_by_return_type(node, model_name)
28
- matching_node = nil
29
- return_type = node.return_type.unwrap
30
- if return_type.to_s == model_name
31
- matching_node = node
32
- elsif node.respond_to?(:scoped_children)
33
- node.scoped_children[return_type].each_value do |child_node|
34
- matching_node = first_child_by_return_type(child_node, model_name)
35
- break if matching_node
36
- end
37
- end
38
- matching_node
39
- end
40
-
41
- def self.children_through_connection(node, return_model)
42
- includes = {}
43
- # if node_is_relay_connection?(node)
44
- # all_connection_children = node.scoped_children[node.return_type.unwrap]
45
- # connection_children = all_connection_children.except('edges')
46
- # edge_node = all_connection_children['edges']
47
- # all_edge_children = edge_node.scoped_children[edge_node.return_type.unwrap]
48
- # edge_children = all_edge_children.except('node')
49
- # target_node = all_edge_children['node']
50
- # children = target_node.scoped_children[target_node.return_type.unwrap]
51
-
52
- # target_association = return_model.reflect_on_association(node_return_class(target_node).name.underscore)
53
- # includes[target_association.name] = includes_from_graphql_node(target_node) if target_association
54
- # else
55
- children = node.scoped_children[node.return_type.unwrap]
56
- # end
57
-
58
- [children, includes]
59
- end
60
-
61
- def self.includes_from_graphql_node(node)
62
- return_model = node_return_class(node)
63
- return [] unless return_model
64
-
65
- includes = []
66
- children, nested_includes = children_through_connection(node, return_model)
67
- children.each_value do |child_node|
68
- child_includes = includes_from_graphql_child(child_node, return_model)
69
-
70
- if child_includes.is_a?(Hash)
71
- nested_includes.merge!(child_includes)
72
- else
73
- includes += child_includes.is_a?(Array) ? child_includes : [child_includes]
74
- end
75
- end
76
-
77
- includes << nested_includes unless nested_includes.blank?
78
- includes.uniq
79
- end
80
-
81
- def self.includes_from_graphql_child(child_node, return_model)
82
- specified_includes = child_node.definitions[0].metadata[:includes]
83
- attribute_name = node_predicted_association_name(child_node)
84
- includes_chain = delegated_includes_chain(return_model, attribute_name)
85
- association = get_model_association(return_model, attribute_name, includes_chain)
86
-
87
- if association
88
- child_includes = includes_from_graphql_node(child_node)
89
- join_name = (specified_includes || attribute_name)
90
-
91
- # if node_is_relay_connection?(child_node)
92
- # join_name = association.options[:through]
93
- # edge_includes_chain = [association.name]
94
- # edge_includes_chain << child_includes.pop[association.name.to_s.singularize.to_sym] if child_includes.last&.is_a?(Hash)
95
- # edge_includes = array_to_nested_hash(edge_includes_chain)
96
- # end
97
-
98
- includes_chain << join_name
99
- includes_chain << child_includes unless child_includes.blank?
100
- # byebug if node_is_relay_connection?(child_node)
101
- edge_includes=nil
102
- [edge_includes, array_to_nested_hash(includes_chain)].reject(&:blank?)
103
- else
104
- includes = []
105
- includes << array_to_nested_hash(includes_chain) unless includes_chain.blank?
106
- includes << specified_includes if specified_includes
107
- includes
108
- end
109
- end
110
-
111
- def self.node_return_class(node)
112
- # rubocop:disable Lint/HandleExceptions, Style/RedundantBegin
113
- begin
114
- Object.const_get(node.return_type.unwrap.name.gsub(/(^SquareFoot|Edge$|Connection$)/, ''))
115
- rescue NameError
116
- end
117
- # rubocop:enable Lint/HandleExceptions, Style/RedundantBegin
118
- end
119
-
120
- def self.node_is_relay_connection?(node)
121
- node.return_type.unwrap.name =~ /Connection$/
122
- end
123
-
124
- def self.node_returns_active_record?(node)
125
- klass = node_return_class(node)
126
- klass && klass < ActiveRecord::Base
127
- end
128
-
129
- def self.node_predicted_association_name(node)
130
- definition = node.definitions[0]
131
- specified_includes = definition.metadata[:includes]
132
- if specified_includes.is_a?(Symbol)
133
- specified_includes
134
- else
135
- (definition.property || definition.name).to_sym
136
- end
137
- end
138
-
139
- def self.get_model_association(model, association_name, includes_chain = nil)
140
- delegated_model = model_name_to_class(includes_chain.last) unless includes_chain.blank?
141
- (delegated_model || model).reflect_on_association(association_name)
142
- end
143
-
144
- # get a 1d array of the chain of delegated model names,
145
- # so if model A delegates method B to model C, which delegates method B to model D,
146
- # delegated_includes_chain(A, :B) => [:C, :D]
147
- def self.delegated_includes_chain(base_model, method_name)
148
- chain = []
149
- method = method_name.to_sym
150
- model_name = base_model.instance_variable_get('@delegate_cache').try(:[], method)
151
- while model_name
152
- chain << model_name
153
- model = model_name_to_class(model_name)
154
- model_name = model.instance_variable_get('@delegate_cache').try(:[], method)
155
- end
156
- chain
157
- end
158
-
159
- # convert a 1d array into a nested hash
160
- # e.g. [:foo, :bar, :baz] => { :foo => { :bar => :baz }}
161
- def self.array_to_nested_hash(arr)
162
- arr.reverse.inject { |acc, item| { item => acc } }
163
- end
164
-
165
- # convert a model name into a class variable,
166
- # e.g. :search_parameters -> SearchParameters
167
- def self.model_name_to_class(model_name)
168
- begin
169
- model = model_name.to_s.camelize.constantize
170
- rescue NameError
171
- model = model_name.to_s.singularize.camelize.constantize
172
- end
173
- model
174
- end
175
28
  end
176
29
  end
@@ -5,15 +5,17 @@ module GraphQLIncludable
5
5
  edge_class_name = join_chain.shift
6
6
  edge_class = str_to_class(edge_class_name)
7
7
 
8
- root_node = { class_to_str(parent.class).to_s.singularize => parent }
9
- terminal_node = { class_to_str(node.class).singularize => node }
8
+ root_association_key = class_to_str(parent.class).to_sym
9
+ root_node = { root_association_key => [parent] }
10
+ terminal_node = { class_to_str(node.class) => node }
10
11
  join_chain.reverse.each do |rel_name|
11
12
  terminal_node = { rel_name.to_s.pluralize => terminal_node }
12
13
  end
14
+
13
15
  search_hash = root_node.merge(terminal_node)
14
16
  edge_includes = join_chain.map { |s| s.to_s.singularize }
15
17
  edge_class = edge_class.includes(*edge_includes) unless edge_includes.empty?
16
- @edge ||= edge_class.find_by(search_hash)
18
+ @edge ||= edge_class.joins(root_association_key).find_by(search_hash)
17
19
  end
18
20
 
19
21
  def method_missing(method_name, *args, &block)
@@ -36,21 +38,29 @@ module GraphQLIncludable
36
38
  end
37
39
 
38
40
  def class_to_str(klass)
39
- klass.name.pluralize.downcase
41
+ klass.name.downcase
40
42
  end
41
43
 
42
44
  def joins_along_edge
43
- join_chain = []
44
- starting_class = parent.class
45
- node_relationship_name = class_to_str(node.class)
46
- while starting_class
47
- reflection = starting_class.reflect_on_association(node_relationship_name)
48
- association_name = reflection&.options&.try(:[], :through)
49
- join_chain << association_name if association_name
50
- starting_class = str_to_class(association_name)
51
- node_relationship_name = node_relationship_name.singularize
45
+ edge_association_name = node.class.name.pluralize.downcase.to_sym
46
+ edge_association = parent.class.reflect_on_association(edge_association_name)
47
+ edge_joins = []
48
+ while edge_association.is_a? ActiveRecord::Reflection::ThroughReflection
49
+ edge_joins.unshift edge_association.options[:through]
50
+ edge_association = parent.class.reflect_on_association(edge_association.options[:through])
52
51
  end
53
- join_chain
52
+ edge_joins
53
+ # join_chain = []
54
+ # starting_class = parent.class
55
+ # node_relationship_name = class_to_str(node.class)
56
+ # while starting_class
57
+ # reflection = starting_class.reflect_on_association(node_relationship_name)
58
+ # association_name = reflection&.options&.try(:[], :through)
59
+ # join_chain << association_name if association_name
60
+ # starting_class = str_to_class(association_name)
61
+ # node_relationship_name = node_relationship_name.singularize
62
+ # end
63
+ # join_chain
54
64
  end
55
65
  end
56
66
  end
@@ -1,4 +1,5 @@
1
1
  require 'graphql'
2
+ require 'graphql_includable/resolver'
2
3
  require 'graphql_includable/concern'
3
4
  require 'graphql_includable/edge'
4
5
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_includable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Rouse
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-03-02 00:00:00.000000000 Z
12
+ date: 2018-04-09 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email:
@@ -42,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
42
42
  version: '0'
43
43
  requirements: []
44
44
  rubyforge_project:
45
- rubygems_version: 2.5.2
45
+ rubygems_version: 2.6.11
46
46
  signing_key:
47
47
  specification_version: 4
48
48
  summary: An ActiveSupport::Concern for GraphQL Ruby to eager-load query data