Skip to content
This repository was archived by the owner on Oct 6, 2024. It is now read-only.

Commit 0449d5a

Browse files
authored
Graphql (#6)
* adds graphql support * version * bundle * fix rubocop
1 parent 58d3e00 commit 0449d5a

File tree

6 files changed

+243
-5
lines changed

6 files changed

+243
-5
lines changed

README.md

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,107 @@ GET https://service.example.com/records
155155

156156
**Be aware that, if you configure ambigious endpoints accross multiple classes, the order of things is not deteministic. Ambigious endpoints accross multiple classes need to be avoided.**
157157

158+
#### GraphQL Endpoints
159+
160+
You can use DHS also to fetch records from GraphQL Endpoints:
161+
162+
```ruby
163+
# app/models/record.rb
164+
165+
class Record < DHS::Record
166+
167+
configuration items_keys: [:data, :ethereum, :address, 0, :balances]
168+
169+
endpoint 'https://graphql.bitquery.io/',
170+
graphql: {
171+
query: %Q{
172+
query ($network: EthereumNetwork!, $address: String!) {
173+
ethereum(network: $network) {
174+
address(address: {is: $address}) {
175+
balances {
176+
currency {
177+
address
178+
name
179+
symbol
180+
decimals
181+
tokenType
182+
}
183+
value
184+
}
185+
}
186+
}
187+
}
188+
},
189+
variables: [:network, :address]
190+
}
191+
192+
end
193+
```
194+
195+
```ruby
196+
# app/controllers/some_controller.rb
197+
198+
records = Record.where(network: 'ethereum', address: '0x317D875cA3B9f8d14f960486C0d1D1913be74e90')
199+
```
200+
201+
```
202+
POST https://graphql.bitquery.io/
203+
204+
BODY
205+
{
206+
"query": "
207+
query ($network: EthereumNetwork!, $address: String!) {
208+
ethereum(network: $network) {
209+
address(address: {is: $address}) {
210+
balances {
211+
currency {
212+
address
213+
name
214+
symbol
215+
decimals
216+
tokenType
217+
}
218+
value
219+
}
220+
}
221+
}
222+
}
223+
",
224+
"variables": {
225+
"network": "ethereum",
226+
"address": "0x317D875cA3B9f8d14f960486C0d1D1913be74e90"
227+
}
228+
}
229+
230+
RESPONSE
231+
"data": {
232+
"ethereum": {
233+
"address": [
234+
{
235+
balances: [
236+
{
237+
"currency": {
238+
"address": "-",
239+
"name": "Ether",
240+
"decimals": 18,
241+
"symbol": "ETH",
242+
"tokenType": ""
243+
},
244+
"value": 0.11741978
245+
}
246+
]
247+
}
248+
]
249+
}
250+
}
251+
```
252+
253+
```ruby
254+
# app/controllers/some_controller.rb
255+
256+
records.first.currency.name # Ethereum
257+
```
258+
158259
### Provider
159260

160261
Providers in DHS allow you to group shared endpoint options under a common provider.
@@ -2851,4 +2952,3 @@ expect(
28512952
## License
28522953

28532954
[GNU General Public License Version 3.](https://www.gnu.org/licenses/gpl-3.0.en.html)
2854-

dhs.gemspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ Gem::Specification.new do |s|
2424

2525
s.add_dependency 'activemodel'
2626
s.add_dependency 'activesupport', '>= 6'
27-
s.add_dependency 'dhc'
27+
s.add_dependency 'dhc', '>= 2'
2828
s.add_dependency 'local_uri'
2929

3030
s.add_development_dependency 'capybara'
3131
s.add_development_dependency 'json', '>= 1.8.2'
3232
s.add_development_dependency 'pry'
3333
s.add_development_dependency 'pry-byebug'
34-
s.add_development_dependency 'rails', '>= 6'
34+
s.add_development_dependency 'rails', '>= 6', '< 7'
3535
s.add_development_dependency 'rollbar', '<= 2.24.0'
3636
s.add_development_dependency 'rspec-rails', '>= 3.7.0'
3737
s.add_development_dependency 'rubocop'

lib/dhs/concerns/record/request.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,13 +469,27 @@ def process_options(options, endpoint)
469469
options = (provider_options || {})
470470
.deep_merge(endpoint.options || {})
471471
.deep_merge(options)
472+
set_graphql_options!(options) if options.dig(:graphql).present?
472473
options[:url] = compute_url!(options[:params]) unless options.key?(:url)
473474
merge_explicit_params!(options[:params])
474475
options.delete(:params) if options[:params]&.empty?
475476
inject_interceptors!(options)
476477
options
477478
end
478479

480+
def set_graphql_options!(options)
481+
options[:method] = :post
482+
variables = {}
483+
options.dig(:graphql, :variables).each do |key|
484+
variables[key] = options[:params][key]
485+
options[:params].delete(key)
486+
end
487+
options[:body] = {
488+
query: options.dig(:graphql, :query).squish,
489+
variables: variables.to_json
490+
}
491+
end
492+
479493
def inject_interceptors!(options)
480494
if DHS.config.request_cycle_cache_enabled
481495
inject_interceptor!(

lib/dhs/concerns/record/update.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Update
88
extend ActiveSupport::Concern
99

1010
included do
11-
class <<self
11+
class << self
1212
alias_method :update, :create
1313
alias_method :update!, :create!
1414
end

lib/dhs/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module DHS
4-
VERSION = '1.2.0'
4+
VERSION = '1.3.0'
55
end

spec/graphql/main_spec.rb

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
describe 'main graphql support' do
6+
let(:network) { 'ethereum' }
7+
let(:address) { '0x317D875cA3B9f8d14f960486C0d1D1913be74e90' }
8+
9+
let!(:stubbed_request) do
10+
stub_request(:post, 'https://graphql.bitquery.io/')
11+
.with(
12+
body: {
13+
query: %{
14+
query ($network: EthereumNetwork!, $address: String!) {
15+
ethereum(network: $network) {
16+
address(address: {is: $address}) {
17+
balances {
18+
currency {
19+
address
20+
name
21+
symbol
22+
decimals
23+
tokenType
24+
}
25+
value
26+
}
27+
}
28+
}
29+
}
30+
}.squish,
31+
variables: {
32+
"network": network,
33+
"address": address
34+
}.to_json
35+
}.to_json
36+
).to_return(body: {
37+
"data": {
38+
"ethereum": {
39+
"address": [
40+
{
41+
balances: [
42+
{
43+
"currency": {
44+
"address": '-',
45+
"name": 'Ether',
46+
"decimals": 18,
47+
"symbol": 'ETH',
48+
"tokenType": ''
49+
},
50+
"value": 0.11741978
51+
},
52+
{
53+
"currency": {
54+
"address": '0xb63b606ac810a52cca15e44bb630fd42d8d1d83d',
55+
"name": 'Monaco',
56+
"decimals": 8,
57+
"symbol": 'MCO',
58+
"tokenType": 'ERC20'
59+
},
60+
"value": 0
61+
},
62+
{
63+
"currency": {
64+
"address": '0x06012c8cf97bead5deae237070f9587f8e7a266d',
65+
"name": 'CryptoKitties',
66+
"decimals": 0,
67+
"symbol": 'CK',
68+
"tokenType": 'ERC721'
69+
},
70+
"value": 90
71+
},
72+
{
73+
"currency": {
74+
"address": '0xdac17f958d2ee523a2206206994597c13d831ec7',
75+
"name": 'Tether USD',
76+
"decimals": 6,
77+
"symbol": 'USDT',
78+
"tokenType": 'ERC20'
79+
},
80+
"value": 10
81+
}
82+
]
83+
}
84+
]
85+
}
86+
}
87+
}.to_json)
88+
end
89+
90+
before do
91+
class Record < DHS::Record
92+
93+
configuration items_key: [:data, :ethereum, :address, 0, :balances]
94+
95+
endpoint 'https://graphql.bitquery.io/',
96+
graphql: {
97+
query: %{
98+
query ($network: EthereumNetwork!, $address: String!) {
99+
ethereum(network: $network) {
100+
address(address: {is: $address}) {
101+
balances {
102+
currency {
103+
address
104+
name
105+
symbol
106+
decimals
107+
tokenType
108+
}
109+
value
110+
}
111+
}
112+
}
113+
}
114+
},
115+
variables: %i[network address]
116+
}
117+
end
118+
end
119+
120+
it 'fetches data from graphql and converts it into DHS Record structure' do
121+
records = Record.where(network: 'ethereum', address: '0x317D875cA3B9f8d14f960486C0d1D1913be74e90').fetch
122+
expect(records.first.currency.name).to eq 'Ether'
123+
end
124+
end

0 commit comments

Comments
 (0)