active_graphql 0.2.1
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.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.hound.yml +4 -0
- data/.rspec +3 -0
- data/.rubocop.yml +48 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +25 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +134 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +6 -0
- data/active_graphql.gemspec +49 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docs/.nojekyll +0 -0
- data/docs/README.md +95 -0
- data/docs/_sidebar.md +4 -0
- data/docs/client.md +69 -0
- data/docs/index.html +70 -0
- data/docs/model.md +464 -0
- data/lib/active_graphql.rb +10 -0
- data/lib/active_graphql/client.rb +38 -0
- data/lib/active_graphql/client/actions.rb +15 -0
- data/lib/active_graphql/client/actions/action.rb +116 -0
- data/lib/active_graphql/client/actions/action/format_inputs.rb +80 -0
- data/lib/active_graphql/client/actions/action/format_outputs.rb +40 -0
- data/lib/active_graphql/client/actions/mutation_action.rb +29 -0
- data/lib/active_graphql/client/actions/query_action.rb +23 -0
- data/lib/active_graphql/client/adapters.rb +10 -0
- data/lib/active_graphql/client/adapters/graphlient_adapter.rb +32 -0
- data/lib/active_graphql/client/response.rb +47 -0
- data/lib/active_graphql/errors.rb +11 -0
- data/lib/active_graphql/model.rb +174 -0
- data/lib/active_graphql/model/action_formatter.rb +96 -0
- data/lib/active_graphql/model/build_or_relation.rb +66 -0
- data/lib/active_graphql/model/configuration.rb +83 -0
- data/lib/active_graphql/model/find_in_batches.rb +54 -0
- data/lib/active_graphql/model/relation_proxy.rb +321 -0
- data/lib/active_graphql/version.rb +5 -0
- metadata +254 -0
data/bin/setup
ADDED
data/docs/.nojekyll
ADDED
File without changes
|
data/docs/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# ActiveGraphql
|
2
|
+
[](https://travis-ci.com/samesystem/active_graphql)
|
3
|
+
[](https://codecov.io/gh/samesystem/active_graphql)
|
4
|
+
[](https://samesystem.github.io/active_graphql)
|
5
|
+
|
6
|
+
GraphQL client which allows to interact with graphql using ActiveRecord-like API
|
7
|
+
|
8
|
+
Detailed documentation can be found at https://samesystem.github.io/active_graphql
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'active_graphql'
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install active_graphql
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
You can fetch data from GraphQL in two different ways: using `ActiveGraphql::Client` or using `ActiveGraphql::Model`
|
29
|
+
|
30
|
+
### [ActiveGraphql::Client](client.md)
|
31
|
+
|
32
|
+
`ActiveGraphql::Client` is a client which allows you to make requests using ruby-friendly code:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
client = ActiveGraphql::Client.new(url: 'https://example.com/graphql')
|
36
|
+
|
37
|
+
client.query(:findUser).inputs(id: 1).outputs(:name, :avatar_url).result
|
38
|
+
# or same request with AR-style syntax
|
39
|
+
client.query(:findUser).select(:name, :avatar_url).where(id: 1).result
|
40
|
+
```
|
41
|
+
|
42
|
+
Find out more how to use Client in [Client documentation](client.md)
|
43
|
+
|
44
|
+
### [ActiveGraphql::Model](model.md)
|
45
|
+
|
46
|
+
If you have well structured GraphQL endpoint, which has CRUD actions for each entity then you can interact with GraphQL endpoints using `ActiveGraphql::Model`.
|
47
|
+
It allows you to have separate class for separate GraphQL entity, Here is an example:
|
48
|
+
|
49
|
+
Suppose you have following endpoints in graphql:
|
50
|
+
|
51
|
+
* `users(filter: UsersFilter!`) - index action with filtering possibilities
|
52
|
+
* `user(id: ID!)` - show action
|
53
|
+
|
54
|
+
In this case you can create ruby class like this:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
class User
|
58
|
+
include ActiveGraphql::Model
|
59
|
+
|
60
|
+
active_graphql do |c|
|
61
|
+
c.url('http://example.com/graphql')
|
62
|
+
c.attributes :id, :first_name, :last_name, :created_at
|
63
|
+
end
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
with this small setup you are able to do following:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
User.where(first_name: 'John').to_a # list all users with name "John"
|
71
|
+
User.limit(5).to_a # list first 5 users
|
72
|
+
User.find(1) # find user with ID: 1
|
73
|
+
User.first(2) # find first 2 users
|
74
|
+
User.last(3) # find last 3 users
|
75
|
+
```
|
76
|
+
|
77
|
+
Find out more how to use Model in [Model documentation](client.md)
|
78
|
+
|
79
|
+
## Development
|
80
|
+
|
81
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
82
|
+
|
83
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/samesystem/active_graphql. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
88
|
+
|
89
|
+
## License
|
90
|
+
|
91
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
92
|
+
|
93
|
+
## Code of Conduct
|
94
|
+
|
95
|
+
Everyone interacting in the ActiveGraphql project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/samesystem/active_graphql/blob/master/CODE_OF_CONDUCT.md).
|
data/docs/_sidebar.md
ADDED
data/docs/client.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Client
|
2
|
+
|
3
|
+
## Initialization
|
4
|
+
|
5
|
+
to initialize graphql client, simply create new client instance with url:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
client = ActiveGraphql::Client.new(url: 'http://example.com/graphql')
|
9
|
+
```
|
10
|
+
|
11
|
+
you can also provide extra options which will be accepted by addapter, like this:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
client = ActiveGraphql::Client.new(url: 'http://example.com/graphql', headers: {}, schema_path: '...')
|
15
|
+
```
|
16
|
+
|
17
|
+
## query and mutation actions
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
mutation = client.mutation(:create_user)
|
21
|
+
query = client.query(:find_user)
|
22
|
+
```
|
23
|
+
|
24
|
+
### where (alias: input)
|
25
|
+
|
26
|
+
In order to filter values you can query with `where` method:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
query = query.where(name: 'John', date: { from: '2000-01-01' })
|
30
|
+
```
|
31
|
+
|
32
|
+
this will produce following GraphQL:
|
33
|
+
|
34
|
+
```graphql
|
35
|
+
query {
|
36
|
+
find_user(name: "John", date: { from: "2000-01-01" }) {
|
37
|
+
...
|
38
|
+
}
|
39
|
+
}
|
40
|
+
```
|
41
|
+
|
42
|
+
### select (alias: output)
|
43
|
+
|
44
|
+
In order to select which attributes you want to receive from query then you need to use `select` method:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
query = query.select(:name, date: [:year])
|
48
|
+
```
|
49
|
+
|
50
|
+
this will produce following GraphQL:
|
51
|
+
|
52
|
+
```graphql
|
53
|
+
query {
|
54
|
+
find_user {
|
55
|
+
name
|
56
|
+
date { year }
|
57
|
+
}
|
58
|
+
}
|
59
|
+
```
|
60
|
+
|
61
|
+
### meta
|
62
|
+
|
63
|
+
You can assign meta attributes in order to use them later
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
query = query.meta(custom: true)
|
67
|
+
query = query.meta(also_custom: 'yes')
|
68
|
+
query.meta_attributes # => { :custom => true, :also_custom => "yes" }
|
69
|
+
```
|
data/docs/index.html
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<title>Document</title>
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
7
|
+
<meta name="description" content="Description">
|
8
|
+
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
9
|
+
<link rel="stylesheet" href="https://unpkg.com/docsify/lib/themes/vue.css">
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<div id="app"></div>
|
13
|
+
<script>
|
14
|
+
function parseQueryString (queryString) {
|
15
|
+
var params = {};
|
16
|
+
var temp;
|
17
|
+
// Split into key/value pairs
|
18
|
+
queries = queryString.split("&");
|
19
|
+
// Convert the array of strings into an object
|
20
|
+
for (var i = 0, l = queries.length; i < l; i++ ) {
|
21
|
+
temp = queries[i].split('=');
|
22
|
+
params[temp[0]] = temp[1];
|
23
|
+
}
|
24
|
+
return params;
|
25
|
+
};
|
26
|
+
|
27
|
+
function getJsonFromUrl() {
|
28
|
+
return parseQueryString(location.search.substr(1));
|
29
|
+
}
|
30
|
+
|
31
|
+
window.$docsify = {
|
32
|
+
auto2top: true,
|
33
|
+
name: 'ActiveGraphql',
|
34
|
+
repo: 'https://github.com/samesystem/active_graphql',
|
35
|
+
subMaxLevel: 3,
|
36
|
+
loadSidebar: true,
|
37
|
+
formatUpdated: '{MM}/{DD} {HH}:{mm}',
|
38
|
+
branchBasePath: 'https://raw.githubusercontent.com/samesystem/active_graphql/',
|
39
|
+
plugins: [
|
40
|
+
function (hook, vm) { // reasign any config value by param attribute
|
41
|
+
Object.assign(window.$docsify, getJsonFromUrl());
|
42
|
+
},
|
43
|
+
|
44
|
+
function (hook, vm) { // allow to change branch
|
45
|
+
if (!window.$docsify.branchBasePath || !window.$docsify.branch) {
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
|
49
|
+
var branch = window.$docsify.branch;
|
50
|
+
var basePath = window.$docsify.branchBasePath + branch;
|
51
|
+
window.$docsify.basePath = basePath;
|
52
|
+
},
|
53
|
+
|
54
|
+
function (hook, vm) { // add edit page link
|
55
|
+
hook.beforeEach(function (html) {
|
56
|
+
var branch = window.$docsify.branch || 'master'
|
57
|
+
var url = 'https://github.com/samesystem/active_graphql/edit/' + branch + '/docs/' + vm.route.file
|
58
|
+
var editHtml = '[:memo: Edit Document](' + url + ')\n'
|
59
|
+
return html
|
60
|
+
+ '\n\n----\n\n'
|
61
|
+
+ editHtml
|
62
|
+
})
|
63
|
+
}
|
64
|
+
]
|
65
|
+
}
|
66
|
+
</script>
|
67
|
+
<script src="https://unpkg.com/docsify/lib/docsify.js"></script>
|
68
|
+
<script src="https://unpkg.com/docsify/lib/plugins/search.min.js"></script>
|
69
|
+
</body>
|
70
|
+
</html>
|
data/docs/model.md
ADDED
@@ -0,0 +1,464 @@
|
|
1
|
+
# Model
|
2
|
+
|
3
|
+
## Setup
|
4
|
+
|
5
|
+
To create graphql model, you need to include `ActiveGraphql::Model` module in your ruby class like this:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
class User
|
9
|
+
include ActiveGraphql::Model
|
10
|
+
|
11
|
+
active_graphql do |c|
|
12
|
+
c.url 'http://localhost:3000'
|
13
|
+
c.attributes :id, :first_name, :last_name
|
14
|
+
end
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
Attributes also can be nested, like this:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
class User
|
22
|
+
include ActiveGraphql::Model
|
23
|
+
|
24
|
+
active_graphql do |c|
|
25
|
+
c.attributes location: [:city, :country, :street]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
User.find(3).location # { city: 'London', country: ... }
|
30
|
+
```
|
31
|
+
|
32
|
+
### active_graphql.url
|
33
|
+
|
34
|
+
Sets url where all GraphQL queries should go
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class User
|
38
|
+
include ActiveGraphql::Model
|
39
|
+
|
40
|
+
active_graphql do |c|
|
41
|
+
c.url 'http://localhost:3000'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
### active_graphql.attributes
|
47
|
+
|
48
|
+
Sets attributes which can be fetched from graphql
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
class User
|
52
|
+
include ActiveGraphql::Model
|
53
|
+
|
54
|
+
active_graphql do |c|
|
55
|
+
c.attributes :id, :first_name, :last_name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
User.find(3).first_name # => some name returned from graphql
|
60
|
+
```
|
61
|
+
|
62
|
+
### active_graphql.attribute
|
63
|
+
|
64
|
+
Sets attribute which can be fetched from graphql
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
class User
|
68
|
+
include ActiveGraphql::Model
|
69
|
+
|
70
|
+
active_graphql do |c|
|
71
|
+
c.attribute :name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
User.find(3).name # => "John"
|
76
|
+
```
|
77
|
+
|
78
|
+
#### nested attributes
|
79
|
+
|
80
|
+
You can have nested attributes. Nested values will be returned as hash:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class User
|
84
|
+
include ActiveGraphql::Model
|
85
|
+
|
86
|
+
active_graphql do |c|
|
87
|
+
c.attribute :id
|
88
|
+
c.attribute :location, [:lat, :long]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
User.find(3).location #=> { lat: 25.0, long: 26.0 }
|
93
|
+
```
|
94
|
+
|
95
|
+
#### decorated attributes
|
96
|
+
|
97
|
+
You can use decorator methods in order to modify model attribute values. It's very in combination with nested values
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class User
|
101
|
+
include ActiveGraphql::Model
|
102
|
+
|
103
|
+
active_graphql do |c|
|
104
|
+
c.attribute :name, decorate_with: :make_fancy_name
|
105
|
+
end
|
106
|
+
|
107
|
+
def make_fancy_name(original_name)
|
108
|
+
"Mr. #{original_name}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
User.find(3).name #=> "Mr. John"
|
113
|
+
```
|
114
|
+
|
115
|
+
### active_graphql.resource_name
|
116
|
+
|
117
|
+
Sets attributes which can be fetched from graphql
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
class User
|
121
|
+
include ActiveGraphql::Model
|
122
|
+
|
123
|
+
active_graphql do |c|
|
124
|
+
c.resource_name :admin_user
|
125
|
+
c.attributes :id
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
User.where(name: 'John').to_graphql # => "query { adminUsers(name: "John") { id } }"
|
130
|
+
```
|
131
|
+
|
132
|
+
### active_graphql.primary_key
|
133
|
+
|
134
|
+
By default primary key is `id`, but you can change it like this:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
class User
|
138
|
+
include ActiveGraphql::Model
|
139
|
+
|
140
|
+
active_graphql do |c|
|
141
|
+
c.primary_key :email
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
User.find('john@example.com') # will execute in GraphQL: 'query { user(email: "john@example.com") }'
|
146
|
+
```
|
147
|
+
|
148
|
+
## Methods
|
149
|
+
|
150
|
+
### find
|
151
|
+
|
152
|
+
Use `find` method in order to find record:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
user = User.find(5)
|
156
|
+
```
|
157
|
+
|
158
|
+
### update
|
159
|
+
|
160
|
+
Use `update` to update record on graphql side:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
User.find(5).update(first_name: 'John') # => true or false
|
164
|
+
```
|
165
|
+
|
166
|
+
### update!
|
167
|
+
|
168
|
+
Use `update!` to update record on graphql side:
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
User.find(5).update!(first_name: 'John') # => true or exception
|
172
|
+
```
|
173
|
+
|
174
|
+
### destroy
|
175
|
+
|
176
|
+
Use `destroy` in order to delete record on graphql side:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
User.find(5).destroy # => true or false
|
180
|
+
```
|
181
|
+
|
182
|
+
### create
|
183
|
+
|
184
|
+
to create model on graphql side simply use `create` method, like this:
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
user = User.create(first_name: 'John', last_name: 'Doe')
|
188
|
+
```
|
189
|
+
|
190
|
+
### create!
|
191
|
+
|
192
|
+
as in ActiveRecord, there is `create!` method which will raise error when create fails:
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
user = User.create!(first_name: 'John', last_name: 'Doe')
|
196
|
+
```
|
197
|
+
|
198
|
+
### where
|
199
|
+
|
200
|
+
Use `where` method in order to find multiple record:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
users = User.where(name: 'John')
|
204
|
+
```
|
205
|
+
|
206
|
+
### merge
|
207
|
+
|
208
|
+
Use `merge` method in order to merge multiple queries:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
# same as User.where(name: 'John', surname: 'Doe') :
|
212
|
+
users = User.where(name: 'John').merge(User.where(surname: 'Doe'))
|
213
|
+
```
|
214
|
+
|
215
|
+
### or
|
216
|
+
|
217
|
+
Use `or` method in order to query using "or" predicate:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
# same as User.where(or: { name: 'John', surname: 'Doe' }) :
|
221
|
+
users = User.where(name: 'John').or(User.where(surname: 'Doe'))
|
222
|
+
```
|
223
|
+
|
224
|
+
Keep in mind that your endpoint must support filtering by "or" key like this:
|
225
|
+
|
226
|
+
```graphql
|
227
|
+
query {
|
228
|
+
users(filter: { or: { name: 'John', surname: 'Doe' } }) {
|
229
|
+
...
|
230
|
+
}
|
231
|
+
}
|
232
|
+
```
|
233
|
+
|
234
|
+
### order
|
235
|
+
|
236
|
+
Use `order` when you need to sort results:
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
users.order(created_at: :desc)
|
240
|
+
```
|
241
|
+
|
242
|
+
### find_each
|
243
|
+
|
244
|
+
In order to iterate through multiple pages, you need to use `find_each` method
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
User.all.find_each do |user|
|
248
|
+
do_something(user)
|
249
|
+
end
|
250
|
+
```
|
251
|
+
|
252
|
+
### paginate
|
253
|
+
|
254
|
+
you can also paginate records:
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
User.paginate(page: 1, per_page: 3)
|
258
|
+
```
|
259
|
+
|
260
|
+
### page
|
261
|
+
|
262
|
+
you can also paginate records:
|
263
|
+
|
264
|
+
```ruby
|
265
|
+
User.page(1)
|
266
|
+
```
|
267
|
+
|
268
|
+
### Selecting certain fields
|
269
|
+
|
270
|
+
You can select only attributes which you want to be selected from model, like this:
|
271
|
+
|
272
|
+
```ruby
|
273
|
+
class User
|
274
|
+
include ActiveGraphql::Model
|
275
|
+
|
276
|
+
active_graphql do |c|
|
277
|
+
c.url 'http://example.com/graphql'
|
278
|
+
c.attributes :id, :first_name, location: %i[street city], name: :full_name
|
279
|
+
end
|
280
|
+
|
281
|
+
def self.main_data
|
282
|
+
select(:first_name, location: :city, name: :full_name)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
User.main_data
|
287
|
+
```
|
288
|
+
|
289
|
+
This will produce GraphQL:
|
290
|
+
```graphql
|
291
|
+
query {
|
292
|
+
users {
|
293
|
+
firstName
|
294
|
+
location {
|
295
|
+
city
|
296
|
+
}
|
297
|
+
name {
|
298
|
+
fullName
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
```
|
303
|
+
|
304
|
+
### defining custom queries
|
305
|
+
|
306
|
+
You can define your custom queries by adding class method, like this:
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
class User
|
310
|
+
include ActiveGraphql::Model
|
311
|
+
|
312
|
+
active_graphql do |c|
|
313
|
+
c.attributes :id
|
314
|
+
end
|
315
|
+
|
316
|
+
def self.with_custom
|
317
|
+
where(custom: true)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
User.where(id: 1).with_custom
|
322
|
+
```
|
323
|
+
|
324
|
+
this will produce GraphQL:
|
325
|
+
|
326
|
+
```graphql
|
327
|
+
query {
|
328
|
+
users(filter: { id: 1, custom: true } ) {
|
329
|
+
id
|
330
|
+
}
|
331
|
+
}
|
332
|
+
```
|
333
|
+
|
334
|
+
### mutate
|
335
|
+
|
336
|
+
You can define your custom mutations by adding instance method, like this:
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
class User
|
340
|
+
include ActiveGraphql::Model
|
341
|
+
|
342
|
+
active_graphql do |c|
|
343
|
+
c.attributes :id, :first_name, :last_name
|
344
|
+
end
|
345
|
+
|
346
|
+
def update_name(first_name, last_name)
|
347
|
+
mutate(:update_name, input: { first_name: 'Fancy', last_name: 'Pants' })
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
User.last.update_name('Fancy', 'Pants')
|
352
|
+
```
|
353
|
+
|
354
|
+
This will produce GraphQL:
|
355
|
+
```graphql
|
356
|
+
mutation {
|
357
|
+
updateName(id: 99, input: { firstName: 'Fancy', lastName: 'Pants' }) {
|
358
|
+
id
|
359
|
+
firstName
|
360
|
+
lastName
|
361
|
+
...
|
362
|
+
}
|
363
|
+
}
|
364
|
+
```
|
365
|
+
|
366
|
+
## Requirements for GraphQL server side
|
367
|
+
|
368
|
+
In order to make active_graphql work, server must met some conditions.
|
369
|
+
|
370
|
+
### Naming requirements
|
371
|
+
|
372
|
+
Resource, attribute and field names must be in camelcase
|
373
|
+
|
374
|
+
#### Resource name requirements for CRUD actions
|
375
|
+
|
376
|
+
Let's say we have `BlogPost` resource, so CRUD actions should be named like this:
|
377
|
+
- `blogPost(id: ID!)` (aka, `show` action)
|
378
|
+
- `blogPosts(filter: FilterInput)` (aka, `index` action)
|
379
|
+
- `createBlogPost(input: SomeCreateInput!)` (aka, `create` action)
|
380
|
+
- `updateBlogPost(id: ID!, input: SomeUpdateInput!)` (aka, `update` action)
|
381
|
+
- `destroyBlogPost(id: ID!)` (aka, `destroy` action)
|
382
|
+
|
383
|
+
### Requirements for Model#find methods
|
384
|
+
|
385
|
+
In order to make Model#find work, server must have resource in singular form with single `id: ID!` argument.
|
386
|
+
|
387
|
+
Example: `user(id: ID!)`
|
388
|
+
|
389
|
+
### Requirements for Model#all, Model#find_each methods
|
390
|
+
|
391
|
+
In order to make Model#all and Model#find_each work, server must have resource in plural form and also response should be paginated.
|
392
|
+
|
393
|
+
Example:
|
394
|
+
```
|
395
|
+
users(first: Integer, last: Integer, before: String, after: String) {
|
396
|
+
edges {
|
397
|
+
node {
|
398
|
+
...
|
399
|
+
}
|
400
|
+
}
|
401
|
+
}
|
402
|
+
```
|
403
|
+
|
404
|
+
### Requirements for Model#where, Model#find_by methods
|
405
|
+
|
406
|
+
In order to make Model#where and Model#find_by work, server must have resource in plural form with `filter: SomeFilterInput` argument. Also resource must match requirements for Model#all too (see previous section)
|
407
|
+
|
408
|
+
Example:
|
409
|
+
```
|
410
|
+
type UsersFilterInput {
|
411
|
+
firstName: String!
|
412
|
+
lastName: String!
|
413
|
+
}
|
414
|
+
|
415
|
+
users(filter: UserFilterInput) {
|
416
|
+
edges {
|
417
|
+
node {
|
418
|
+
...
|
419
|
+
}
|
420
|
+
}
|
421
|
+
}
|
422
|
+
```
|
423
|
+
|
424
|
+
### Requirements for Model#or method
|
425
|
+
|
426
|
+
In order to make Model#or resouce must match requirements for `Model#where` method. Also `filter` input must have `or` argument
|
427
|
+
|
428
|
+
Example:
|
429
|
+
```
|
430
|
+
type UsersFilterInput {
|
431
|
+
or: UsersOrFilterInput
|
432
|
+
groupId: [ID!],
|
433
|
+
name: String!
|
434
|
+
}
|
435
|
+
|
436
|
+
type UsersOrFilterInput {
|
437
|
+
groupId: [ID!],
|
438
|
+
name: String!
|
439
|
+
}
|
440
|
+
|
441
|
+
users(filter: UserFilterInput) {
|
442
|
+
edges {
|
443
|
+
node {
|
444
|
+
...
|
445
|
+
}
|
446
|
+
}
|
447
|
+
}
|
448
|
+
```
|
449
|
+
|
450
|
+
### Requirements for Model#count
|
451
|
+
|
452
|
+
In order to make Model#where and Model#find_by work, server must have resource in plural form. This resource must have `total:Integer` **output** field:
|
453
|
+
|
454
|
+
Example:
|
455
|
+
```
|
456
|
+
users() {
|
457
|
+
total
|
458
|
+
edges {
|
459
|
+
node {
|
460
|
+
...
|
461
|
+
}
|
462
|
+
}
|
463
|
+
}
|
464
|
+
```
|