search_object_graphql 0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +15 -3
- data/.ruby-version +1 -0
- data/.travis.yml +3 -2
- data/CHANGELOG.md +25 -0
- data/Gemfile +2 -0
- data/README.md +34 -33
- data/Rakefile +3 -1
- data/example/.ruby-version +1 -1
- data/example/Gemfile +3 -1
- data/example/README.md +3 -3
- data/example/Rakefile +2 -0
- data/example/app/controllers/application_controller.rb +2 -0
- data/example/app/controllers/graphql_controller.rb +22 -18
- data/example/app/graphql/mutations/.keep +0 -0
- data/example/app/graphql/resolvers/base_resolver.rb +6 -0
- data/example/app/graphql/resolvers/base_search_resolver.rb +3 -1
- data/example/app/graphql/resolvers/category_search.rb +5 -3
- data/example/app/graphql/resolvers/post_search.rb +6 -4
- data/example/app/graphql/schema.rb +3 -1
- data/example/app/graphql/types/base_enum.rb +6 -0
- data/example/app/graphql/types/base_input_object.rb +6 -0
- data/example/app/graphql/types/base_interface.rb +7 -0
- data/example/app/graphql/types/base_object.rb +6 -0
- data/example/app/graphql/types/base_scalar.rb +6 -0
- data/example/app/graphql/types/base_union.rb +6 -0
- data/example/app/graphql/types/category_type.rb +7 -6
- data/example/app/graphql/types/date_time_type.rb +3 -4
- data/example/app/graphql/types/mutation_type.rb +6 -0
- data/example/app/graphql/types/post_type.rb +13 -11
- data/example/app/graphql/types/query_type.rb +6 -5
- data/example/app/models/application_record.rb +2 -0
- data/example/app/models/category.rb +2 -0
- data/example/app/models/post.rb +2 -0
- data/example/bin/bundle +3 -1
- data/example/bin/rails +2 -0
- data/example/bin/rake +2 -0
- data/example/bin/setup +4 -2
- data/example/bin/update +4 -2
- data/example/config.ru +2 -0
- data/example/config/application.rb +1 -1
- data/example/db/migrate/20170507175133_create_demo_tables.rb +1 -1
- data/example/db/schema.rb +1 -1
- data/example/public/favicon.ico +0 -0
- data/lib/search_object/plugin/graphql.rb +26 -47
- data/lib/search_object/plugin/graphql/version.rb +3 -1
- data/search_object_graphql.gemspec +9 -9
- data/spec/search_object/plugin/graphql_spec.rb +114 -96
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helper_active_record.rb +2 -0
- metadata +31 -35
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
name 'Category'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Types
|
4
|
+
class CategoryType < BaseObject
|
5
|
+
field :id, ID, null: false
|
6
|
+
field :name, String, null: false
|
7
|
+
field :posts, resolver: Resolvers::PostSearch
|
8
|
+
end
|
8
9
|
end
|
@@ -1,6 +1,5 @@
|
|
1
|
-
|
2
|
-
name 'DateTime'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
module Types
|
4
|
+
DateTimeType = GraphQL::Types::ISO8601DateTime
|
6
5
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
|
2
|
-
name 'Post'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
3
|
+
module Types
|
4
|
+
class PostType < BaseObject
|
5
|
+
field :id, ID, null: false
|
6
|
+
field :title, String, null: false
|
7
|
+
field :body, String, null: false
|
8
|
+
field :category, CategoryType, null: false
|
9
|
+
field :views_count, Int, null: false
|
10
|
+
field :likes_count, Int, null: false
|
11
|
+
field :comments_count, Int, null: false
|
12
|
+
field :is_published, Boolean, null: false, method: :published?
|
13
|
+
field :published_at, DateTimeType, null: false
|
14
|
+
end
|
13
15
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
|
-
name 'Query'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Types
|
4
|
+
class QueryType < Types::BaseObject
|
5
|
+
field :categories, resolver: Resolvers::CategorySearch
|
6
|
+
field :posts, resolver: Resolvers::PostSearch
|
7
|
+
end
|
7
8
|
end
|
data/example/app/models/post.rb
CHANGED
data/example/bin/bundle
CHANGED
data/example/bin/rails
CHANGED
data/example/bin/rake
CHANGED
data/example/bin/setup
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require 'pathname'
|
3
5
|
require 'fileutils'
|
4
|
-
include FileUtils
|
6
|
+
include FileUtils # rubocop:disable Style/MixinUsage
|
5
7
|
|
6
8
|
# path to your application root.
|
7
|
-
APP_ROOT = Pathname.new File.expand_path('
|
9
|
+
APP_ROOT = Pathname.new File.expand_path('..', __dir__)
|
8
10
|
|
9
11
|
def system!(*args)
|
10
12
|
system(*args) || abort("\n== Command #{args} failed ==")
|
data/example/bin/update
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require 'pathname'
|
3
5
|
require 'fileutils'
|
4
|
-
include FileUtils
|
6
|
+
include FileUtils # rubocop:disable Style/MixinUsage
|
5
7
|
|
6
8
|
# path to your application root.
|
7
|
-
APP_ROOT = Pathname.new File.expand_path('
|
9
|
+
APP_ROOT = Pathname.new File.expand_path('..', __dir__)
|
8
10
|
|
9
11
|
def system!(*args)
|
10
12
|
system(*args) || abort("\n== Command #{args} failed ==")
|
data/example/config.ru
CHANGED
@@ -3,7 +3,7 @@ require_relative 'boot'
|
|
3
3
|
require "rails"
|
4
4
|
# Pick the frameworks you want:
|
5
5
|
require "active_model/railtie"
|
6
|
-
|
6
|
+
require "active_job/railtie"
|
7
7
|
require "active_record/railtie"
|
8
8
|
require "action_controller/railtie"
|
9
9
|
# require "action_mailer/railtie"
|
data/example/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 2017_05_07_175133) do
|
14
14
|
|
15
15
|
create_table "categories", force: :cascade do |t|
|
16
16
|
t.string "name", null: false
|
File without changes
|
@@ -1,26 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SearchObject
|
2
4
|
module Plugin
|
3
5
|
module Graphql
|
4
6
|
def self.included(base)
|
7
|
+
raise NotIncludedInResolverError, base unless base.ancestors.include? GraphQL::Schema::Resolver
|
8
|
+
|
5
9
|
base.include SearchObject::Plugin::Enum
|
6
10
|
base.extend ClassMethods
|
7
11
|
end
|
8
12
|
|
9
13
|
attr_reader :object, :context
|
10
14
|
|
11
|
-
def initialize(filters: {}, object: nil, context: {}, scope: nil)
|
15
|
+
def initialize(filters: {}, object: nil, context: {}, scope: nil, field: nil)
|
12
16
|
@object = object
|
13
17
|
@context = context
|
14
18
|
|
15
|
-
super filters: filters, scope: scope
|
19
|
+
super filters: filters, scope: scope, field: field
|
20
|
+
end
|
21
|
+
|
22
|
+
# NOTE(rstankov): GraphQL::Schema::Resolver interface
|
23
|
+
# Documentation - http://graphql-ruby.org/fields/resolvers.html#using-resolver
|
24
|
+
def resolve_with_support(args = {})
|
25
|
+
self.params = args.to_h
|
26
|
+
results
|
16
27
|
end
|
17
28
|
|
18
29
|
module ClassMethods
|
19
30
|
def option(name, options = {}, &block)
|
20
|
-
|
21
|
-
|
31
|
+
type = options.fetch(:type) { raise MissingTypeDefinitionError, name }
|
32
|
+
options[:enum] = type.values.map { |value, enum_value| enum_value.value || value } if type.respond_to?(:values)
|
22
33
|
|
23
|
-
|
34
|
+
argument(
|
35
|
+
name.to_s,
|
36
|
+
options[:type],
|
37
|
+
required: options[:required] || false,
|
38
|
+
description: options[:description],
|
39
|
+
camelize: options[:camelize]
|
40
|
+
)
|
24
41
|
|
25
42
|
super(name, options, &block)
|
26
43
|
end
|
@@ -28,35 +45,11 @@ module SearchObject
|
|
28
45
|
def types
|
29
46
|
GraphQL::Define::TypeDefiner.instance
|
30
47
|
end
|
48
|
+
end
|
31
49
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
new(filters: args.to_h, object: object, context: context).results
|
36
|
-
end
|
37
|
-
|
38
|
-
def arguments
|
39
|
-
config[:args] ||= {}
|
40
|
-
end
|
41
|
-
|
42
|
-
def type(value = :default, &block)
|
43
|
-
return config[:type] if value == :default && !block_given?
|
44
|
-
config[:type] = block_given? ? GraphQL::ObjectType.define(&block) : value
|
45
|
-
end
|
46
|
-
|
47
|
-
def complexity(value = :default)
|
48
|
-
return config[:complexity] || 1 if value == :default
|
49
|
-
config[:complexity] = value
|
50
|
-
end
|
51
|
-
|
52
|
-
def description(value = :default)
|
53
|
-
return config[:description] if value == :default
|
54
|
-
config[:description] = value
|
55
|
-
end
|
56
|
-
|
57
|
-
def deprecation_reason(value = :default)
|
58
|
-
return config[:deprecation_reason] if value == :default
|
59
|
-
config[:deprecation_reason] = value
|
50
|
+
class NotIncludedInResolverError < ArgumentError
|
51
|
+
def initialize(base)
|
52
|
+
super "#{base.name} should inherit from GraphQL::Schema::Resolver. Current ancestors #{base.ancestors}"
|
60
53
|
end
|
61
54
|
end
|
62
55
|
|
@@ -65,20 +58,6 @@ module SearchObject
|
|
65
58
|
super "GraphQL type has to passed as :type to '#{name}' option"
|
66
59
|
end
|
67
60
|
end
|
68
|
-
|
69
|
-
# :api: private
|
70
|
-
module Helper
|
71
|
-
module_function
|
72
|
-
|
73
|
-
def build_argument(name, options)
|
74
|
-
argument = GraphQL::Argument.new
|
75
|
-
argument.name = name.to_s
|
76
|
-
argument.type = options.fetch(:type) { raise MissingTypeDefinitionError, name }
|
77
|
-
argument.default_value = options[:default] if options.key? :default
|
78
|
-
argument.description = options[:description] if options.key? :description
|
79
|
-
argument
|
80
|
-
end
|
81
|
-
end
|
82
61
|
end
|
83
62
|
end
|
84
63
|
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'English'
|
5
6
|
require 'search_object/plugin/graphql/version'
|
@@ -19,13 +20,12 @@ Gem::Specification.new do |spec|
|
|
19
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
21
|
spec.require_paths = ['lib']
|
21
22
|
|
22
|
-
spec.add_dependency '
|
23
|
-
spec.add_dependency '
|
23
|
+
spec.add_dependency 'graphql', '~> 1.8'
|
24
|
+
spec.add_dependency 'search_object', '~> 1.2.2'
|
24
25
|
|
25
|
-
spec.add_development_dependency 'bundler', '~> 1.13'
|
26
|
-
spec.add_development_dependency 'rake'
|
27
|
-
spec.add_development_dependency 'rspec', '~> 3.5'
|
28
|
-
spec.add_development_dependency 'rubocop', '0.46.0'
|
29
|
-
spec.add_development_dependency 'rubocop-rspec', '1.8.0'
|
30
26
|
spec.add_development_dependency 'coveralls'
|
27
|
+
spec.add_development_dependency 'rake'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
29
|
+
spec.add_development_dependency 'rubocop', '0.62.0'
|
30
|
+
spec.add_development_dependency 'rubocop-rspec', '1.31.0'
|
31
31
|
end
|
@@ -1,29 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'graphql'
|
3
5
|
require 'ostruct'
|
4
6
|
require 'search_object/plugin/graphql'
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
{ 'id' => id }
|
10
|
-
end
|
8
|
+
Post = Struct.new(:id) do
|
9
|
+
def to_json(_options = {})
|
10
|
+
{ 'id' => id }
|
11
11
|
end
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
field :id, !types.ID
|
17
|
-
end
|
14
|
+
class PostType < GraphQL::Schema::Object
|
15
|
+
field :id, ID, null: false
|
16
|
+
end
|
18
17
|
|
18
|
+
describe SearchObject::Plugin::Graphql do
|
19
19
|
def define_schema(&block)
|
20
|
-
query_type = GraphQL::
|
21
|
-
|
20
|
+
query_type = Class.new(GraphQL::Schema::Object) do
|
21
|
+
graphql_name 'Query'
|
22
22
|
|
23
23
|
instance_eval(&block)
|
24
24
|
end
|
25
25
|
|
26
|
-
GraphQL::Schema
|
26
|
+
Class.new(GraphQL::Schema) do
|
27
27
|
query query_type
|
28
28
|
|
29
29
|
max_complexity 1000
|
@@ -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 { [] }
|
@@ -45,20 +45,38 @@ describe SearchObject::Plugin::Graphql do
|
|
45
45
|
|
46
46
|
define_schema do
|
47
47
|
if search_object.type.nil?
|
48
|
-
field :posts,
|
48
|
+
field :posts, [PostType], resolver: search_object
|
49
49
|
else
|
50
|
-
field :posts,
|
50
|
+
field :posts, resolver: search_object
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
it '
|
56
|
-
|
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
|
+
|
61
|
+
it 'can be used as GraphQL::Schema::Resolver' do
|
62
|
+
post_type = Class.new(GraphQL::Schema::Object) do
|
63
|
+
graphql_name 'Post'
|
64
|
+
|
65
|
+
field :id, GraphQL::Types::ID, null: false
|
66
|
+
end
|
67
|
+
|
68
|
+
search_object = define_search_class do
|
57
69
|
scope { [Post.new('1'), Post.new('2'), Post.new('3')] }
|
58
70
|
|
71
|
+
type [post_type], null: 1
|
72
|
+
|
59
73
|
option(:id, type: !types.ID) { |scope, value| scope.select { |p| p.id == value } }
|
60
74
|
end
|
61
75
|
|
76
|
+
schema = define_schema do
|
77
|
+
field :posts, resolver: search_object
|
78
|
+
end
|
79
|
+
|
62
80
|
result = schema.execute '{ posts(id: "2") { id } }'
|
63
81
|
|
64
82
|
expect(result).to eq(
|
@@ -73,19 +91,19 @@ describe SearchObject::Plugin::Graphql do
|
|
73
91
|
scope { object.posts }
|
74
92
|
end
|
75
93
|
|
76
|
-
parent_type = GraphQL::
|
77
|
-
|
94
|
+
parent_type = Class.new(GraphQL::Schema::Object) do
|
95
|
+
graphql_name 'Parent'
|
78
96
|
|
79
|
-
field :posts,
|
97
|
+
field :posts, [PostType], resolver: search_object
|
80
98
|
end
|
81
99
|
|
82
100
|
schema = define_schema do
|
83
|
-
field :parent, parent_type
|
84
|
-
resolve ->(_obj, _args, _ctx) { OpenStruct.new posts: [Post.new('from_parent')] }
|
85
|
-
end
|
101
|
+
field :parent, parent_type, null: false
|
86
102
|
end
|
87
103
|
|
88
|
-
|
104
|
+
root = OpenStruct.new(parent: OpenStruct.new(posts: [Post.new('from_parent')]))
|
105
|
+
|
106
|
+
result = schema.execute '{ parent { posts { id } } }', root_value: root
|
89
107
|
|
90
108
|
expect(result).to eq(
|
91
109
|
'data' => {
|
@@ -124,86 +142,40 @@ describe SearchObject::Plugin::Graphql do
|
|
124
142
|
)
|
125
143
|
end
|
126
144
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
field :title, types.String
|
133
|
-
end
|
145
|
+
describe 'option' do
|
146
|
+
it 'converts GraphQL::Schema::Enum to SearchObject enum' do
|
147
|
+
schema = define_search_class_and_return_schema do
|
148
|
+
enum_type = Class.new(GraphQL::Schema::Enum) do
|
149
|
+
graphql_name 'PostOrder'
|
134
150
|
|
135
|
-
|
136
|
-
|
151
|
+
value 'PRICE'
|
152
|
+
value 'DATE'
|
153
|
+
end
|
137
154
|
|
138
|
-
|
139
|
-
{
|
140
|
-
__type(name: "Query") {
|
141
|
-
name
|
142
|
-
fields {
|
143
|
-
name
|
144
|
-
deprecationReason
|
145
|
-
type {
|
146
|
-
name
|
147
|
-
fields {
|
148
|
-
name
|
149
|
-
}
|
150
|
-
}
|
151
|
-
}
|
152
|
-
}
|
153
|
-
}
|
154
|
-
SQL
|
155
|
+
option(:order, type: enum_type)
|
155
156
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
'name' => 'Query',
|
160
|
-
'fields' => [{
|
161
|
-
'name' => 'posts',
|
162
|
-
'deprecationReason' => nil,
|
163
|
-
'type' => {
|
164
|
-
'name' => 'Test',
|
165
|
-
'fields' => [{
|
166
|
-
'name' => 'title'
|
167
|
-
}]
|
168
|
-
}
|
169
|
-
}]
|
170
|
-
}
|
171
|
-
}
|
172
|
-
)
|
173
|
-
end
|
157
|
+
define_method(:apply_order_with_price) do |_scope|
|
158
|
+
[Post.new('price')]
|
159
|
+
end
|
174
160
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
end
|
161
|
+
define_method(:apply_order_with_date) do |_scope|
|
162
|
+
[Post.new('date')]
|
163
|
+
end
|
164
|
+
end
|
180
165
|
|
181
|
-
|
182
|
-
{
|
183
|
-
__type(name: "Query") {
|
184
|
-
name
|
185
|
-
fields {
|
186
|
-
name
|
187
|
-
}
|
188
|
-
}
|
189
|
-
}
|
190
|
-
QUERY
|
166
|
+
result = schema.execute '{ posts(order: PRICE) { id } }'
|
191
167
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
'name' => 'Query',
|
196
|
-
'fields' => []
|
168
|
+
expect(result).to eq(
|
169
|
+
'data' => {
|
170
|
+
'posts' => [Post.new('price').to_json]
|
197
171
|
}
|
198
|
-
|
199
|
-
|
200
|
-
end
|
172
|
+
)
|
173
|
+
end
|
201
174
|
|
202
|
-
describe 'option' do
|
203
175
|
it 'converts GraphQL::EnumType to SearchObject enum' do
|
204
176
|
schema = define_search_class_and_return_schema do
|
205
|
-
enum_type = GraphQL::
|
206
|
-
|
177
|
+
enum_type = Class.new(GraphQL::Schema::Enum) do
|
178
|
+
graphql_name 'TestEnum'
|
207
179
|
|
208
180
|
value 'PRICE'
|
209
181
|
value 'DATE'
|
@@ -245,9 +217,21 @@ describe SearchObject::Plugin::Graphql do
|
|
245
217
|
)
|
246
218
|
end
|
247
219
|
|
220
|
+
it 'accepts "required"' do
|
221
|
+
schema = define_search_class_and_return_schema do
|
222
|
+
option(:id, type: types.String, required: true) do |_scope, value|
|
223
|
+
[Post.new(value)]
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
result = schema.execute '{ posts { id } }'
|
228
|
+
|
229
|
+
expect(result['errors'][0]['message']).to eq("Field 'posts' is missing required arguments: id")
|
230
|
+
end
|
231
|
+
|
248
232
|
it 'accepts description' do
|
249
233
|
schema = define_search_class_and_return_schema do
|
250
|
-
type PostType
|
234
|
+
type PostType, null: true
|
251
235
|
|
252
236
|
option('option', type: types.String, description: 'what this argument does') { [] }
|
253
237
|
end
|
@@ -281,6 +265,40 @@ describe SearchObject::Plugin::Graphql do
|
|
281
265
|
)
|
282
266
|
end
|
283
267
|
|
268
|
+
it 'accepts camelize' do
|
269
|
+
schema = define_search_class_and_return_schema do
|
270
|
+
type PostType, null: true
|
271
|
+
|
272
|
+
option('option_field', type: types.String, camelize: false)
|
273
|
+
end
|
274
|
+
|
275
|
+
result = schema.execute <<-SQL
|
276
|
+
{
|
277
|
+
__type(name: "Query") {
|
278
|
+
name
|
279
|
+
fields {
|
280
|
+
args {
|
281
|
+
name
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
}
|
286
|
+
SQL
|
287
|
+
|
288
|
+
expect(result.to_h).to eq(
|
289
|
+
'data' => {
|
290
|
+
'__type' => {
|
291
|
+
'name' => 'Query',
|
292
|
+
'fields' => [{
|
293
|
+
'args' => [{
|
294
|
+
'name' => 'option_field'
|
295
|
+
}]
|
296
|
+
}]
|
297
|
+
}
|
298
|
+
}
|
299
|
+
)
|
300
|
+
end
|
301
|
+
|
284
302
|
it 'raises error when no type is given' do
|
285
303
|
expect { define_search_class { option :name } }.to raise_error described_class::MissingTypeDefinitionError
|
286
304
|
end
|