graphiti_gql 0.2.0 → 0.2.1

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: 2a19fd68dc698b8a7284fe80686da9f50ee137365508241cd374e32aa6c505aa
4
- data.tar.gz: d509f137452b90e94986c46267f8728160021de305e599ba47512af9366fe109
3
+ metadata.gz: ff76a3032a8378019cc0034c48cc1bd33302a8d662515fd722d970e642ee355e
4
+ data.tar.gz: 532980890cd827d260bceebd5f944eeb999a561cde6df3e14cff5ddbfaa5f146
5
5
  SHA512:
6
- metadata.gz: 22f8643e779d272d806d53179e5f83e6ca6157fc8c261e03ea3232fdf685faa35ad50c70bd3f5f0f445b8bd4578e616b9a538c9205e330a301a30f370b2c612a
7
- data.tar.gz: ec6e08b56162dc2bb077bfd3cfc5fb5dcf8edcdc3680d940347eb33949f8530967e6d828e0b914f0920a406bad4807d83c643981f9ab0136dd7a3e9e422e068a
6
+ metadata.gz: 8a67a1e359377aa6682b2f23fd0461b2547a05df41c14739d4abf691d879682dd8cd83a4e4deda386855ae6c7a587feb453b2aff5490d2e0d44998955ff6bba9
7
+ data.tar.gz: f5f83d5859fc24f3215723d3abd7d1105dcefc3f02002853f829a4d954923444df0d1a37c0cbbb736dbb79df9745dd1be1c197c6151b07febb117272eb12e8e7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- graphiti_gql (0.1.0)
4
+ graphiti_gql (0.2.1)
5
5
  graphiti (~> 1.3.9)
6
6
  graphql (~> 2.0)
7
7
  graphql-batch (~> 0.5)
@@ -121,6 +121,24 @@ module GraphitiGql
121
121
  end
122
122
  Graphiti::Scoping::Paginate.send(:prepend, PaginateExtras)
123
123
 
124
+ module ManyToManyExtras
125
+ extend ActiveSupport::Concern
126
+
127
+ class_methods do
128
+ attr_accessor :edge_resource
129
+
130
+ def attribute(*args, &blk)
131
+ @edge_resource = Class.new(Graphiti::Resource) do
132
+ def self.abstract_class?
133
+ true
134
+ end
135
+ end
136
+ @edge_resource.attribute(*args, &blk)
137
+ end
138
+ end
139
+ end
140
+ Graphiti::Sideload::ManyToMany.send(:include, ManyToManyExtras)
141
+
124
142
  module StatsExtras
125
143
  def calculate_stat(name, function)
126
144
  config = @resource.all_attributes[name] || {}
@@ -166,7 +184,9 @@ module GraphitiGql
166
184
  alias_method :filter_precise_datetime_not_eq, :filter_not_eq
167
185
  end
168
186
  end
169
- Graphiti::Adapters::ActiveRecord.send(:include, ActiveRecordAdapterExtras)
187
+ if defined?(Graphiti::Adapters::ActiveRecord)
188
+ Graphiti::Adapters::ActiveRecord.send(:include, ActiveRecordAdapterExtras)
189
+ end
170
190
 
171
191
  Graphiti::Adapters::Abstract.class_eval do
172
192
  class << self
@@ -215,4 +235,17 @@ module GraphitiGql
215
235
  end
216
236
  end
217
237
  Graphiti::Scope.send(:prepend, ScopeExtras)
238
+
239
+ module ActiveRecordManyToManyExtras
240
+ # flipping .includes to .joins
241
+ def belongs_to_many_filter(scope, value)
242
+ scope
243
+ .joins(through_relationship_name)
244
+ .where(belongs_to_many_clause(value, type))
245
+ end
246
+ end
247
+ if defined?(ActiveRecord)
248
+ ::Graphiti::Adapters::ActiveRecord::ManyToManySideload
249
+ .send(:prepend, ActiveRecordManyToManyExtras)
250
+ end
218
251
  end
@@ -2,15 +2,32 @@ module GraphitiGql
2
2
  module Loaders
3
3
  class ManyToMany < Many
4
4
  def assign(ids, proxy)
5
- records = proxy.data
6
5
  thru = @sideload.foreign_key.keys.first
7
6
  fk = @sideload.foreign_key[thru]
7
+ add_join_table_magic(proxy)
8
+ records = proxy.data
8
9
  ids.each do |id|
9
- match = ->(thru) { thru.send(fk) == id }
10
- corresponding = records.select { |record| record.send(thru).any?(&match) }
10
+ corresponding = records.select do |record|
11
+ record.send(:"_edge_#{fk}") == id
12
+ end
11
13
  fulfill(id, [corresponding, proxy])
12
14
  end
13
15
  end
16
+
17
+ private
18
+
19
+ def add_join_table_magic(proxy)
20
+ if defined?(ActiveRecord) && proxy.resource.model.ancestors.include?(ActiveRecord::Base)
21
+ thru = @sideload.foreign_key.keys.first
22
+ thru_model = proxy.resource.model.reflect_on_association(thru).klass
23
+ names = thru_model.column_names.map do |n|
24
+ "#{thru_model.table_name}.#{n} as _edge_#{n}"
25
+ end
26
+ scope = proxy.scope.object
27
+ scope = scope.select(["#{proxy.resource.model.table_name}.*"] + names)
28
+ proxy.scope.object = scope
29
+ end
30
+ end
14
31
  end
15
32
  end
16
33
  end
@@ -2,10 +2,12 @@ module GraphitiGql
2
2
  class Schema
3
3
  module Fields
4
4
  class Attribute
5
- def initialize(name, config)
5
+ # If sideload is present, we're applying m2m metadata to an edge
6
+ def initialize(name, config, sideload = nil)
6
7
  @config = config
7
8
  @name = name
8
9
  @alias = config[:alias]
10
+ @sideload = sideload # is_edge: true
9
11
  end
10
12
 
11
13
  def apply(type)
@@ -13,20 +15,39 @@ module GraphitiGql
13
15
  _config = @config
14
16
  _name = @name
15
17
  _alias = @alias
18
+ _sideload = @sideload
16
19
  opts = @config.slice(:null, :deprecation_reason)
17
20
  type.field(_name, field_type, **opts)
18
21
  type.define_method _name do
19
22
  if (readable = _config[:readable]).is_a?(Symbol)
20
- resource = object.instance_variable_get(:@__graphiti_resource)
23
+ obj = object
24
+ obj = object.node if _sideload
25
+ resource = obj.instance_variable_get(:@__graphiti_resource)
21
26
  unless resource.send(readable)
22
27
  path = Graphiti.context[:object][:current_path].join(".")
23
28
  raise Errors::UnauthorizedField.new(path)
24
29
  end
25
30
  end
31
+
32
+ edge_attrs = nil
33
+ if _sideload
34
+ edge_attrs = object.node.attributes
35
+ .select { |k, v| k.to_s.starts_with?("_edge_") }
36
+ edge_attrs.transform_keys! { |k| k.to_s.gsub("_edge_", "").to_sym }
37
+ end
38
+
26
39
  value = if _config[:proc]
27
- instance_eval(&_config[:proc])
40
+ if _sideload
41
+ instance_exec(edge_attrs, &_config[:proc])
42
+ else
43
+ instance_eval(&_config[:proc])
44
+ end
28
45
  else
29
- object.send(_alias || _name)
46
+ if _sideload
47
+ edge_attrs[_alias || _name]
48
+ else
49
+ object.send(_alias || _name)
50
+ end
30
51
  end
31
52
  return if value.nil?
32
53
  Graphiti::Types[_config[:type]][:read].call(value)
@@ -36,9 +57,12 @@ module GraphitiGql
36
57
  private
37
58
 
38
59
  def field_type
39
- canonical_graphiti_type = Graphiti::Types.name_for(@config[:type])
40
- field_type = GQL_TYPE_MAP[canonical_graphiti_type.to_sym]
41
- field_type = String if @name == :id
60
+ field_type = Graphiti::Types[@config[:type]][:graphql_type]
61
+ if !field_type
62
+ canonical_graphiti_type = Graphiti::Types.name_for(@config[:type])
63
+ field_type = GQL_TYPE_MAP[canonical_graphiti_type.to_sym]
64
+ field_type = String if @name == :id
65
+ end
42
66
  field_type = [field_type] if @config[:type].to_s.starts_with?("array_of")
43
67
  field_type
44
68
  end
@@ -4,7 +4,11 @@ module GraphitiGql
4
4
  class ToMany
5
5
  def initialize(sideload, sideload_type)
6
6
  @sideload = sideload
7
- @sideload_type = sideload_type
7
+ @sideload_type = if customized_edge?
8
+ build_customized_edge_type(sideload_type)
9
+ else
10
+ sideload_type
11
+ end
8
12
  end
9
13
 
10
14
  def apply(type)
@@ -31,6 +35,33 @@ module GraphitiGql
31
35
  Loaders::Many.factory(_sideload, params).load(id)
32
36
  end
33
37
  end
38
+
39
+ private
40
+
41
+ def customized_edge?
42
+ @sideload.type == :many_to_many && @sideload.class.edge_resource
43
+ end
44
+
45
+ def build_customized_edge_type(sideload_type)
46
+ # build the edge class
47
+ prior_edge_class = sideload_type.edge_type_class
48
+ edge_class = Class.new(prior_edge_class)
49
+ edge_resource = @sideload.class.edge_resource
50
+ edge_resource.attributes.each_pair do |name, config|
51
+ next if name == :id
52
+ Schema::Fields::Attribute.new(name, config, @sideload).apply(edge_class)
53
+ end
54
+ registered_parent = Schema.registry.get(@sideload.parent_resource.class)
55
+ parent_name = registered_parent[:type].graphql_name
56
+ edge_class.define_method :graphql_name do
57
+ "#{parent_name}To#{sideload_type.graphql_name}Edge"
58
+ end
59
+
60
+ # build the sideload type with new edge class applied
61
+ klass = Class.new(sideload_type)
62
+ klass.edge_type_class(edge_class)
63
+ klass
64
+ end
34
65
  end
35
66
  end
36
67
  end
@@ -1,3 +1,3 @@
1
1
  module GraphitiGql
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphiti_gql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Richmond
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-16 00:00:00.000000000 Z
11
+ date: 2022-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -108,7 +108,7 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '7.0'
111
- description:
111
+ description:
112
112
  email:
113
113
  - richmolj@gmail.com
114
114
  executables: []
@@ -167,7 +167,7 @@ licenses:
167
167
  - MIT
168
168
  metadata:
169
169
  homepage_uri: https://www.graphiti.dev
170
- post_install_message:
170
+ post_install_message:
171
171
  rdoc_options: []
172
172
  require_paths:
173
173
  - lib
@@ -182,8 +182,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
182
182
  - !ruby/object:Gem::Version
183
183
  version: '0'
184
184
  requirements: []
185
- rubygems_version: 3.0.3.1
186
- signing_key:
185
+ rubygems_version: 3.3.7
186
+ signing_key:
187
187
  specification_version: 4
188
188
  summary: GraphQL support for Graphiti
189
189
  test_files: []