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.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +15 -3
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +3 -2
  5. data/CHANGELOG.md +25 -0
  6. data/Gemfile +2 -0
  7. data/README.md +34 -33
  8. data/Rakefile +3 -1
  9. data/example/.ruby-version +1 -1
  10. data/example/Gemfile +3 -1
  11. data/example/README.md +3 -3
  12. data/example/Rakefile +2 -0
  13. data/example/app/controllers/application_controller.rb +2 -0
  14. data/example/app/controllers/graphql_controller.rb +22 -18
  15. data/example/app/graphql/mutations/.keep +0 -0
  16. data/example/app/graphql/resolvers/base_resolver.rb +6 -0
  17. data/example/app/graphql/resolvers/base_search_resolver.rb +3 -1
  18. data/example/app/graphql/resolvers/category_search.rb +5 -3
  19. data/example/app/graphql/resolvers/post_search.rb +6 -4
  20. data/example/app/graphql/schema.rb +3 -1
  21. data/example/app/graphql/types/base_enum.rb +6 -0
  22. data/example/app/graphql/types/base_input_object.rb +6 -0
  23. data/example/app/graphql/types/base_interface.rb +7 -0
  24. data/example/app/graphql/types/base_object.rb +6 -0
  25. data/example/app/graphql/types/base_scalar.rb +6 -0
  26. data/example/app/graphql/types/base_union.rb +6 -0
  27. data/example/app/graphql/types/category_type.rb +7 -6
  28. data/example/app/graphql/types/date_time_type.rb +3 -4
  29. data/example/app/graphql/types/mutation_type.rb +6 -0
  30. data/example/app/graphql/types/post_type.rb +13 -11
  31. data/example/app/graphql/types/query_type.rb +6 -5
  32. data/example/app/models/application_record.rb +2 -0
  33. data/example/app/models/category.rb +2 -0
  34. data/example/app/models/post.rb +2 -0
  35. data/example/bin/bundle +3 -1
  36. data/example/bin/rails +2 -0
  37. data/example/bin/rake +2 -0
  38. data/example/bin/setup +4 -2
  39. data/example/bin/update +4 -2
  40. data/example/config.ru +2 -0
  41. data/example/config/application.rb +1 -1
  42. data/example/db/migrate/20170507175133_create_demo_tables.rb +1 -1
  43. data/example/db/schema.rb +1 -1
  44. data/example/public/favicon.ico +0 -0
  45. data/lib/search_object/plugin/graphql.rb +26 -47
  46. data/lib/search_object/plugin/graphql/version.rb +3 -1
  47. data/search_object_graphql.gemspec +9 -9
  48. data/spec/search_object/plugin/graphql_spec.rb +114 -96
  49. data/spec/spec_helper.rb +2 -0
  50. data/spec/spec_helper_active_record.rb +2 -0
  51. metadata +31 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 20d420d2ee1dd08bdfe48da2c5e1e3ba0a3a8233
4
- data.tar.gz: 57a5009d415d6fad948001d18d428676dbd1471c
2
+ SHA256:
3
+ metadata.gz: 49fd6817f69aa33a15ce7cc2e768bd239020c3f7f6b6e385e1f12d3c9d5c30ff
4
+ data.tar.gz: c6c4a8d82f1d5afa85519a1e8aee726b321495b2305e63fa0d5e986db75066fb
5
5
  SHA512:
6
- metadata.gz: d25a679fad52b5605c5720a774f2bee6d273abc369dbfd90cc48a75793d7fd3cc6359092406d178aecd0ae97fdb6e2f938f891b764b2ebfb26c47bf99fc63605
7
- data.tar.gz: f7d5f5e368c50e3bc274b8d665c83ca975f1093e55a7059c906f17e93a40388c097d51ce7288b99394b3d8268913bfe0ea1ef1d2a611bedaa0e7df9380160f5f
6
+ metadata.gz: a71588bac7cc2fba645d1e4007bfeed111749c0016d4a2de7e832990ff33f37e1656c08a47fd3a52f18664e594bbefee3939d1412aa3fc5d679dd9c3d875d533
7
+ data.tar.gz: 4c9bfd49332eafbd37b10be48bc58c65bfffa0546dc7c394a7b77e3e146769ee77083f39bbd40f101302ad7ffb967d8b7e0054b6512c35febdcedc0e00c94855
data/.rubocop.yml CHANGED
@@ -7,15 +7,15 @@ AllCops:
7
7
  - search_object.gemspec
8
8
 
9
9
  # Disables "Line is too long"
10
- LineLength:
10
+ Metrics/LineLength:
11
11
  Enabled: false
12
12
 
13
13
  # Disables Module has too many lines
14
- ModuleLength:
14
+ Metrics/ModuleLength:
15
15
  Enabled: false
16
16
 
17
17
  # Disables "Missing top-level class documentation comment"
18
- Documentation:
18
+ Style/Documentation:
19
19
  Enabled: false
20
20
 
21
21
  # Disables "Use each_with_object instead of inject"
@@ -26,10 +26,22 @@ Style/EachWithObject:
26
26
  Style/CollectionMethods:
27
27
  Enabled: false
28
28
 
29
+ # Disables "Avoid the use of double negation (!!)."
30
+ Style/DoubleNegation:
31
+ Enabled: false
32
+
29
33
  # Disables "Block has too many lines."
30
34
  Metrics/BlockLength:
31
35
  Enabled: false
32
36
 
37
+ # Disables "Assignment Branch Condition size for field_options is too high."
38
+ Metrics/AbcSize:
39
+ Enabled: false
40
+
41
+ # Disables "Method has too many line."
42
+ Metrics/MethodLength:
43
+ Enabled: false
44
+
33
45
  # Disables "Example has too many lines."
34
46
  RSpec/ExampleLength:
35
47
  Enabled: false
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.6.2
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2
4
- - 2.3.0
3
+ - 2.4.1
4
+ - 2.5.2
5
+ - 2.6.0
5
6
  script:
6
7
  - bundle exec rubocop
7
8
  - bundle exec rspec spec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
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
+
10
+ ## Version 0.3.2
11
+
12
+ * __[feature]__ Added `camelize` argument to `option`, *`true` by default* (@glenbray)
13
+
14
+ ## Version 0.3.1
15
+
16
+ * __[fix]__ Support for GraphQL gem version v1.9.16 (@ardinusawan)
17
+
18
+ ## Version 0.3
19
+
20
+ * __[feature]__ Allow passing `required` key to option definition (@vfonic)
21
+ * __[fix]__ Support for GraphQL gem enums (@Postmodum37)
22
+
23
+ ## Version 0.2
24
+
25
+ * Added support for GraphQL::Schema::Resolver (@rstankov)
26
+ * Added support for GraphQL 1.8 class API (@rstankov)
27
+
3
28
  ## Version 0.1
4
29
 
5
30
  * Initial release (@rstankov)
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in search_object.gemspec
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+ [![Gem Version](https://badge.fury.io/rb/search_object_graphql.svg)](http://badge.fury.io/rb/search_object_graphql)
1
2
  [![Code Climate](https://codeclimate.com/github/RStankov/SearchObjectGraphQL.svg)](https://codeclimate.com/github/RStankov/SearchObjectGraphQL)
2
3
  [![Build Status](https://secure.travis-ci.org/RStankov/SearchObjectGraphQL.svg)](http://travis-ci.org/RStankov/SearchObjectGraphQL)
3
4
  [![Code coverage](https://coveralls.io/repos/RStankov/SearchObjectGraphQL/badge.svg?branch=master#2)](https://coveralls.io/r/RStankov/SearchObjectGraphQL)
@@ -19,13 +20,15 @@
19
20
  * [Accessing Parent Object](#accessing-parent-object)
20
21
  * [Enums Support](#enums-support)
21
22
  * [Relay Support](#relay-support)
23
+ * [Contributing](#contributing)
24
+ * [License](#license)
22
25
 
23
26
  ## Installation
24
27
 
25
28
  Add this line to your application's Gemfile:
26
29
 
27
30
  ```ruby
28
- gem 'search_object'
31
+ gem 'search_object_graphql'
29
32
  ```
30
33
 
31
34
  And then execute:
@@ -34,7 +37,15 @@ And then execute:
34
37
 
35
38
  Or install it yourself as:
36
39
 
37
- $ gem install search_object
40
+ $ gem install search_object_graphql
41
+
42
+
43
+ **Require manually in your project**
44
+
45
+ ```ruby
46
+ require 'search_object'
47
+ require 'search_object/plugin/graphql'
48
+ ```
38
49
 
39
50
  ## Dependencies
40
51
 
@@ -46,22 +57,22 @@ Or install it yourself as:
46
57
  Just include the ```SearchObject.module``` and define your search options and their types:
47
58
 
48
59
  ```ruby
49
- class PostResolver
60
+ class PostResolver < GraphQL::Schema::Resolver
50
61
  include SearchObject.module(:graphql)
51
62
 
52
- type PostType
63
+ type [PostType], null: false
53
64
 
54
65
  scope { Post.all }
55
66
 
56
- option(:name, type: types.String) { |scope, value| scope.where name: value }
57
- option(:published, type: types.Boolean) { |scope, value| value ? scope.published : scope.unpublished }
67
+ option(:name, type: String) { |scope, value| scope.where name: value }
68
+ option(:published, type: Boolean) { |scope, value| value ? scope.published : scope.unpublished }
58
69
  end
59
70
  ```
60
71
 
61
- Then you can just use `PostResolver` as [GraphQL::Function](https://rmosolgo.github.io/graphql-ruby/schema/code_reuse#functions):
72
+ Then you can just use `PostResolver` as [GraphQL::Schema::Resolver](https://graphql-ruby.org/fields/resolvers.html):
62
73
 
63
74
  ```ruby
64
- field :posts, function: PostResolver
75
+ field :posts, resolver: PostResolver
65
76
  ```
66
77
 
67
78
  Options are exposed as arguments in the GraphQL query:
@@ -78,32 +89,12 @@ You can find example of most important features and plugins - [here](https://git
78
89
 
79
90
  ## Features
80
91
 
81
- ### Custom Types
82
-
83
- Custom types can be define inside the search object:
84
-
85
- ```ruby
86
- class PostResolver
87
- include SearchObject.module(:graphql)
88
-
89
- type do
90
- name 'Custom Type'
91
-
92
- field :id, !types.ID
93
- field :title, !types.String
94
- field :body, !types.String
95
- end
96
-
97
- # ...
98
- end
99
- ```
100
-
101
92
  ### Documentation
102
93
 
103
94
  Search object itself can be documented, as well as its options:
104
95
 
105
96
  ```ruby
106
- class PostResolver
97
+ class PostResolver < GraphQL::Schema::Resolver
107
98
  include SearchObject.module(:graphql)
108
99
 
109
100
  description 'Lists all posts'
@@ -116,7 +107,7 @@ end
116
107
  ### Default Values
117
108
 
118
109
  ```ruby
119
- class PostResolver
110
+ class PostResolver < GraphQL::Schema::Resolver
120
111
  include SearchObject.module(:graphql)
121
112
 
122
113
  scope { Post.all }
@@ -130,7 +121,7 @@ end
130
121
  Sometimes you want to scope posts based on parent object, it is accessible as `object` property:
131
122
 
132
123
  ```ruby
133
- class PostResolver
124
+ class PostResolver < GraphQL::Schema::Resolver
134
125
  include SearchObject.module(:graphql)
135
126
 
136
127
  # lists only posts from certain category
@@ -174,10 +165,20 @@ end
174
165
 
175
166
  ### Relay Support
176
167
 
177
- Search objects can be used as [Relay Connections](https://rmosolgo.github.io/graphql-ruby/relay/connections):
168
+ Search objects can be used as [Relay Connections](https://graphql-ruby.org/relay/connections.html):
169
+
170
+ ```ruby
171
+ class PostResolver < GraphQL::Schema::Resolver
172
+ include SearchObject.module(:graphql)
173
+
174
+ type PostType.connection_type, null: false
175
+
176
+ # ...
177
+ end
178
+ ```
178
179
 
179
180
  ```ruby
180
- connection :posts, Types::PostType.connection_type, function: Resolvers::PostSearch
181
+ field :posts, resolver: PostResolver
181
182
  ```
182
183
 
183
184
  ## Contributing
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
  require 'rubocop/rake_task'
@@ -5,4 +7,4 @@ require 'rubocop/rake_task'
5
7
  RSpec::Core::RakeTask.new(:spec)
6
8
  RuboCop::RakeTask.new(:rubocop)
7
9
 
8
- task default: [:rubocop, :spec]
10
+ task default: %i[rubocop spec]
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.5.1
data/example/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  git_source(:github) do |repo_name|
@@ -5,7 +7,7 @@ git_source(:github) do |repo_name|
5
7
  "https://github.com/#{repo_name}.git"
6
8
  end
7
9
 
8
- gem 'rails', '~> 5.1.0'
10
+ gem 'rails', '~> 5.2.0'
9
11
 
10
12
  gem 'graphql'
11
13
  gem 'puma', '~> 3.7'
data/example/README.md CHANGED
@@ -16,9 +16,9 @@ This is example application showing, one of the possible usages of ```SearchObje
16
16
  ```
17
17
  gem install bundler
18
18
  bundle install
19
- rake db:create
20
- rake db:migrate
21
- rake db:seed
19
+ rails db:create
20
+ rails db:migrate
21
+ rails db:seed
22
22
 
23
23
  rails server
24
24
  ```
data/example/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Add your own tasks in files placed in lib/tasks ending in .rake,
2
4
  # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
5
 
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ApplicationController < ActionController::API
2
4
  end
@@ -1,29 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class GraphqlController < ApplicationController
2
4
  def execute
3
- render json: Schema.execute(query, variables: variables, context: context)
5
+ result = Schema.execute(params[:query],
6
+ variables: ensure_hash(params[:variables]),
7
+ context: {},
8
+ operation_name: params[:operationName])
9
+ render json: result
10
+ rescue StandardError => e
11
+ raise e unless Rails.env.development?
12
+
13
+ handle_error_in_development e
4
14
  end
5
15
 
6
16
  private
7
17
 
8
- def query
9
- params[:query]
10
- end
11
-
12
- def variables
13
- ensure_hash(params[:variables])
18
+ def ensure_hash(ambiguous_param)
19
+ case ambiguous_param
20
+ when String then ambiguous_param.present? ? ensure_hash(JSON.parse(ambiguous_param)) : {}
21
+ when Hash, ActionController::Parameters then ambiguous_param
22
+ when nil then {}
23
+ else raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
24
+ end
14
25
  end
15
26
 
16
- def context
17
- {}
18
- end
27
+ def handle_error_in_development(error)
28
+ logger.error error.message
29
+ logger.error error.backtrace.join("\n")
19
30
 
20
- # Handle form data, JSON body, or a blank value
21
- def ensure_hash(params)
22
- case params
23
- when String then params.present? ? ensure_hash(JSON.parse(params)) : {}
24
- when Hash, ActionController::Parameters then params
25
- when nil then {}
26
- else raise ArgumentError, "Unexpected parameter: #{params}"
27
- end
31
+ render json: { error: { message: error.message, backtrace: error.backtrace }, data: {} }, status: 500
28
32
  end
29
33
  end
File without changes
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ class BaseResolver < GraphQL::Schema::Resolver
5
+ end
6
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Resolvers
2
- class BaseSearchResolver
4
+ class BaseSearchResolver < BaseResolver
3
5
  include SearchObject.module(:graphql)
4
6
 
5
7
  def escape_search_term(term)
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Resolvers
2
4
  class CategorySearch < Resolvers::BaseSearchResolver
3
- type Types::CategoryType
5
+ type Types::CategoryType.connection_type, null: false
4
6
  description 'Lists categories'
5
7
 
6
- OrderEnum = GraphQL::EnumType.define do
7
- name 'CategoryOrder'
8
+ class OrderEnum < Types::BaseEnum
9
+ graphql_name 'CategoryOrder'
8
10
 
9
11
  value 'RECENT'
10
12
  value 'NAME'
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Resolvers
2
4
  class PostSearch < Resolvers::BaseSearchResolver
3
- type Types::PostType
5
+ type Types::PostType.connection_type, null: false
4
6
  description 'Lists posts'
5
7
 
6
- OrderEnum = GraphQL::EnumType.define do
7
- name 'PostOrder'
8
+ class OrderEnum < Types::BaseEnum
9
+ graphql_name 'PostOrder'
8
10
 
9
11
  value 'RECENT'
10
12
  value 'VIEWS'
@@ -51,7 +53,7 @@ module Resolvers
51
53
  end
52
54
 
53
55
  def apply_order_with_recent(scope)
54
- scope.order 'published_at IS NOT NULL, published_at DESC'
56
+ scope.order Arel.sql('published_at IS NOT NULL'), published_at: :desc
55
57
  end
56
58
 
57
59
  def apply_order_with_views(scope)
@@ -1,3 +1,5 @@
1
- Schema = GraphQL::Schema.define do
1
+ # frozen_string_literal: true
2
+
3
+ class Schema < GraphQL::Schema
2
4
  query Types::QueryType
3
5
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ class BaseEnum < GraphQL::Schema::Enum
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ class BaseInputObject < GraphQL::Schema::InputObject
5
+ end
6
+ end