graphql_rails 1.0.0 → 1.2.3
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/.hound.yml +1 -0
- data/.rubocop.yml +3 -3
- data/.ruby-version +1 -1
- data/.travis.yml +2 -2
- data/CHANGELOG.md +22 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +145 -119
- data/docs/README.md +3 -3
- data/docs/components/controller.md +23 -7
- data/docs/components/model.md +43 -3
- data/docs/getting_started/quick_start.md +1 -1
- data/docs/index.html +1 -1
- data/docs/other_tools/query_runner.md +1 -1
- data/docs/other_tools/schema_dump.md +1 -1
- data/graphql_rails.gemspec +5 -5
- data/lib/generators/graphql_rails/templates/graphql_router_spec.erb +10 -7
- data/lib/graphql_rails/attributes/attributable.rb +5 -9
- data/lib/graphql_rails/attributes/attribute.rb +26 -6
- data/lib/graphql_rails/attributes/attribute_name_parser.rb +4 -4
- data/lib/graphql_rails/attributes/input_attribute.rb +5 -1
- data/lib/graphql_rails/attributes/type_parseable.rb +17 -13
- data/lib/graphql_rails/concerns/service.rb +6 -2
- data/lib/graphql_rails/controller.rb +6 -6
- data/lib/graphql_rails/controller/action.rb +5 -1
- data/lib/graphql_rails/controller/build_controller_action_resolver.rb +2 -2
- data/lib/graphql_rails/controller/log_controller_action.rb +7 -2
- data/lib/graphql_rails/controller/request.rb +1 -1
- data/lib/graphql_rails/controller/request/format_errors.rb +1 -1
- data/lib/graphql_rails/decorator/relation_decorator.rb +0 -4
- data/lib/graphql_rails/model/add_fields_to_graphql_type.rb +45 -0
- data/lib/graphql_rails/model/build_connection_type.rb +5 -1
- data/lib/graphql_rails/model/build_connection_type/count_items.rb +2 -2
- data/lib/graphql_rails/model/build_graphql_input_type.rb +1 -1
- data/lib/graphql_rails/model/call_graphql_model_method.rb +14 -1
- data/lib/graphql_rails/model/configurable.rb +6 -2
- data/lib/graphql_rails/model/configuration.rb +9 -4
- data/lib/graphql_rails/model/find_or_build_graphql_type.rb +64 -0
- data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +46 -0
- data/lib/graphql_rails/router.rb +2 -2
- data/lib/graphql_rails/router/resource_routes_builder.rb +8 -8
- data/lib/graphql_rails/router/route.rb +3 -7
- data/lib/graphql_rails/router/schema_builder.rb +5 -1
- data/lib/graphql_rails/rspec_controller_helpers.rb +2 -2
- data/lib/graphql_rails/version.rb +1 -1
- metadata +25 -18
- data/lib/graphql_rails/model/build_graphql_type.rb +0 -53
@@ -78,7 +78,7 @@ Specifies input type:
|
|
78
78
|
class OrderController < GraphqlRails::Controller
|
79
79
|
action(:create)
|
80
80
|
.permit_input(:price, type: :integer!)
|
81
|
-
# Same as `.permit(
|
81
|
+
# Same as `.permit(price: :integer!)`
|
82
82
|
end
|
83
83
|
```
|
84
84
|
|
@@ -169,7 +169,7 @@ class UsersController < GraphqlRails::Controller
|
|
169
169
|
end
|
170
170
|
```
|
171
171
|
|
172
|
-
Also check ['decorating controller responses'](
|
172
|
+
Also check ['decorating controller responses'](components/decorator) for more details about working with active record and decorators.
|
173
173
|
|
174
174
|
#### *max_page_size*
|
175
175
|
|
@@ -219,6 +219,22 @@ class UsersController < GraphqlRails::Controller
|
|
219
219
|
end
|
220
220
|
```
|
221
221
|
|
222
|
+
You can also return raw graphql-ruby types:
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
# raw graphql-ruby type:
|
226
|
+
class OrderType < GraphQL::Schema::Object
|
227
|
+
graphql_name 'Order'
|
228
|
+
field :id, ID
|
229
|
+
end
|
230
|
+
|
231
|
+
class UsersController < GraphqlRails::Controller
|
232
|
+
action(:last_order).permit(:id).returns(OrderType)
|
233
|
+
end
|
234
|
+
```
|
235
|
+
|
236
|
+
Check [graphql-ruby documentation](https://graphql-ruby.org) for more details about graphql-ruby types.
|
237
|
+
|
222
238
|
### *returns_list*
|
223
239
|
|
224
240
|
When you have defined `model` dynamically, you can use `returns_list` to indicate that action must return list without specifying model type for each action. By default list and inner types are required but you can change that with `required_list: false` and `required_inner: false`
|
@@ -430,7 +446,7 @@ class UsersController < GraphqlRails::Controller
|
|
430
446
|
raise 'Not authenticated' unless User.where(token: params[:token]).exist?
|
431
447
|
end
|
432
448
|
|
433
|
-
def
|
449
|
+
def require_admin_token
|
434
450
|
raise 'Admin not authenticated' unless Admin.where(token: params[:admin_token]).exist?
|
435
451
|
end
|
436
452
|
end
|
@@ -438,13 +454,13 @@ end
|
|
438
454
|
|
439
455
|
## decorating objects
|
440
456
|
|
441
|
-
See ['Decorating controller responses'](
|
457
|
+
See ['Decorating controller responses'](components/decorator) for various options how you can decorate paginated responses
|
442
458
|
|
443
459
|
## Rendering errors
|
444
460
|
|
445
461
|
### Rendering strings as errors
|
446
462
|
|
447
|
-
The
|
463
|
+
The simplest way to render an error is to provide a list of error messages, like this:
|
448
464
|
|
449
465
|
```ruby
|
450
466
|
class UsersController < GraphqlRails::Controller
|
@@ -509,12 +525,12 @@ end
|
|
509
525
|
|
510
526
|
### Raising custom error classes
|
511
527
|
|
512
|
-
If you want to have customized error classes you need to create errors which
|
528
|
+
If you want to have customized error classes you need to create errors which inherit from `GraphqlRails::ExecutionError`
|
513
529
|
|
514
530
|
```ruby
|
515
531
|
class MyCustomError < GraphqlRails::ExecutionError
|
516
532
|
def to_h
|
517
|
-
# this part will be rendered in
|
533
|
+
# this part will be rendered in graphql
|
518
534
|
{ something_custom: 'yes' }
|
519
535
|
end
|
520
536
|
end
|
data/docs/components/model.md
CHANGED
@@ -17,13 +17,13 @@ end
|
|
17
17
|
|
18
18
|
## graphql
|
19
19
|
|
20
|
-
This method must be called inside your model body. `
|
20
|
+
This method must be called inside your model body. `graphql` is used for making your model convertible to graphql type.
|
21
21
|
|
22
22
|
## attribute
|
23
23
|
|
24
24
|
Most commonly you will use `attribute` to make your model methods and attributes visible via graphql endpoint.
|
25
25
|
|
26
|
-
|
26
|
+
### attribute.type
|
27
27
|
|
28
28
|
Some types can be determined by attribute name, so you can skip this attribute:
|
29
29
|
|
@@ -54,9 +54,33 @@ class User
|
|
54
54
|
end
|
55
55
|
```
|
56
56
|
|
57
|
+
#### attribute.type: using graphql-ruby objects
|
58
|
+
|
59
|
+
You can also use raw graphql-ruby objects as attribute types. Here is an example:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
# raw graphql-ruby type:
|
63
|
+
class AddressType < GraphQL::Schema::Object
|
64
|
+
graphql_name 'Address'
|
65
|
+
|
66
|
+
field :city, String, null: false
|
67
|
+
field :street_name, String, null: false
|
68
|
+
field :street_number, Integer
|
69
|
+
end
|
70
|
+
|
71
|
+
# GraphqlRails model:
|
72
|
+
class User
|
73
|
+
include GraphqlRails::Model
|
74
|
+
|
75
|
+
graphql.attribute :address, type: AddressType, required: true
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
Check [graphql-ruby documentation](https://graphql-ruby.org) for more details about graphql-ruby types.
|
80
|
+
|
57
81
|
### attribute.property
|
58
82
|
|
59
|
-
By default graphql attribute names are expected to be same as model methods/attributes, but if you want to use different name on grapqhl side, you can use `
|
83
|
+
By default graphql attribute names are expected to be same as model methods/attributes, but if you want to use different name on grapqhl side, you can use `property` option:
|
60
84
|
|
61
85
|
```ruby
|
62
86
|
class User
|
@@ -86,6 +110,22 @@ class User
|
|
86
110
|
end
|
87
111
|
```
|
88
112
|
|
113
|
+
### attribute.options
|
114
|
+
|
115
|
+
Allows passing options to attribute definition. Available options:
|
116
|
+
|
117
|
+
* `attribute_name_format` - if `:original` value is passed, it will not camelCase attribute name.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
class User
|
121
|
+
include GraphqlRails::Model
|
122
|
+
|
123
|
+
graphql do |c|
|
124
|
+
c.attribute :first_name # will be accessible as firstName from client side
|
125
|
+
c.attribute :first_name, options: { attribute_name_format: :original } # will be accessible as first_name from client side
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
89
129
|
### attribute.permit
|
90
130
|
|
91
131
|
To define attributes which are accepted by each model method, you need to call `permit` method, like this:
|
@@ -11,7 +11,7 @@ bundle exec rails g graphql_rails:install
|
|
11
11
|
```ruby
|
12
12
|
# config/graphql/routes.rb
|
13
13
|
GraphqlRails::Router.draw do
|
14
|
-
# will create createUser, updateUser,
|
14
|
+
# will create createUser, updateUser, destroyUser mutations and user, users queries.
|
15
15
|
# expects that UsersController class exist
|
16
16
|
resources :users
|
17
17
|
|
data/docs/index.html
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
<html lang="en">
|
3
3
|
<head>
|
4
4
|
<meta charset="UTF-8">
|
5
|
-
<title>
|
5
|
+
<title>GraphqlRails</title>
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
7
7
|
<meta name="description" content="Description">
|
8
8
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
@@ -16,7 +16,7 @@ end
|
|
16
16
|
|
17
17
|
## Executing grouped schema
|
18
18
|
|
19
|
-
If you have multiple schemas (read [routes section](
|
19
|
+
If you have multiple schemas (read [routes section](components/routes) on how to do that) and you want to render group specific schema, you need to provide group name, like this:
|
20
20
|
|
21
21
|
```ruby
|
22
22
|
class MyRailsClass < ApplicationController
|
@@ -8,7 +8,7 @@ rake graphql_rails:schema:dump
|
|
8
8
|
|
9
9
|
## Dumping non default schema
|
10
10
|
|
11
|
-
You can have multiple graphql schemas. Read more about this in [routes section](
|
11
|
+
You can have multiple graphql schemas. Read more about this in [routes section](components/routes). In order to generate schema for one of groups, provide optional `name` argument:
|
12
12
|
|
13
13
|
```bash
|
14
14
|
rake graphql_rails:schema:dump['your_group_name']
|
data/graphql_rails.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ['Povilas Jurčys']
|
10
10
|
spec.email = ['po.jurcys@gmail.com']
|
11
11
|
|
12
|
-
spec.summary = %q{
|
12
|
+
spec.summary = %q{Rails style structure for GraphQL API.}
|
13
13
|
spec.homepage = 'https://github.com/samesystem/graphql_rails'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
@@ -20,13 +20,13 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.add_dependency 'graphql', '>= 1.
|
23
|
+
spec.add_dependency 'graphql', '~> 1.12', '>= 1.12.4'
|
24
24
|
spec.add_dependency 'activesupport', '>= 4'
|
25
25
|
|
26
|
-
spec.add_development_dependency 'bundler', '~>
|
27
|
-
spec.add_development_dependency 'rake', '~>
|
26
|
+
spec.add_development_dependency 'bundler', '~> 2'
|
27
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
28
28
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
29
29
|
spec.add_development_dependency 'activerecord'
|
30
30
|
spec.add_development_dependency 'pry-byebug'
|
31
|
-
spec.add_development_dependency 'rails', '~>
|
31
|
+
spec.add_development_dependency 'rails', '~> 6'
|
32
32
|
end
|
@@ -3,16 +3,19 @@
|
|
3
3
|
require 'rails_helper'
|
4
4
|
|
5
5
|
RSpec.describe GraphqlRouter do
|
6
|
-
|
6
|
+
subject(:schema) { described_class.graphql_schema }
|
7
|
+
|
8
|
+
describe '#to_definition' do
|
9
|
+
subject(:to_definition) { schema.to_definition.strip }
|
10
|
+
|
11
|
+
let(:schema_dump_path) { Rails.root.join('spec', 'fixtures', 'graphql_schema.graphql') }
|
12
|
+
let(:previous_definition) { File.read(schema_dump_path).strip }
|
13
|
+
|
7
14
|
it 'returns correct structure' do
|
8
15
|
# if you need to update saved_schema, run rake task:
|
9
|
-
# $ RAILS_ENV=test rake graphql_rails:schema:dump
|
10
|
-
|
11
|
-
schema_path = Rails.root.join('spec', 'fixtures', 'graphql_schema.graphql')
|
12
|
-
saved_schema = File.read(schema_path).strip
|
13
|
-
real_schema = described_class.to_definition.strip
|
16
|
+
# $ RAILS_ENV=test bin/rake graphql_rails:schema:dump
|
14
17
|
|
15
|
-
expect(
|
18
|
+
expect(to_definition).to eq(previous_definition)
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -21,11 +21,9 @@ module GraphqlRails
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def required?
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@required
|
28
|
-
end
|
24
|
+
return @required unless @required.nil?
|
25
|
+
|
26
|
+
attribute_name_parser.required? || !initial_type.to_s[/!$/].nil? || initial_type.is_a?(GraphQL::Schema::NonNull)
|
29
27
|
end
|
30
28
|
|
31
29
|
def required
|
@@ -46,10 +44,8 @@ module GraphqlRails
|
|
46
44
|
!required?
|
47
45
|
end
|
48
46
|
|
49
|
-
|
50
|
-
|
51
|
-
def options
|
52
|
-
{}
|
47
|
+
def scalar_type?
|
48
|
+
type_parser.raw_graphql_type? || type_parser.core_scalar_type?
|
53
49
|
end
|
54
50
|
|
55
51
|
private
|
@@ -13,14 +13,17 @@ module GraphqlRails
|
|
13
13
|
|
14
14
|
attr_reader :attributes
|
15
15
|
|
16
|
-
|
16
|
+
# rubocop:disable Metrics/ParameterLists
|
17
|
+
def initialize(name, type = nil, description: nil, property: name, required: nil, options: {})
|
17
18
|
@initial_type = type
|
18
19
|
@initial_name = name
|
20
|
+
@options = options
|
19
21
|
@description = description
|
20
22
|
@property = property.to_s
|
21
23
|
@required = required
|
22
24
|
@attributes ||= {}
|
23
25
|
end
|
26
|
+
# rubocop:enable Metrics/ParameterLists
|
24
27
|
|
25
28
|
def type(new_type = nil)
|
26
29
|
return @initial_type if new_type.nil?
|
@@ -43,18 +46,29 @@ module GraphqlRails
|
|
43
46
|
self
|
44
47
|
end
|
45
48
|
|
49
|
+
def options(new_options = {})
|
50
|
+
return @options if new_options.blank?
|
51
|
+
|
52
|
+
@options = new_options
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
46
56
|
def field_args
|
47
57
|
[
|
48
58
|
field_name,
|
49
59
|
type_parser.type_arg,
|
50
|
-
*description
|
51
|
-
{
|
52
|
-
method: property.to_sym,
|
53
|
-
null: optional?
|
54
|
-
}
|
60
|
+
*description
|
55
61
|
]
|
56
62
|
end
|
57
63
|
|
64
|
+
def field_options
|
65
|
+
{
|
66
|
+
method: property.to_sym,
|
67
|
+
null: optional?,
|
68
|
+
camelize: camelize?
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
58
72
|
def argument_args
|
59
73
|
[
|
60
74
|
field_name,
|
@@ -69,6 +83,12 @@ module GraphqlRails
|
|
69
83
|
protected
|
70
84
|
|
71
85
|
attr_reader :initial_type, :initial_name
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def camelize?
|
90
|
+
options[:input_format] != :original && options[:attribute_name_format] != :original
|
91
|
+
end
|
72
92
|
end
|
73
93
|
end
|
74
94
|
end
|
@@ -27,11 +27,11 @@ module GraphqlRails
|
|
27
27
|
@graphql_type ||= \
|
28
28
|
case name
|
29
29
|
when 'id', /_id\Z/
|
30
|
-
GraphQL::
|
30
|
+
GraphQL::Types::ID
|
31
31
|
when /\?\Z/
|
32
|
-
GraphQL::
|
32
|
+
GraphQL::Types::Boolean
|
33
33
|
else
|
34
|
-
GraphQL::
|
34
|
+
GraphQL::Types::String
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -44,7 +44,7 @@ module GraphqlRails
|
|
44
44
|
attr_reader :options
|
45
45
|
|
46
46
|
def original_format?
|
47
|
-
options[:input_format] == :original
|
47
|
+
options[:input_format] == :original || options[:attribute_name_format] == :original
|
48
48
|
end
|
49
49
|
|
50
50
|
def preprocesed_name
|
@@ -24,7 +24,11 @@ module GraphqlRails
|
|
24
24
|
def input_argument_args
|
25
25
|
type = raw_input_type || input_type_parser.input_type_arg
|
26
26
|
|
27
|
-
[field_name, type
|
27
|
+
[field_name, type]
|
28
|
+
end
|
29
|
+
|
30
|
+
def input_argument_options
|
31
|
+
{ required: required?, description: description, camelize: false }
|
28
32
|
end
|
29
33
|
|
30
34
|
def paginated?
|
@@ -11,23 +11,23 @@ module GraphqlRails
|
|
11
11
|
class UnknownTypeError < ArgumentError; end
|
12
12
|
|
13
13
|
TYPE_MAPPING = {
|
14
|
-
'id' => GraphQL::
|
14
|
+
'id' => GraphQL::Types::ID,
|
15
15
|
|
16
|
-
'int' => GraphQL::
|
17
|
-
'integer' => GraphQL::
|
16
|
+
'int' => GraphQL::Types::Int,
|
17
|
+
'integer' => GraphQL::Types::Int,
|
18
18
|
|
19
|
-
'string' => GraphQL::
|
20
|
-
'str' => GraphQL::
|
21
|
-
'text' => GraphQL::
|
22
|
-
'time' => GraphQL::
|
23
|
-
'date' => GraphQL::
|
19
|
+
'string' => GraphQL::Types::String,
|
20
|
+
'str' => GraphQL::Types::String,
|
21
|
+
'text' => GraphQL::Types::String,
|
22
|
+
'time' => GraphQL::Types::String,
|
23
|
+
'date' => GraphQL::Types::String,
|
24
24
|
|
25
|
-
'bool' => GraphQL::
|
26
|
-
'boolean' => GraphQL::
|
25
|
+
'bool' => GraphQL::Types::Boolean,
|
26
|
+
'boolean' => GraphQL::Types::Boolean,
|
27
27
|
|
28
|
-
'float' => GraphQL::
|
29
|
-
'double' => GraphQL::
|
30
|
-
'decimal' => GraphQL::
|
28
|
+
'float' => GraphQL::Types::Float,
|
29
|
+
'double' => GraphQL::Types::Float,
|
30
|
+
'decimal' => GraphQL::Types::Float
|
31
31
|
}.freeze
|
32
32
|
|
33
33
|
WRAPPER_TYPES = [
|
@@ -57,6 +57,10 @@ module GraphqlRails
|
|
57
57
|
unparsed_type < GraphQL::Schema::Member
|
58
58
|
end
|
59
59
|
|
60
|
+
def core_scalar_type?
|
61
|
+
unwrapped_scalar_type.in?(TYPE_MAPPING.values)
|
62
|
+
end
|
63
|
+
|
60
64
|
def graphql_model
|
61
65
|
type_class = \
|
62
66
|
if unparsed_type.is_a?(Class) && unparsed_type < GraphqlRails::Model
|
@@ -7,8 +7,12 @@ module GraphqlRails
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
class_methods do
|
10
|
-
def call(*args, &block)
|
11
|
-
|
10
|
+
def call(*args, **kwargs, &block)
|
11
|
+
if kwargs.present?
|
12
|
+
new(*args, **kwargs).call(&block)
|
13
|
+
else
|
14
|
+
new(*args).call(&block)
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
@@ -18,16 +18,16 @@ module GraphqlRails
|
|
18
18
|
subclass.instance_variable_set(:@controller_configuration, new_config)
|
19
19
|
end
|
20
20
|
|
21
|
-
def before_action(*args, &block)
|
22
|
-
controller_configuration.add_action_hook(:before, *args, &block)
|
21
|
+
def before_action(*args, **kwargs, &block)
|
22
|
+
controller_configuration.add_action_hook(:before, *args, **kwargs, &block)
|
23
23
|
end
|
24
24
|
|
25
|
-
def around_action(*args, &block)
|
26
|
-
controller_configuration.add_action_hook(:around, *args, &block)
|
25
|
+
def around_action(*args, **kwargs, &block)
|
26
|
+
controller_configuration.add_action_hook(:around, *args, **kwargs, &block)
|
27
27
|
end
|
28
28
|
|
29
|
-
def after_action(*args, &block)
|
30
|
-
controller_configuration.add_action_hook(:after, *args, &block)
|
29
|
+
def after_action(*args, **kwargs, &block)
|
30
|
+
controller_configuration.add_action_hook(:after, *args, **kwargs, &block)
|
31
31
|
end
|
32
32
|
|
33
33
|
def action(action_name)
|