gqli 0.1.0

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.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +31 -0
  5. data/.rubocop_todo.yml +44 -0
  6. data/.travis.yml +13 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +9 -0
  9. data/Gemfile +9 -0
  10. data/Gemfile.lock +154 -0
  11. data/Guardfile +24 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +284 -0
  14. data/Rakefile +33 -0
  15. data/coverage/.last_run.json +5 -0
  16. data/coverage/.resultset.json +512 -0
  17. data/coverage/.resultset.json.lock +0 -0
  18. data/coverage/assets/0.10.2/application.css +799 -0
  19. data/coverage/assets/0.10.2/application.js +1707 -0
  20. data/coverage/assets/0.10.2/colorbox/border.png +0 -0
  21. data/coverage/assets/0.10.2/colorbox/controls.png +0 -0
  22. data/coverage/assets/0.10.2/colorbox/loading.gif +0 -0
  23. data/coverage/assets/0.10.2/colorbox/loading_background.png +0 -0
  24. data/coverage/assets/0.10.2/favicon_green.png +0 -0
  25. data/coverage/assets/0.10.2/favicon_red.png +0 -0
  26. data/coverage/assets/0.10.2/favicon_yellow.png +0 -0
  27. data/coverage/assets/0.10.2/loading.gif +0 -0
  28. data/coverage/assets/0.10.2/magnify.png +0 -0
  29. data/coverage/assets/0.10.2/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  30. data/coverage/assets/0.10.2/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  31. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  32. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  33. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  34. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  35. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  36. data/coverage/assets/0.10.2/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  37. data/coverage/assets/0.10.2/smoothness/images/ui-icons_222222_256x240.png +0 -0
  38. data/coverage/assets/0.10.2/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  39. data/coverage/assets/0.10.2/smoothness/images/ui-icons_454545_256x240.png +0 -0
  40. data/coverage/assets/0.10.2/smoothness/images/ui-icons_888888_256x240.png +0 -0
  41. data/coverage/assets/0.10.2/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  42. data/coverage/index.html +3255 -0
  43. data/doc/GQLi/Base.html +628 -0
  44. data/doc/GQLi/Client.html +830 -0
  45. data/doc/GQLi/DSL.html +421 -0
  46. data/doc/GQLi/Fragment.html +405 -0
  47. data/doc/GQLi/Introspection.html +837 -0
  48. data/doc/GQLi/Node.html +413 -0
  49. data/doc/GQLi/Query.html +390 -0
  50. data/doc/GQLi/Response.html +370 -0
  51. data/doc/GQLi.html +157 -0
  52. data/doc/_index.html +236 -0
  53. data/doc/class_list.html +51 -0
  54. data/doc/css/common.css +1 -0
  55. data/doc/css/full_list.css +58 -0
  56. data/doc/css/style.css +496 -0
  57. data/doc/file.CHANGELOG.html +76 -0
  58. data/doc/file.LICENSE.html +70 -0
  59. data/doc/file.README.html +365 -0
  60. data/doc/file_list.html +66 -0
  61. data/doc/frames.html +17 -0
  62. data/doc/index.html +365 -0
  63. data/doc/js/app.js +292 -0
  64. data/doc/js/full_list.js +216 -0
  65. data/doc/js/jquery.js +4 -0
  66. data/doc/method_list.html +355 -0
  67. data/doc/top-level-namespace.html +110 -0
  68. data/gqli.gemspec +37 -0
  69. data/lib/gqli/base.rb +53 -0
  70. data/lib/gqli/client.rb +59 -0
  71. data/lib/gqli/dsl.rb +37 -0
  72. data/lib/gqli/fragment.rb +25 -0
  73. data/lib/gqli/introspection.rb +215 -0
  74. data/lib/gqli/node.rb +48 -0
  75. data/lib/gqli/query.rb +29 -0
  76. data/lib/gqli/response.rb +15 -0
  77. data/lib/gqli/version.rb +7 -0
  78. data/lib/gqli.rb +6 -0
  79. data/spec/fixtures/vcr_cassettes/catCollection.yml +63 -0
  80. data/spec/fixtures/vcr_cassettes/client.yml +171 -0
  81. data/spec/fixtures/vcr_cassettes/validation_error.yml +62 -0
  82. data/spec/lib/gqli/client_spec.rb +90 -0
  83. data/spec/lib/gqli/dsl_spec.rb +205 -0
  84. data/spec/lib/gqli/introspection_spec.rb +125 -0
  85. data/spec/spec_helper.rb +25 -0
  86. data/usage.rb +100 -0
  87. data/usage_introspection.rb +63 -0
  88. data/usage_with_inlined_dsl.rb +69 -0
  89. metadata +387 -0
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe GQLi::Client do
4
+ let(:client) do
5
+ vcr('client') {
6
+ space_id = 'cfexampleapi'
7
+ token = 'b4c0n73n7fu1'
8
+ GQLi::Client.new(
9
+ "https://graphql.contentful.com/content/v1/spaces/#{space_id}",
10
+ headers: { "Authorization" => "Bearer #{token}" }
11
+ )
12
+ }
13
+ end
14
+
15
+ let(:client_no_validations) do
16
+ vcr('client') {
17
+ space_id = 'cfexampleapi'
18
+ token = 'b4c0n73n7fu1'
19
+ GQLi::Client.new(
20
+ "https://graphql.contentful.com/content/v1/spaces/#{space_id}",
21
+ headers: { "Authorization" => "Bearer #{token}" },
22
+ validate_query: false
23
+ )
24
+ }
25
+ end
26
+
27
+ let(:dsl) { GQLi::DSL }
28
+
29
+ context 'validations enabled' do
30
+ subject { client }
31
+
32
+ it 'upon instantiation caches the schema' do
33
+ expect(subject.schema.types).not_to be_empty
34
+ end
35
+
36
+ it 'when executing a query performs schema validation' do
37
+ vcr('catCollection') {
38
+ expect(subject.execute(
39
+ dsl.query {
40
+ catCollection {
41
+ items {
42
+ name
43
+ }
44
+ }
45
+ }).data
46
+ ).not_to be_empty
47
+
48
+ expect { subject.execute(
49
+ dsl.query {
50
+ foobar
51
+ }
52
+ )}.to raise_exception 'Validation Error: query is invalid - HTTP Request not sent'
53
+ }
54
+ end
55
+
56
+ it 'can skip validations when using `#execute!`' do
57
+ vcr('validation_error') {
58
+ expect { subject.execute!(
59
+ dsl.query {
60
+ foobar
61
+ }
62
+ )}.to raise_exception([
63
+ "Error: Bad Request",
64
+ 'Body: {"errors":[{"message":"Cannot query field \"foobar\" on type \"Query\".","locations":[{"line":2,"column":3}]}]}'
65
+ ].join("\n"))
66
+ }
67
+ end
68
+ end
69
+
70
+ context 'validations disabled' do
71
+ subject { client_no_validations }
72
+
73
+ it 'upon instantiation doesnt cache the schema' do
74
+ expect(subject.schema).to be_nil
75
+ end
76
+
77
+ it 'when executing a query doesnt perform schema validation' do
78
+ vcr('validation_error') {
79
+ expect { subject.execute(
80
+ dsl.query {
81
+ foobar
82
+ }
83
+ )}.to raise_exception([
84
+ "Error: Bad Request",
85
+ 'Body: {"errors":[{"message":"Cannot query field \"foobar\" on type \"Query\".","locations":[{"line":2,"column":3}]}]}'
86
+ ].join("\n"))
87
+ }
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+
3
+ class MockGQLInterface
4
+ include GQLi::DSL
5
+ end
6
+
7
+ describe GQLi::DSL do
8
+ subject { described_class }
9
+
10
+ describe 'module level methods' do
11
+ describe '::query' do
12
+ it 'can create a query without name' do
13
+ query = subject.query {
14
+ someField
15
+ }
16
+
17
+ expect(query).to be_a GQLi::Query
18
+ expect(query.to_gql).to eq <<~GRAPHQL
19
+ query {
20
+ someField
21
+ }
22
+ GRAPHQL
23
+ end
24
+
25
+ it 'can create a query with a name' do
26
+ query = subject.query('FooBar') {
27
+ someOtherField
28
+ }
29
+
30
+ expect(query).to be_a GQLi::Query
31
+ expect(query.to_gql).to eq <<~GRAPHQL
32
+ query FooBar {
33
+ someOtherField
34
+ }
35
+ GRAPHQL
36
+ end
37
+ end
38
+
39
+ describe '::fragment' do
40
+ it 'can create a fragment' do
41
+ fragment = subject.fragment('FooBar', 'Foo') {
42
+ someFooField
43
+ }
44
+
45
+ expect(fragment).to be_a GQLi::Fragment
46
+ expect(fragment.to_gql).to eq <<~GRAPHQL
47
+ fragment FooBar on Foo {
48
+ someFooField
49
+ }
50
+ GRAPHQL
51
+ end
52
+ end
53
+ end
54
+
55
+ describe 'instance level methods' do
56
+ subject { MockGQLInterface.new }
57
+
58
+ describe '#query does the same as ::query' do
59
+ it 'can create a query without name' do
60
+ query = subject.query {
61
+ someField
62
+ }
63
+
64
+ expect(query).to be_a GQLi::Query
65
+ expect(query.to_gql).to eq <<~GRAPHQL
66
+ query {
67
+ someField
68
+ }
69
+ GRAPHQL
70
+ end
71
+
72
+ it 'can create a query with a name' do
73
+ query = subject.query('FooBar') {
74
+ someOtherField
75
+ }
76
+
77
+ expect(query).to be_a GQLi::Query
78
+ expect(query.to_gql).to eq <<~GRAPHQL
79
+ query FooBar {
80
+ someOtherField
81
+ }
82
+ GRAPHQL
83
+ end
84
+ end
85
+
86
+ describe '#fragment does the same as ::fragment' do
87
+ it 'can create a fragment' do
88
+ fragment = subject.fragment('FooBar', 'Foo') {
89
+ someFooField
90
+ }
91
+
92
+ expect(fragment).to be_a GQLi::Fragment
93
+ expect(fragment.to_gql).to eq <<~GRAPHQL
94
+ fragment FooBar on Foo {
95
+ someFooField
96
+ }
97
+ GRAPHQL
98
+ end
99
+ end
100
+ end
101
+
102
+ describe 'node DSL' do
103
+ it 'nodes can have arguments' do
104
+ query = subject.query {
105
+ someNode(arg1: 100)
106
+ otherNode(arg2: 'some_string')
107
+ moreNodes(arg3: { nestedArg: [1, 2] })
108
+ }
109
+
110
+ expect(query.to_gql).to eq <<~GRAPHQL
111
+ query {
112
+ someNode(arg1: 100)
113
+ otherNode(arg2: "some_string")
114
+ moreNodes(arg3: {nestedArg: [1, 2]})
115
+ }
116
+ GRAPHQL
117
+ end
118
+
119
+ it 'nodes can have arbitrarily nested nodes' do
120
+ query = subject.query {
121
+ aNode {
122
+ withChild {
123
+ moreChildren
124
+ andASibiling(someParameterHere: 'just for fun') {
125
+ withEvenMore
126
+ }
127
+ }
128
+ alsoASibiling
129
+ }
130
+ withoutChild
131
+ }
132
+
133
+ expect(query.to_gql).to eq <<~GRAPHQL
134
+ query {
135
+ aNode {
136
+ withChild {
137
+ moreChildren
138
+ andASibiling(someParameterHere: "just for fun") {
139
+ withEvenMore
140
+ }
141
+ }
142
+ alsoASibiling
143
+ }
144
+ withoutChild
145
+ }
146
+ GRAPHQL
147
+ end
148
+
149
+ it 'queries can have inlined fragments at any level' do
150
+ NameFragment = subject.fragment('NameFragment', 'Foo') {
151
+ name
152
+ }
153
+
154
+ AgeFragment = subject.fragment('AgeFragment', 'Foo') {
155
+ age
156
+ }
157
+
158
+ query = subject.query {
159
+ peopleCollection {
160
+ ___ NameFragment
161
+ ___ AgeFragment
162
+ }
163
+ }
164
+
165
+ expect(query.to_gql).to eq <<~GRAPHQL
166
+ query {
167
+ peopleCollection {
168
+ name
169
+ age
170
+ }
171
+ }
172
+ GRAPHQL
173
+ end
174
+
175
+ it 'queries can have type matchers' do
176
+ query = subject.query {
177
+ catCollection {
178
+ items {
179
+ name
180
+ bestFriend {
181
+ __on('Cat') {
182
+ name
183
+ }
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ expect(query.to_gql).to eq <<~GRAPHQL
190
+ query {
191
+ catCollection {
192
+ items {
193
+ name
194
+ bestFriend {
195
+ ... on Cat {
196
+ name
197
+ }
198
+ }
199
+ }
200
+ }
201
+ }
202
+ GRAPHQL
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ describe GQLi::Introspection do
4
+ let(:dsl) { GQLi::DSL }
5
+ let(:client) do
6
+ vcr('client') {
7
+ space_id = 'cfexampleapi'
8
+ token = 'b4c0n73n7fu1'
9
+ GQLi::Client.new(
10
+ "https://graphql.contentful.com/content/v1/spaces/#{space_id}",
11
+ headers: { "Authorization" => "Bearer #{token}" }
12
+ )
13
+ }
14
+ end
15
+
16
+ subject { client.schema }
17
+
18
+ describe 'introspection schema' do
19
+ it 'queries the API for the schema' do
20
+ expect(subject.types).not_to be_empty
21
+
22
+ expect(subject.types.map(&:name)).to include('Cat', 'CatCollection', 'Human')
23
+ end
24
+ end
25
+
26
+ describe 'validations' do
27
+ it 'valid query returns true' do
28
+ query = dsl.query {
29
+ catCollection(
30
+ locale:"en-US",
31
+ limit: 1,
32
+ where: {
33
+ name:"Nyan Cat",
34
+ OR: {
35
+ name:"Happy Cat"
36
+ }
37
+ }
38
+ ) {
39
+ items {
40
+ name
41
+ color
42
+ birthday
43
+ lives
44
+ bestFriend {
45
+ __on('Cat') {
46
+ name
47
+ }
48
+ }
49
+ image {
50
+ url
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ expect(subject.valid?(query)).to be_truthy
57
+ end
58
+
59
+ it 'wrong node returns false' do
60
+ query = dsl.query {
61
+ foo
62
+ }
63
+
64
+ expect(subject.valid?(query)).to be_falsey
65
+ end
66
+
67
+ it 'object node that doesnt have proper values returns false' do
68
+ query = dsl.query {
69
+ catCollection
70
+ }
71
+
72
+ expect(subject.valid?(query)).to be_falsey
73
+ end
74
+
75
+ it 'object list node that doesnt have proper values returns false' do
76
+ query = dsl.query {
77
+ catCollection {
78
+ items
79
+ }
80
+ }
81
+
82
+ expect(subject.valid?(query)).to be_falsey
83
+ end
84
+
85
+ it 'type matching on invalid type returns false' do
86
+ query = dsl.query {
87
+ catCollection {
88
+ items {
89
+ bestFriend {
90
+ __on('InvalidType') {
91
+ foo
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ expect(subject.valid?(query)).to be_falsey
99
+ end
100
+
101
+ it 'invalid arguments return false' do
102
+ query = dsl.query {
103
+ catCollection(invalidParam: 1) {
104
+ items {
105
+ name
106
+ }
107
+ }
108
+ }
109
+
110
+ expect(subject.valid?(query)).to be_falsey
111
+ end
112
+
113
+ it 'invalid argument type returns false' do
114
+ query = dsl.query {
115
+ catCollection(limit: 'foo') {
116
+ items {
117
+ name
118
+ }
119
+ }
120
+ }
121
+
122
+ expect(subject.valid?(query)).to be_falsey
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,25 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ require 'rspec'
5
+ require 'vcr'
6
+
7
+ Dir[File.join('..', File.dirname(__FILE__), 'lib', '**', '*.rb')].each { |f| require f }
8
+
9
+ require 'gqli'
10
+
11
+ RSpec.configure do |config|
12
+ config.filter_run :focus => true
13
+ config.run_all_when_everything_filtered = true
14
+ end
15
+
16
+ VCR.configure do |c|
17
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
18
+ c.ignore_localhost = true
19
+ c.hook_into :webmock
20
+ c.default_cassette_options = { record: :once }
21
+ end
22
+
23
+ def vcr(name, &block)
24
+ VCR.use_cassette(name, &block)
25
+ end
data/usage.rb ADDED
@@ -0,0 +1,100 @@
1
+ require_relative './lib/gqli'
2
+
3
+ puts GQLi::DSL.query {
4
+ __on('Foo') {
5
+ bar
6
+ }
7
+ }.to_gql
8
+
9
+
10
+ puts GQLi::DSL.query {
11
+ viewer {
12
+ login
13
+ repositories(first: 10) {
14
+ edges {
15
+ node {
16
+ nameWithOwner
17
+ watchers(first: 10) {
18
+ edges {
19
+ node {
20
+ login
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }.to_gql
29
+
30
+ FragmentFoo = GQLi::DSL.fragment('Foo', 'Bar') {
31
+ foo
32
+ bar(b: 10)
33
+ baz {
34
+ qux(c: 3)
35
+ }
36
+ }
37
+
38
+ puts FragmentFoo.to_gql
39
+
40
+ puts GQLi::DSL.query {
41
+ ___ FragmentFoo
42
+ }.to_gql
43
+
44
+ puts "-------------"
45
+
46
+ SPACE_ID = 'cfexampleapi'
47
+ ACCESS_TOKEN = 'b4c0n73n7fu1'
48
+ CONTENTFUL_GQL = GQLi::Client.new(
49
+ "https://graphql.contentful.com/content/v1/spaces/#{SPACE_ID}",
50
+ headers: { "Authorization" => "Bearer #{ACCESS_TOKEN}" }
51
+ )
52
+
53
+ CatBase = GQLi::DSL.fragment('CatBase', 'Cat') {
54
+ name
55
+ likes
56
+ lives
57
+ }
58
+
59
+ CatBestFriend = GQLi::DSL.fragment('CatBestFriend', 'Cat') {
60
+ bestFriend {
61
+ __on('Cat') {
62
+ ___ CatBase
63
+ }
64
+ }
65
+ }
66
+
67
+ CatImportantFields = GQLi::DSL.fragment('CatImportantFields', 'Cat') {
68
+ ___ CatBase
69
+ ___ CatBestFriend
70
+ }
71
+
72
+ Query = GQLi::DSL.query {
73
+ catCollection(limit: 1) {
74
+ items {
75
+ ___ CatImportantFields
76
+ image {
77
+ url
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ response = CONTENTFUL_GQL.execute(Query)
84
+
85
+ puts "Query sent:"
86
+ puts response.query.to_gql
87
+
88
+ puts
89
+ puts "Response received"
90
+ response.data.catCollection.items.each do |c|
91
+ puts "Name: #{c.nam}e"
92
+ puts "Likes: #{c.likes.join(", ")}"
93
+ puts "Lives #: #{c.lives}"
94
+ c.bestFriend.tap do |bf|
95
+ puts "Best Friend:"
96
+ puts "\tName: #{bf.name}"
97
+ puts "\tLikes: #{bf.likes.join(", ")}"
98
+ puts "\tLives #: #{bf.lives}"
99
+ end
100
+ end
@@ -0,0 +1,63 @@
1
+ require_relative './lib/gqli'
2
+
3
+ SPACE_ID = 'cfexampleapi'
4
+ ACCESS_TOKEN = 'b4c0n73n7fu1'
5
+ CONTENTFUL_GQL = GQLi::Client.new(
6
+ "https://graphql.contentful.com/content/v1/spaces/#{SPACE_ID}",
7
+ headers: { "Authorization" => "Bearer #{ACCESS_TOKEN}" }
8
+ )
9
+
10
+ CatBase = GQLi::DSL.fragment('CatBase', 'Cat') {
11
+ name
12
+ likes
13
+ lives
14
+ }
15
+
16
+ CatBestFriend = GQLi::DSL.fragment('CatBestFriend', 'Cat') {
17
+ bestFriend {
18
+ __on('Cat') {
19
+ ___ CatBase
20
+ }
21
+ }
22
+ }
23
+
24
+ CatImportantFields = GQLi::DSL.fragment('CatImportantFields', 'Cat') {
25
+ ___ CatBase
26
+ ___ CatBestFriend
27
+ }
28
+
29
+ Query = GQLi::DSL.query {
30
+ catCollection(limit: 1) {
31
+ items {
32
+ ___ CatImportantFields
33
+ image {
34
+ url
35
+ }
36
+ }
37
+ }
38
+ }
39
+
40
+ response = CONTENTFUL_GQL.execute(Query)
41
+
42
+ puts "Query sent:"
43
+ puts response.query.to_gql
44
+
45
+ puts
46
+ puts "Response received"
47
+ response.data.catCollection.items.each do |c|
48
+ puts "Name: #{c.nam}e"
49
+ puts "Likes: #{c.likes.join(", ")}"
50
+ puts "Lives #: #{c.lives}"
51
+ c.bestFriend.tap do |bf|
52
+ puts "Best Friend:"
53
+ puts "\tName: #{bf.name}"
54
+ puts "\tLikes: #{bf.likes.join(", ")}"
55
+ puts "\tLives #: #{bf.lives}"
56
+ end
57
+ end
58
+
59
+ puts "Trying to execute invalid query"
60
+
61
+ CONTENTFUL_GQL.execute!(GQLi::DSL.query {
62
+ invalidNode
63
+ })
@@ -0,0 +1,69 @@
1
+ require_relative './lib/gqli'
2
+
3
+ class ContentfulClient
4
+ extend GQLi::DSL # Makes DSL available at a class level
5
+ include GQLi::DSL # Makes DSL available at an object level
6
+
7
+ SPACE_ID = 'cfexampleapi'
8
+ ACCESS_TOKEN = 'b4c0n73n7fu1'
9
+ CONTENTFUL_GQL = GQLi::Client.new(
10
+ "https://graphql.contentful.com/content/v1/spaces/#{SPACE_ID}",
11
+ headers: { "Authorization" => "Bearer #{ACCESS_TOKEN}" }
12
+ )
13
+
14
+ CatBase = fragment('CatBase', 'Cat') {
15
+ name
16
+ likes
17
+ lives
18
+ }
19
+
20
+ CatBestFriend = fragment('CatBestFriend', 'Cat') {
21
+ bestFriend {
22
+ __on('Cat') {
23
+ ___ CatBase
24
+ }
25
+ }
26
+ }
27
+
28
+ CatImportantFields = fragment('CatImportantFields', 'Cat') {
29
+ ___ CatBase
30
+ ___ CatBestFriend
31
+ }
32
+
33
+ def cats
34
+ CONTENTFUL_GQL.execute(
35
+ query {
36
+ catCollection(limit: 10, locale: 'tlh') {
37
+ items {
38
+ ___ CatImportantFields
39
+ image {
40
+ url
41
+ }
42
+ }
43
+ }
44
+ }
45
+ )
46
+ end
47
+ end
48
+
49
+ response = ContentfulClient.new.cats
50
+
51
+ puts "Query sent:"
52
+ puts response.query.to_gql
53
+
54
+ puts
55
+ puts "Response received"
56
+ response.data.catCollection.items.each do |c|
57
+ puts "Name: #{c.name}"
58
+ puts "Likes: #{c.likes.join(", ")}"
59
+ puts "Lives #: #{c.lives}"
60
+ puts "Image: #{c.image.url}" if c.image?
61
+ c.bestFriend.tap do |bf|
62
+ next if bf.nil?
63
+ puts "Best Friend:"
64
+ puts "\tName: #{bf.name}"
65
+ puts "\tLikes: #{bf.likes.join(", ")}"
66
+ puts "\tLives #: #{bf.lives}"
67
+ end
68
+ puts
69
+ end