Skip to content

Commit 65ad7b3

Browse files
Support fragments with aliases for CacheKeyBuilder (#25)
1 parent 35b45d0 commit 65ad7b3

File tree

4 files changed

+140
-0
lines changed

4 files changed

+140
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## master
44

5+
- [PR#25](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/25) Support fragments with aliases for CacheKeyBuilder ([@DmitryTsepelev][])
6+
57
## 1.0.0 (2020-06-13)
68

79
- [PR#24](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/24) Add nil caching. **BREAKING CHANGE**: custom cache stores must also implement `#exist?(key)` method ([@DmitryTsepelev][])

lib/graphql/fragment_cache/cache_key_builder.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,13 @@ def alias_selections
7676

7777
def lookup_alias_node(nodes, name)
7878
return if nodes.empty?
79+
7980
nodes.find do |node|
81+
if node.is_a?(GraphQL::Language::Nodes::FragmentSpread)
82+
node = @query.fragments[node.name]
83+
raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})") unless node
84+
end
85+
8086
return node if node.alias?(name)
8187
child = lookup_alias_node(node.children, name)
8288
return child if child

spec/graphql/fragment_cache/cache_key_builder_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,48 @@
221221

222222
specify { is_expected.to eq "schema_key/posts/0/cachedTitle[]" }
223223
end
224+
225+
context "when query has fragment" do
226+
let(:query) do
227+
<<~GQL
228+
fragment PostFragment on PostType {
229+
id
230+
author: cachedAuthor {
231+
name
232+
}
233+
}
234+
235+
query getPost($id: ID!) {
236+
post(id: $id) {
237+
...PostFragment
238+
}
239+
}
240+
GQL
241+
end
242+
243+
let(:path) { ["post", "author"] }
244+
245+
specify { is_expected.to eq "schema_key/post(id:1)/cachedAuthor[name]" }
246+
end
247+
248+
context "when query has inline fragment" do
249+
let(:query) do
250+
<<~GQL
251+
query getPost($id: ID!) {
252+
post(id: $id) {
253+
...on PostType {
254+
id
255+
author: cachedAuthor {
256+
name
257+
}
258+
}
259+
}
260+
}
261+
GQL
262+
end
263+
264+
let(:path) { ["post", "author"] }
265+
266+
specify { is_expected.to eq "schema_key/post(id:1)/cachedAuthor[name]" }
267+
end
224268
end

spec/graphql/fragment_cache/object_helpers_spec.rb

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,94 @@
180180
})
181181
end
182182

183+
context "when query has fragment" do
184+
let(:author) { User.new(id: 1, name: "John") }
185+
let!(:post) { Post.create(id: 1, title: "object test", author: author) }
186+
187+
let(:query_with_fragment) do
188+
<<~GQL
189+
fragment PostFragment on PostType {
190+
id
191+
author: cachedAuthor {
192+
name
193+
}
194+
}
195+
196+
query getPost($id: ID!) {
197+
post(id: $id) {
198+
...PostFragment
199+
}
200+
}
201+
GQL
202+
end
203+
204+
let(:resolver) do
205+
->(id:) do
206+
Post.find(id)
207+
end
208+
end
209+
210+
it "returns cached fragment" do
211+
author_data = execute_query(query_with_fragment).dig("data", "post", "author")
212+
expect(author_data).to eq({"name" => author.name})
213+
end
214+
215+
context "when fragment name is wrong" do
216+
let(:query_with_fragment) do
217+
<<~GQL
218+
fragment PostFragment on PostType {
219+
id
220+
author: cachedAuthor {
221+
name
222+
}
223+
}
224+
225+
query getPost($id: ID!) {
226+
post(id: $id) {
227+
...WrongPostFragment
228+
}
229+
}
230+
GQL
231+
end
232+
233+
it "returns cached fragment" do
234+
error_message = execute_query(query_with_fragment).dig("errors").first["message"]
235+
expect(error_message).to eq("Fragment WrongPostFragment was used, but not defined")
236+
end
237+
end
238+
end
239+
240+
context "when query has inline fragment" do
241+
let(:author) { User.new(id: 1, name: "John") }
242+
let!(:post) { Post.create(id: 1, title: "object test", author: author) }
243+
244+
let(:query_with_fragment) do
245+
<<~GQL
246+
query getPost($id: ID!) {
247+
post(id: $id) {
248+
...on PostType {
249+
id
250+
author: cachedAuthor {
251+
name
252+
}
253+
}
254+
}
255+
}
256+
GQL
257+
end
258+
259+
let(:resolver) do
260+
->(id:) do
261+
Post.find(id)
262+
end
263+
end
264+
265+
it "returns cached fragment" do
266+
author_data = execute_query(query_with_fragment).dig("data", "post", "author")
267+
expect(author_data).to eq({"name" => author.name})
268+
end
269+
end
270+
183271
context "with multiple aliases" do
184272
let(:query) do
185273
<<~GQL

0 commit comments

Comments
 (0)