graphql-sources 0.3.0 → 0.4.0

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: f88238e75afcee4b41463d85c77e4ec70a89afffe18baf5bdaa5a780e153335f
4
- data.tar.gz: eb3a39814d97bf3c06c6ea996cd50dcff262a170b5700edd4019f98c2ff80cad
3
+ metadata.gz: c950f4402666974cd24dd441f3b51caac7d337429518753e6886cecc9d9a46dd
4
+ data.tar.gz: 88194279dc3f9ea1f3a1e47349cc5620b7cf550badbe6c0720fa35fcbf20a340
5
5
  SHA512:
6
- metadata.gz: 968c6e5955b5f936c040d862219b890137fed330047670ffda3c7b79ecab1531f976696729e24fb50257acacfff6141296071d84d395e27bedfe757cde5f6f5f
7
- data.tar.gz: 6ec3329d4de24ca2fe71f7c339fa4e6e9d569e4ef6e940f4b1174b2707e8641a72857c4ae1cb30ad53b436a53875616d6a4d254586619d2ebf76bf8a9dc26707
6
+ metadata.gz: 4f63d94f097e6c72665be2086ee3736ba11c87ceb41935afcfcefb1fbb4b64d9b0fe71f93eea66bdc0ddb8f4846e637b320e6f1117631d2a6522638869fc2df2
7
+ data.tar.gz: 620fe9b524a7a0af4a67dbdfcc1f558f419977c25116830b3c46c42ed32f1fc86b1eba92c6a857c5ffc4d8814781cc989dca5b78519eefe6e04ef0b08f0c6b6a
data/README.md CHANGED
@@ -78,6 +78,46 @@ WHERE "comments"."user_id" IN (...)
78
78
  ORDER BY "comments"."id"
79
79
  ```
80
80
 
81
+ ### Loading `has_one_attached` Associations
82
+
83
+ ```ruby
84
+ class User
85
+ has_one_attached :avatar
86
+ end
87
+ ```
88
+
89
+ ```ruby
90
+ class UserType < GraphQL::Schema::Object
91
+ field :avatar, AttachedType, null: false
92
+
93
+ def avatar
94
+ dataloader
95
+ .with(GraphQL::Sources::ActiveStorageHasOneAttached, :avatar)
96
+ .load(object)
97
+ end
98
+ end
99
+ ```
100
+
101
+ ### Loading `has_many_attached` Associations
102
+
103
+ ```ruby
104
+ class User
105
+ has_many_attached :photos
106
+ end
107
+ ```
108
+
109
+ ```ruby
110
+ class UserType < GraphQL::Schema::Object
111
+ field :photos, [AttachedType], null: false
112
+
113
+ def photos
114
+ dataloader
115
+ .with(GraphQL::Sources::ActiveStorageHasOneAttached, :photos)
116
+ .load(object)
117
+ end
118
+ end
119
+ ```
120
+
81
121
  ### Loading Counts
82
122
 
83
123
  ```ruby
@@ -111,6 +151,12 @@ WHERE "likes"."post_id" IN (1, 2, 3, ...)
111
151
  GROUP BY "likes"."post_id"
112
152
  ```
113
153
 
154
+ ## Status
155
+
156
+ [![CircleCI](https://circleci.com/gh/ksylvest/graphql-sources.svg?style=svg)](https://circleci.com/gh/ksylvest/rhino)
157
+ [![Maintainability](https://api.codeclimate.com/v1/badges/bc301cb72712637e67dd/maintainability)](https://codeclimate.com/github/ksylvest/graphql-sources/maintainability)
158
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/bc301cb72712637e67dd/test_coverage)](https://codeclimate.com/github/ksylvest/graphql-sources/test_coverage)
159
+
114
160
  ## License
115
161
 
116
162
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphQL
4
+ module Sources
5
+ # An abstract class for interacting with active storage.
6
+ class ActiveStorageBase < GraphQL::Dataloader::Source
7
+ # @param name [String] the association name
8
+ def initialize(name)
9
+ super()
10
+ @name = name
11
+ end
12
+
13
+ protected
14
+
15
+ # @param records [Array<ActiveRecord::Base>] a collection of records to load attachments for
16
+ # @return [Array<ActiveStorage::Attachment>] the associated attachments with preloaded blobs
17
+ def attachments(records:)
18
+ ActiveStorage::Attachment
19
+ .preload(:blob)
20
+ .where(record: records)
21
+ .where(name: @name)
22
+ .order(:id)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './active_storage_base'
4
+
5
+ module GraphQL
6
+ module Sources
7
+ # A class for loading `has_many_attached` style associations.
8
+ #
9
+ # class User
10
+ # has_many_attached :photos
11
+ # end
12
+ #
13
+ # class UserType < GraphQL::Schema::Object
14
+ # field :photos, [AttachedType], null: false
15
+ #
16
+ # def photos
17
+ # dataloader
18
+ # .with(GraphQL::Sources::ActiveStorageHasManyAttached, :photos)
19
+ # .load(object)
20
+ # end
21
+ # end
22
+ #
23
+ # The resulting SQL query is:
24
+ #
25
+ # SELECT "active_storage_attachments".*
26
+ # FROM "active_storage_attachments"
27
+ # WHERE "active_storage_attachments"."name" = 'photos'
28
+ # AND "active_storage_attachments"."record_type" = 'User'
29
+ # AND "active_storage_attachments"."record_id" IN (...)
30
+ class ActiveStorageHasManyAttached < ActiveStorageBase
31
+ def fetch(records)
32
+ attachments = attachments(records: records).load_async
33
+ dataloader.yield
34
+
35
+ map = attachments.group_by { |attachment| [attachment.record_type, attachment.record_id] }
36
+ records.map { |record| map[[record.class.name, record.id]] || [] }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './active_storage_base'
4
+
5
+ module GraphQL
6
+ module Sources
7
+ # A class for loading `has_one_attached` style associations.
8
+ #
9
+ # class User
10
+ # has_one_attached :photo
11
+ # end
12
+ #
13
+ # class UserType < GraphQL::Schema::Object
14
+ # field :avatar, AttachedType, null: false
15
+ #
16
+ # def avatar
17
+ # dataloader
18
+ # .with(GraphQL::Sources::ActiveStorageHasOneAttached, :avatar)
19
+ # .load(object)
20
+ # end
21
+ # end
22
+ #
23
+ # The resulting SQL query is:
24
+ #
25
+ # SELECT "active_storage_attachments".*
26
+ # FROM "active_storage_attachments"
27
+ # WHERE "active_storage_attachments"."name" = 'avatar'
28
+ # AND "active_storage_attachments"."record_type" = 'User'
29
+ # AND "active_storage_attachments"."record_id" IN (...)
30
+ class ActiveStorageHasOneAttached < ActiveStorageBase
31
+ def fetch(records)
32
+ attachments = attachments(records: records).load_async
33
+ dataloader.yield
34
+
35
+ map = attachments.index_by { |attachment| [attachment.record_type, attachment.record_id] }
36
+ records.map { |record| map[[record.class.name, record.id]] }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GraphQL
4
4
  module Sources
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -5,6 +5,8 @@ require 'graphql'
5
5
  require_relative './sources/active_record_count'
6
6
  require_relative './sources/active_record_collection'
7
7
  require_relative './sources/active_record_object'
8
+ require_relative './sources/active_storage_has_many_attached'
9
+ require_relative './sources/active_storage_has_one_attached'
8
10
 
9
11
  module GraphQL
10
12
  # A collection of common GraphQL dataloader classes.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql-sources
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  description: Common loaders for various database or cache operations.
154
168
  email:
155
169
  - kevin@ksylvest.com
@@ -165,6 +179,9 @@ files:
165
179
  - lib/graphql/sources/active_record_collection.rb
166
180
  - lib/graphql/sources/active_record_count.rb
167
181
  - lib/graphql/sources/active_record_object.rb
182
+ - lib/graphql/sources/active_storage_base.rb
183
+ - lib/graphql/sources/active_storage_has_many_attached.rb
184
+ - lib/graphql/sources/active_storage_has_one_attached.rb
168
185
  - lib/graphql/sources/version.rb
169
186
  homepage: https://github.com/ksylvest/graphql-sources
170
187
  licenses: