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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ab34781a81c8808d0b9702dcf9742955e9859c5827461e00e1b1a431f1df216
4
- data.tar.gz: b5ed30f8e4b39c36d4fb1e9d28b1f2118a7bfd1507a045fac76286a61e8345ac
3
+ metadata.gz: 49fd6817f69aa33a15ce7cc2e768bd239020c3f7f6b6e385e1f12d3c9d5c30ff
4
+ data.tar.gz: c6c4a8d82f1d5afa85519a1e8aee726b321495b2305e63fa0d5e986db75066fb
5
5
  SHA512:
6
- metadata.gz: 93701d2abfb6a521f6aa199aaaf4a0fee641367a20de4b2806cbaeac45539909289529183590ca924c7329aeb7ce9cf53d3c5b581205208338c0ef8200e97874
7
- data.tar.gz: 209b6af6cea55e752c7c76cbdb9769e8af18bed61c124982e58e502f7e10d8136f3a29653875c7b25d876676db0bdb3cb9faa0605132dfca3356a614288255ee
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
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ class BaseResolver < GraphQL::Schema::Resolver
5
+ end
6
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Resolvers
4
- class BaseSearchResolver
4
+ class BaseSearchResolver < BaseResolver
5
5
  include SearchObject.module(:graphql)
6
6
 
7
7
  def escape_search_term(term)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Resolvers
4
4
  class CategorySearch < Resolvers::BaseSearchResolver
5
- type Types::CategoryType.connection_type
5
+ type Types::CategoryType.connection_type, null: false
6
6
  description 'Lists categories'
7
7
 
8
8
  class OrderEnum < Types::BaseEnum
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Resolvers
4
4
  class PostSearch < Resolvers::BaseSearchResolver
5
- type Types::PostType.connection_type
5
+ type Types::PostType.connection_type, null: false
6
6
  description 'Lists posts'
7
7
 
8
8
  class OrderEnum < Types::BaseEnum
@@ -4,6 +4,6 @@ module Types
4
4
  class CategoryType < BaseObject
5
5
  field :id, ID, null: false
6
6
  field :name, String, null: false
7
- field :posts, function: Resolvers::PostSearch
7
+ field :posts, resolver: Resolvers::PostSearch
8
8
  end
9
9
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Types
4
4
  class QueryType < Types::BaseObject
5
- field :categories, function: Resolvers::CategorySearch
5
+ field :categories, resolver: Resolvers::CategorySearch
6
6
  field :posts, resolver: Resolvers::PostSearch
7
7
  end
8
8
  end
@@ -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
- super(name, options, &block)
41
- end
42
-
43
- def type(value = :default, null: true, &block)
44
- return config[:type] if value == :default && !block_given?
45
-
46
- config[:type] = block_given? ? GraphQL::ObjectType.define(&block) : value
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
- config[:deprecation_reason] = value
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
- # NOTE(rstankov): Used for GraphQL::Function
80
- def arguments
81
- (config[:arguments] || {}).inject({}) do |acc, (name, options)|
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
 
@@ -3,7 +3,7 @@
3
3
  module SearchObject
4
4
  module Plugin
5
5
  module Graphql
6
- VERSION = '0.3.2'
6
+ VERSION = '1.0.0'
7
7
  end
8
8
  end
9
9
  end
@@ -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::EnumType.define do
275
- name 'TestEnum'
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.3.2
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: 2020-06-07 00:00:00.000000000 Z
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