search_object_graphql 0.3.2 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +5 -21
- data/example/app/graphql/resolvers/base_resolver.rb +6 -0
- data/example/app/graphql/resolvers/base_search_resolver.rb +1 -1
- data/example/app/graphql/resolvers/category_search.rb +1 -1
- data/example/app/graphql/resolvers/post_search.rb +1 -1
- data/example/app/graphql/types/category_type.rb +1 -1
- data/example/app/graphql/types/query_type.rb +1 -1
- data/lib/search_object/plugin/graphql.rb +14 -98
- data/lib/search_object/plugin/graphql/version.rb +1 -1
- data/spec/search_object/plugin/graphql_spec.rb +12 -109
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49fd6817f69aa33a15ce7cc2e768bd239020c3f7f6b6e385e1f12d3c9d5c30ff
|
4
|
+
data.tar.gz: c6c4a8d82f1d5afa85519a1e8aee726b321495b2305e63fa0d5e986db75066fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a71588bac7cc2fba645d1e4007bfeed111749c0016d4a2de7e832990ff33f37e1656c08a47fd3a52f18664e594bbefee3939d1412aa3fc5d679dd9c3d875d533
|
7
|
+
data.tar.gz: 4c9bfd49332eafbd37b10be48bc58c65bfffa0546dc7c394a7b77e3e146769ee77083f39bbd40f101302ad7ffb967d8b7e0054b6512c35febdcedc0e00c94855
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Version 1.0.0 (unreleased)
|
4
|
+
|
5
|
+
* __[break]__ Removed support for defining types via `type` method (@rstankov)
|
6
|
+
* __[break]__ Require `GraphQL::Schema::Resolver` inheritance (@rstankov)
|
7
|
+
* __[break]__ Removed support for legacy `GraphQL::Function` (@rstankov)
|
8
|
+
* __[break]__ `type` creates type based on `GraphQL::Schema::Object`, not the deprecated `GraphQL::ObjectType.define` (@rstankov)
|
9
|
+
|
3
10
|
## Version 0.3.2
|
4
11
|
|
5
12
|
* __[feature]__ Added `camelize` argument to `option`, *`true` by default* (@glenbray)
|
data/README.md
CHANGED
@@ -57,7 +57,7 @@ require 'search_object/plugin/graphql'
|
|
57
57
|
Just include the ```SearchObject.module``` and define your search options and their types:
|
58
58
|
|
59
59
|
```ruby
|
60
|
-
class PostResolver
|
60
|
+
class PostResolver < GraphQL::Schema::Resolver
|
61
61
|
include SearchObject.module(:graphql)
|
62
62
|
|
63
63
|
type [PostType], null: false
|
@@ -94,7 +94,7 @@ You can find example of most important features and plugins - [here](https://git
|
|
94
94
|
Search object itself can be documented, as well as its options:
|
95
95
|
|
96
96
|
```ruby
|
97
|
-
class PostResolver
|
97
|
+
class PostResolver < GraphQL::Schema::Resolver
|
98
98
|
include SearchObject.module(:graphql)
|
99
99
|
|
100
100
|
description 'Lists all posts'
|
@@ -107,7 +107,7 @@ end
|
|
107
107
|
### Default Values
|
108
108
|
|
109
109
|
```ruby
|
110
|
-
class PostResolver
|
110
|
+
class PostResolver < GraphQL::Schema::Resolver
|
111
111
|
include SearchObject.module(:graphql)
|
112
112
|
|
113
113
|
scope { Post.all }
|
@@ -121,7 +121,7 @@ end
|
|
121
121
|
Sometimes you want to scope posts based on parent object, it is accessible as `object` property:
|
122
122
|
|
123
123
|
```ruby
|
124
|
-
class PostResolver
|
124
|
+
class PostResolver < GraphQL::Schema::Resolver
|
125
125
|
include SearchObject.module(:graphql)
|
126
126
|
|
127
127
|
# lists only posts from certain category
|
@@ -168,7 +168,7 @@ end
|
|
168
168
|
Search objects can be used as [Relay Connections](https://graphql-ruby.org/relay/connections.html):
|
169
169
|
|
170
170
|
```ruby
|
171
|
-
class PostResolver
|
171
|
+
class PostResolver < GraphQL::Schema::Resolver
|
172
172
|
include SearchObject.module(:graphql)
|
173
173
|
|
174
174
|
type PostType.connection_type, null: false
|
@@ -181,22 +181,6 @@ end
|
|
181
181
|
field :posts, resolver: PostResolver
|
182
182
|
```
|
183
183
|
|
184
|
-
### Legacy Function Support
|
185
|
-
|
186
|
-
```ruby
|
187
|
-
class PostResolver
|
188
|
-
include SearchObject.module(:graphql)
|
189
|
-
|
190
|
-
type [PostType], null: false
|
191
|
-
|
192
|
-
# ...
|
193
|
-
end
|
194
|
-
```
|
195
|
-
|
196
|
-
```ruby
|
197
|
-
field :posts, function: PostResolver
|
198
|
-
```
|
199
|
-
|
200
184
|
## Contributing
|
201
185
|
|
202
186
|
1. Fork it
|
@@ -4,8 +4,9 @@ module SearchObject
|
|
4
4
|
module Plugin
|
5
5
|
module Graphql
|
6
6
|
def self.included(base)
|
7
|
+
raise NotIncludedInResolverError, base unless base.ancestors.include? GraphQL::Schema::Resolver
|
8
|
+
|
7
9
|
base.include SearchObject::Plugin::Enum
|
8
|
-
base.include ::GraphQL::Schema::Member::GraphQLTypeNames
|
9
10
|
base.extend ClassMethods
|
10
11
|
end
|
11
12
|
|
@@ -26,114 +27,29 @@ module SearchObject
|
|
26
27
|
end
|
27
28
|
|
28
29
|
module ClassMethods
|
29
|
-
KEYS = %i[type default description required camelize].freeze
|
30
30
|
def option(name, options = {}, &block)
|
31
|
-
config[:arguments] ||= {}
|
32
|
-
config[:arguments][name.to_s] = KEYS.inject({}) do |acc, key|
|
33
|
-
acc[key] = options[key] if options.key?(key)
|
34
|
-
acc
|
35
|
-
end
|
36
|
-
|
37
31
|
type = options.fetch(:type) { raise MissingTypeDefinitionError, name }
|
38
32
|
options[:enum] = type.values.map { |value, enum_value| enum_value.value || value } if type.respond_to?(:values)
|
39
33
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
config[:null] = null
|
48
|
-
end
|
49
|
-
|
50
|
-
def complexity(value = :default)
|
51
|
-
return config[:complexity] || 1 if value == :default
|
52
|
-
|
53
|
-
config[:complexity] = value
|
54
|
-
end
|
55
|
-
|
56
|
-
def description(value = :default)
|
57
|
-
return config[:description] if value == :default
|
58
|
-
|
59
|
-
config[:description] = value
|
60
|
-
end
|
61
|
-
|
62
|
-
def deprecation_reason(value = :default)
|
63
|
-
return config[:deprecation_reason] if value == :default
|
34
|
+
argument(
|
35
|
+
name.to_s,
|
36
|
+
options[:type],
|
37
|
+
required: options[:required] || false,
|
38
|
+
description: options[:description],
|
39
|
+
camelize: options[:camelize]
|
40
|
+
)
|
64
41
|
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
# NOTE(rstankov): GraphQL::Function interface (deprecated in favour of GraphQL::Schema::Resolver)
|
69
|
-
# Documentation - http://graphql-ruby.org/guides
|
70
|
-
def call(object, args, context)
|
71
|
-
new(filters: args.to_h, object: object, context: context).results
|
42
|
+
super(name, options, &block)
|
72
43
|
end
|
73
44
|
|
74
|
-
# NOTE(rstankov): Used for GraphQL::Function
|
75
45
|
def types
|
76
46
|
GraphQL::Define::TypeDefiner.instance
|
77
47
|
end
|
48
|
+
end
|
78
49
|
|
79
|
-
|
80
|
-
def
|
81
|
-
|
82
|
-
argument = GraphQL::Argument.new
|
83
|
-
argument.name = name.to_s
|
84
|
-
argument.type = options.fetch(:type) { raise MissingTypeDefinitionError, name }
|
85
|
-
argument.default_value = options[:default] if options.key? :default
|
86
|
-
argument.description = options[:description] if options.key? :description
|
87
|
-
|
88
|
-
acc[name] = argument
|
89
|
-
acc
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# NOTE(rstankov): Used for GraphQL::Schema::Resolver
|
94
|
-
def field_options
|
95
|
-
{
|
96
|
-
type: type,
|
97
|
-
description: description,
|
98
|
-
extras: [],
|
99
|
-
resolver_method: :resolve_with_support,
|
100
|
-
resolver_class: self,
|
101
|
-
deprecation_reason: deprecation_reason,
|
102
|
-
arguments: (config[:arguments] || {}).inject({}) do |acc, (name, options)|
|
103
|
-
if options.fetch(:camelize) { true }
|
104
|
-
name = name.to_s.split('_').map(&:capitalize).join
|
105
|
-
name[0] = name[0].downcase
|
106
|
-
end
|
107
|
-
|
108
|
-
acc[name] = ::GraphQL::Schema::Argument.new(
|
109
|
-
name: name.to_s,
|
110
|
-
type: options.fetch(:type) { raise MissingTypeDefinitionError, name },
|
111
|
-
description: options[:description],
|
112
|
-
required: !!options[:required],
|
113
|
-
camelize: !!options[:camelize],
|
114
|
-
default_value: options.fetch(:default) { ::GraphQL::Schema::Argument::NO_DEFAULT },
|
115
|
-
owner: self
|
116
|
-
)
|
117
|
-
acc
|
118
|
-
end,
|
119
|
-
null: !!config[:null],
|
120
|
-
complexity: complexity
|
121
|
-
}
|
122
|
-
end
|
123
|
-
|
124
|
-
# NOTE(rstankov): Used for GraphQL::Schema::Resolver
|
125
|
-
def visible?(_context)
|
126
|
-
true
|
127
|
-
end
|
128
|
-
|
129
|
-
# NOTE(rstankov): Used for GraphQL::Schema::Resolver
|
130
|
-
def accessible?(_context)
|
131
|
-
true
|
132
|
-
end
|
133
|
-
|
134
|
-
# NOTE(rstankov): Used for GraphQL::Schema::Resolver
|
135
|
-
def authorized?(_object, _context)
|
136
|
-
true
|
50
|
+
class NotIncludedInResolverError < ArgumentError
|
51
|
+
def initialize(base)
|
52
|
+
super "#{base.name} should inherit from GraphQL::Schema::Resolver. Current ancestors #{base.ancestors}"
|
137
53
|
end
|
138
54
|
end
|
139
55
|
|
@@ -31,7 +31,7 @@ describe SearchObject::Plugin::Graphql do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def define_search_class(&block)
|
34
|
-
Class.new do
|
34
|
+
Class.new(GraphQL::Schema::Resolver) do
|
35
35
|
include SearchObject.module(:graphql)
|
36
36
|
|
37
37
|
scope { [] }
|
@@ -52,6 +52,12 @@ describe SearchObject::Plugin::Graphql do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
it 'requires class to inherit from GraphQL::Schema::Resolver' do
|
56
|
+
expect do
|
57
|
+
Class.new { include SearchObject.module(:graphql) }
|
58
|
+
end.to raise_error SearchObject::Plugin::Graphql::NotIncludedInResolverError
|
59
|
+
end
|
60
|
+
|
55
61
|
it 'can be used as GraphQL::Schema::Resolver' do
|
56
62
|
post_type = Class.new(GraphQL::Schema::Object) do
|
57
63
|
graphql_name 'Post'
|
@@ -62,7 +68,7 @@ describe SearchObject::Plugin::Graphql do
|
|
62
68
|
search_object = define_search_class do
|
63
69
|
scope { [Post.new('1'), Post.new('2'), Post.new('3')] }
|
64
70
|
|
65
|
-
type [post_type]
|
71
|
+
type [post_type], null: 1
|
66
72
|
|
67
73
|
option(:id, type: !types.ID) { |scope, value| scope.select { |p| p.id == value } }
|
68
74
|
end
|
@@ -80,34 +86,6 @@ describe SearchObject::Plugin::Graphql do
|
|
80
86
|
)
|
81
87
|
end
|
82
88
|
|
83
|
-
it 'can be used as GraphQL::Function' do
|
84
|
-
post_type = GraphQL::ObjectType.define do
|
85
|
-
name 'Post'
|
86
|
-
|
87
|
-
field :id, !types.ID
|
88
|
-
end
|
89
|
-
|
90
|
-
search_object = define_search_class do
|
91
|
-
scope { [Post.new('1'), Post.new('2'), Post.new('3')] }
|
92
|
-
|
93
|
-
type types[post_type]
|
94
|
-
|
95
|
-
option(:id, type: !types.ID) { |scope, value| scope.select { |p| p.id == value } }
|
96
|
-
end
|
97
|
-
|
98
|
-
schema = define_schema do
|
99
|
-
field :posts, function: search_object
|
100
|
-
end
|
101
|
-
|
102
|
-
result = schema.execute '{ posts(id: "2") { id } }'
|
103
|
-
|
104
|
-
expect(result).to eq(
|
105
|
-
'data' => {
|
106
|
-
'posts' => [Post.new('2').to_json]
|
107
|
-
}
|
108
|
-
)
|
109
|
-
end
|
110
|
-
|
111
89
|
it 'can access to parent object' do
|
112
90
|
search_object = define_search_class do
|
113
91
|
scope { object.posts }
|
@@ -164,81 +142,6 @@ describe SearchObject::Plugin::Graphql do
|
|
164
142
|
)
|
165
143
|
end
|
166
144
|
|
167
|
-
it 'can define a custom type' do
|
168
|
-
schema = define_search_class_and_return_schema do
|
169
|
-
type do
|
170
|
-
name 'Test'
|
171
|
-
|
172
|
-
field :title, types.String
|
173
|
-
end
|
174
|
-
|
175
|
-
description 'Test description'
|
176
|
-
end
|
177
|
-
|
178
|
-
result = schema.execute <<-SQL
|
179
|
-
{
|
180
|
-
__type(name: "Query") {
|
181
|
-
name
|
182
|
-
fields {
|
183
|
-
name
|
184
|
-
deprecationReason
|
185
|
-
type {
|
186
|
-
name
|
187
|
-
fields {
|
188
|
-
name
|
189
|
-
}
|
190
|
-
}
|
191
|
-
}
|
192
|
-
}
|
193
|
-
}
|
194
|
-
SQL
|
195
|
-
|
196
|
-
expect(result).to eq(
|
197
|
-
'data' => {
|
198
|
-
'__type' => {
|
199
|
-
'name' => 'Query',
|
200
|
-
'fields' => [{
|
201
|
-
'name' => 'posts',
|
202
|
-
'deprecationReason' => nil,
|
203
|
-
'type' => {
|
204
|
-
'name' => 'Test',
|
205
|
-
'fields' => [{
|
206
|
-
'name' => 'title'
|
207
|
-
}]
|
208
|
-
}
|
209
|
-
}]
|
210
|
-
}
|
211
|
-
}
|
212
|
-
)
|
213
|
-
end
|
214
|
-
|
215
|
-
it 'can be marked as deprecated' do
|
216
|
-
schema = define_search_class_and_return_schema do
|
217
|
-
type [PostType]
|
218
|
-
deprecation_reason 'Not needed any more'
|
219
|
-
end
|
220
|
-
|
221
|
-
result = schema.execute <<-QUERY
|
222
|
-
{
|
223
|
-
__type(name: "Query") {
|
224
|
-
name
|
225
|
-
fields {
|
226
|
-
name
|
227
|
-
}
|
228
|
-
}
|
229
|
-
}
|
230
|
-
QUERY
|
231
|
-
|
232
|
-
expect(result.to_h).to eq(
|
233
|
-
'data' => {
|
234
|
-
'__type' => {
|
235
|
-
'name' => 'Query',
|
236
|
-
'fields' => []
|
237
|
-
}
|
238
|
-
}
|
239
|
-
)
|
240
|
-
end
|
241
|
-
|
242
145
|
describe 'option' do
|
243
146
|
it 'converts GraphQL::Schema::Enum to SearchObject enum' do
|
244
147
|
schema = define_search_class_and_return_schema do
|
@@ -271,8 +174,8 @@ describe SearchObject::Plugin::Graphql do
|
|
271
174
|
|
272
175
|
it 'converts GraphQL::EnumType to SearchObject enum' do
|
273
176
|
schema = define_search_class_and_return_schema do
|
274
|
-
enum_type = GraphQL::
|
275
|
-
|
177
|
+
enum_type = Class.new(GraphQL::Schema::Enum) do
|
178
|
+
graphql_name 'TestEnum'
|
276
179
|
|
277
180
|
value 'PRICE'
|
278
181
|
value 'DATE'
|
@@ -328,7 +231,7 @@ describe SearchObject::Plugin::Graphql do
|
|
328
231
|
|
329
232
|
it 'accepts description' do
|
330
233
|
schema = define_search_class_and_return_schema do
|
331
|
-
type PostType
|
234
|
+
type PostType, null: true
|
332
235
|
|
333
236
|
option('option', type: types.String, description: 'what this argument does') { [] }
|
334
237
|
end
|
@@ -364,7 +267,7 @@ describe SearchObject::Plugin::Graphql do
|
|
364
267
|
|
365
268
|
it 'accepts camelize' do
|
366
269
|
schema = define_search_class_and_return_schema do
|
367
|
-
type PostType
|
270
|
+
type PostType, null: true
|
368
271
|
|
369
272
|
option('option_field', type: types.String, camelize: false)
|
370
273
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: search_object_graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Radoslav Stankov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- example/app/controllers/application_controller.rb
|
135
135
|
- example/app/controllers/graphql_controller.rb
|
136
136
|
- example/app/graphql/mutations/.keep
|
137
|
+
- example/app/graphql/resolvers/base_resolver.rb
|
137
138
|
- example/app/graphql/resolvers/base_search_resolver.rb
|
138
139
|
- example/app/graphql/resolvers/category_search.rb
|
139
140
|
- example/app/graphql/resolvers/post_search.rb
|