graphql-rails-api 0.1.6 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b644695c5f738ce04ffbffc6751c67f43b5e3e5abe171e39ea98f5a526b50aaf
4
- data.tar.gz: b59bdb2628478c676369f59a594181e1cc3a4d98d8ccdbb9ac9e4a52ebdb2f14
3
+ metadata.gz: d57fa3b16ccdcf04df7d00d4fe67475c52023335a4655a2efa0261023a4cf78c
4
+ data.tar.gz: 13a7ae285e5f4594322f9960d400f9657c06326e57bfde6322633764b573e3b0
5
5
  SHA512:
6
- metadata.gz: 7d9293440b05eb1bad81b54d1f980a1247947a19a1282a0713d34d64b440fcfb1f5fdf472ea11530abf2c0b56f94e826acd9cc5b3339bfc2543959a042c8628d
7
- data.tar.gz: a8845eb6c68a3b49fe778144bbdcf2986a7ea5f2197b3fcb90217941dc683726508a51bc6898bfee325c0a532241cccf469d4986d8f646baa9976b2b69b0b353
6
+ metadata.gz: 525754f37def8d961cceb0ae151d44e00369b8f2099f5ad6648f5ab276759b9de36ad1e1ed0e50f1ec48130f5c0088be7193d5bbd8d881c699fa3e1f84f16d95
7
+ data.tar.gz: 9d5d568d8e8e22a50ef9b4760629cb1efbcf6a536c397510bc4d170bba5d4e178962a3ef933cba12ab8c4a45078319c45e33bc9824a9d16ddf1707bc2a6fdf66
@@ -10,115 +10,53 @@ module Graphql
10
10
 
11
11
  def run
12
12
  hash = parse_fields(@fields)
13
- selectable_values = transform_to_selectable_values(hash)
14
- joins = remove_keys_with_nil_values(Marshal.load(Marshal.dump(hash)))
15
- join_model = @model.includes(joins)
16
- join_model = join_model.where(id: @id) if @id.present?
17
- res2d = pluck_to_hash_with_ids(join_model, pluckable_attributes(selectable_values))
18
- joins_with_root = { model_name.to_sym => remove_keys_with_nil_values(Marshal.load(Marshal.dump(hash))) }
19
- ir = nest(joins_with_root, res2d).first
20
- @visibility_hash = Graphql::VisibilityHash.new(joins_with_root, @user).run
21
- @id ? ir_to_output(ir).first : ir_to_output(ir)
13
+ array = hash_to_array_of_hashes(hash, @model)
14
+ @model = @model.where(id: @id) if @id
15
+ plucked = @model.deep_pluck(*array)
16
+ result = plucked_attr_to_structs(plucked)
17
+ @id ? result.first : result
22
18
  end
23
19
 
24
- def pluck_to_hash_with_ids(model, keys)
25
- keys.each do |k|
26
- resource = k.split('.').first
27
- keys << "#{resource.pluralize}.id" unless keys.include?("#{resource}.id")
28
- end
29
- keys = keys.compact.uniq
30
- model.pluck(*keys).map do |pa|
31
- Hash[keys.zip([pa].flatten)]
32
- end
20
+ def plucked_attr_to_structs(arr)
21
+ arr.map { |e| hash_to_struct(e) }
33
22
  end
34
23
 
35
- def pluckable_attributes(keys)
36
- db_attributes = keys.uniq.map { |k| k.gsub(/\..*$/, '') }.uniq.map do |resource|
37
- next unless Object.const_defined?(resource.singularize.camelize)
38
- resource.singularize.camelize.constantize.new.attributes.keys.map do |attribute|
39
- "#{resource}.#{attribute}"
40
- end
41
- end.flatten.compact
42
- keys.select { |e| db_attributes.flatten.include?(e) }.map do |e|
43
- split = e.split('.')
44
- "#{split.first.pluralize}.#{split.last}"
24
+ def hash_to_struct(hash)
25
+ hash.each_with_object(OpenStruct.new) do |(k, v), struct|
26
+ next struct[k.to_sym] = plucked_attr_to_structs(v) if v.is_a?(Array)
27
+ next struct[k.to_sym] = hash_to_struct(v) if v.is_a?(Hash)
28
+ struct[k.to_sym] = v
45
29
  end
46
30
  end
47
31
 
48
- def ir_to_output(inter_result)
49
- model_name = inter_result&.first&.first&.first&.first&.to_s
50
- return [] if model_name.blank?
51
- res = if singular?(model_name)
52
- ir_node_to_output(inter_result.first)
53
- else
54
- inter_result.map { |ir_node| ir_node_to_output(ir_node) if ir_node }
55
- end
56
- res.compact! if res.is_a?(Array)
57
- res
58
- end
59
-
60
- def ir_node_to_output(ir_node)
61
- model_name = ir_node.keys.reject { |key| key == :results }.first.first.to_s
62
- t = ir_node[:results].first.each_with_object({}) do |(attribute, v), h|
63
- h[attribute.gsub(model_name.pluralize + '.', '')] = v
32
+ def hash_to_array_of_hashes(hash, parent_class)
33
+ return if parent_class.nil?
34
+ hash.each_with_object([]) do |(k, v), arr|
35
+ next arr << k if v.blank? && parent_class.new.attributes.key?(k)
36
+ klass = evaluate_model(parent_class, k)
37
+ arr << { k.to_sym => hash_to_array_of_hashes(v, klass) } if klass.present? && v.present?
64
38
  end
65
- relations = ir_node.values&.first&.map { |e| e&.first&.first&.first&.first }
66
- relations.zip(ir_node[ir_node.keys.reject { |key| key == :results }&.first]).to_h.map do |key, value|
67
- res = ir_to_output(value)
68
- t[key] = res if value
69
- t[key].compact! if t[key].is_a?(Array)
70
- end
71
- return unless @visibility_hash[model_name.singularize.to_sym]&.include?(t['id'])
72
- Struct.new(*t.keys.map(&:to_sym)).new(*t.values) if !t.keys.blank? && !t.values.compact.blank?
73
- end
74
-
75
- def singular?(string)
76
- string.singularize == string
77
39
  end
78
40
 
79
- def nest(joins, res)
80
- joins.map do |relation_name, other_joins|
81
- res.group_by do |row|
82
- [relation_name, row["#{relation_name.to_s.pluralize}.id"]]
83
- end.map do |k, ungrouped|
84
- Hash[k, nest(other_joins, ungrouped)].merge(results: extract_values_of_level(k[0], ungrouped).uniq)
85
- end
86
- end
87
- end
88
-
89
- def extract_values_of_level(level, ungrouped)
90
- ungrouped.map do |row|
91
- row.select { |k, _| k =~ /#{level.to_s.pluralize}.*/ }
92
- end
93
- end
94
-
95
- def transform_to_selectable_values(hash, res = nil)
96
- @values ||= []
97
- hash.each do |k, v|
98
- if v.nil?
99
- @values << "#{res || model_name}.#{k}" unless activerecord_model?(k)
100
- else
101
- next @values << "#{res || model_name}.#{k}" unless activerecord_model?(k)
102
- transform_to_selectable_values(v, k)
103
- end
41
+ def activerecord_model?(name)
42
+ class_name = name.to_s.singularize.camelize
43
+ begin
44
+ class_name.constantize.ancestors.include?(ApplicationRecord)
45
+ rescue NameError
46
+ false
104
47
  end
105
- @values
106
48
  end
107
49
 
108
- def remove_keys_with_nil_values(hash)
109
- hash.symbolize_keys!
110
- hash.each_key do |k|
111
- if hash[k].nil? || !activerecord_model?(k)
112
- hash.delete(k)
113
- else
114
- remove_keys_with_nil_values(hash[k])
115
- end
116
- end
50
+ def evaluate_model(parent, child)
51
+ child_class_name = child.to_s.singularize.camelize
52
+ parent_class_name = parent.to_s.singularize.camelize
53
+ return child_class_name.constantize if activerecord_model?(child_class_name)
54
+ return unless activerecord_model?(parent_class_name)
55
+ parent_class_name.constantize.reflections[child.to_s.underscore]&.klass
117
56
  end
118
57
 
119
58
  def parse_fields(fields)
120
59
  fields.each_with_object({}) do |(k, v), h|
121
- next if k == '__typename'
122
60
  h[k] = v.scoped_children == {} ? nil : parse_fields(v.scoped_children.values.first)
123
61
  end
124
62
  end
@@ -127,14 +65,5 @@ module Graphql
127
65
  @model.class.to_s.split('::').first.underscore.pluralize
128
66
  end
129
67
 
130
- def activerecord_model?(name)
131
- class_name = name.to_s.singularize.camelize
132
- begin
133
- class_name.constantize.ancestors.include?(ApplicationRecord)
134
- rescue NameError
135
- false
136
- end
137
- end
138
-
139
68
  end
140
69
  end
@@ -1,7 +1,7 @@
1
1
  module Graphql
2
2
  module Rails
3
3
  module Api
4
- VERSION = '0.1.6'.freeze
4
+ VERSION = '0.2'.freeze
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-rails-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - poilon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-11 00:00:00.000000000 Z
11
+ date: 2018-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: deep_pluck
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: graphql
15
29
  requirement: !ruby/object:Gem::Requirement