graphql_rails 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +45 -43
- data/README.md +2 -3
- data/docs/README.md +2 -3
- data/docs/components/controller.md +20 -0
- data/graphql_rails.gemspec +1 -1
- data/lib/graphql_rails.rb +1 -0
- data/lib/graphql_rails/attribute.rb +8 -36
- data/lib/graphql_rails/attribute/attributable.rb +58 -0
- data/lib/graphql_rails/attribute/attribute_name_parser.rb +46 -0
- data/lib/graphql_rails/attribute/type_parser.rb +115 -0
- data/lib/graphql_rails/controller/action.rb +2 -0
- data/lib/graphql_rails/controller/action_configuration.rb +4 -3
- data/lib/graphql_rails/controller/controller_function.rb +1 -1
- data/lib/graphql_rails/errors/validation_error.rb +1 -1
- data/lib/graphql_rails/model.rb +2 -2
- data/lib/graphql_rails/model/configurable.rb +23 -0
- data/lib/graphql_rails/model/configuration.rb +20 -15
- data/lib/graphql_rails/model/graphql_input_type_builder.rb +33 -0
- data/lib/graphql_rails/model/graphql_type_builder.rb +1 -1
- data/lib/graphql_rails/model/input.rb +44 -0
- data/lib/graphql_rails/model/input_attribute.rb +46 -0
- data/lib/graphql_rails/router/route.rb +1 -0
- data/lib/graphql_rails/version.rb +1 -1
- metadata +11 -4
- data/lib/graphql_rails/type_parser.rb +0 -111
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f314505789425775da7e899dd4d30bbc6558da828af5b3f617a84d42eb8f4933
|
4
|
+
data.tar.gz: 9afab45a8f249aadf6540715514d2f7e21a713290fa7f753fc1933bc574cb18a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c5709a879b830f8beeccfd391ec0f4f7de83cc3af0d4a37880f3051ab00d2d06fc88794087c5b0f8a18331c5d059caca389894cdc36c722e11d4393546fb289
|
7
|
+
data.tar.gz: 9df5208778bfbe2a47c8e652ec2b5442747e51a5e5c4a315fbada63c92248d96d37a85d4598ec8210b5c2e8cc34e8df2f7731faf988ceefb6c91c499da38a68b
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
## [Unreleased]
|
2
|
+
|
3
|
+
* Your contribution here.
|
4
|
+
|
5
|
+
## 0.5.0 (2019-04-03)
|
6
|
+
|
7
|
+
* [#56](https://github.com/ashkan18/graphlient/pull/56) Added GraphQL input type generators [@povilasjurcys](https://github.com/povilasjurcys).
|
8
|
+
* Added CHANGELOG [@povilasjurcys](https://github.com/povilasjurcys).
|
9
|
+
* Fixed GraphQL word typos in documentation and code [@povilasjurcys](https://github.com/povilasjurcys).
|
data/Gemfile.lock
CHANGED
@@ -1,82 +1,84 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
graphql_rails (0.
|
4
|
+
graphql_rails (0.5.0)
|
5
5
|
activesupport (>= 4)
|
6
6
|
graphql (~> 1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activemodel (5.2.
|
12
|
-
activesupport (= 5.2.
|
13
|
-
activerecord (5.2.
|
14
|
-
activemodel (= 5.2.
|
15
|
-
activesupport (= 5.2.
|
11
|
+
activemodel (5.2.2.1)
|
12
|
+
activesupport (= 5.2.2.1)
|
13
|
+
activerecord (5.2.2.1)
|
14
|
+
activemodel (= 5.2.2.1)
|
15
|
+
activesupport (= 5.2.2.1)
|
16
16
|
arel (>= 9.0)
|
17
|
-
activesupport (5.2.
|
17
|
+
activesupport (5.2.2.1)
|
18
18
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
19
19
|
i18n (>= 0.7, < 2)
|
20
20
|
minitest (~> 5.1)
|
21
21
|
tzinfo (~> 1.1)
|
22
22
|
arel (9.0.0)
|
23
23
|
ast (2.4.0)
|
24
|
-
bson (4.
|
25
|
-
byebug (
|
26
|
-
codecov (0.1.
|
24
|
+
bson (4.4.2)
|
25
|
+
byebug (11.0.1)
|
26
|
+
codecov (0.1.14)
|
27
27
|
json
|
28
28
|
simplecov
|
29
29
|
url
|
30
30
|
coderay (1.1.2)
|
31
|
-
concurrent-ruby (1.
|
31
|
+
concurrent-ruby (1.1.5)
|
32
32
|
diff-lcs (1.3)
|
33
|
-
docile (1.3.
|
33
|
+
docile (1.3.1)
|
34
34
|
graphql (1.9.3)
|
35
|
-
i18n (1.0
|
35
|
+
i18n (1.6.0)
|
36
36
|
concurrent-ruby (~> 1.0)
|
37
|
-
|
38
|
-
|
37
|
+
jaro_winkler (1.5.2)
|
38
|
+
json (2.2.0)
|
39
|
+
method_source (0.9.2)
|
39
40
|
minitest (5.11.3)
|
40
|
-
mongo (2.
|
41
|
-
bson (>= 4.
|
42
|
-
mongoid (7.0.
|
41
|
+
mongo (2.8.0)
|
42
|
+
bson (>= 4.4.2, < 5.0.0)
|
43
|
+
mongoid (7.0.2)
|
43
44
|
activemodel (>= 5.1, < 6.0.0)
|
44
45
|
mongo (>= 2.5.1, < 3.0.0)
|
45
|
-
parallel (1.
|
46
|
-
parser (2.
|
46
|
+
parallel (1.16.0)
|
47
|
+
parser (2.6.2.0)
|
47
48
|
ast (~> 2.4.0)
|
48
|
-
|
49
|
-
pry (0.11.3)
|
49
|
+
pry (0.12.2)
|
50
50
|
coderay (~> 1.1.0)
|
51
51
|
method_source (~> 0.9.0)
|
52
|
-
pry-byebug (3.
|
53
|
-
byebug (~>
|
52
|
+
pry-byebug (3.7.0)
|
53
|
+
byebug (~> 11.0)
|
54
54
|
pry (~> 0.10)
|
55
|
+
psych (3.1.0)
|
55
56
|
rainbow (3.0.0)
|
56
57
|
rake (10.5.0)
|
57
|
-
rspec (3.
|
58
|
-
rspec-core (~> 3.
|
59
|
-
rspec-expectations (~> 3.
|
60
|
-
rspec-mocks (~> 3.
|
61
|
-
rspec-core (3.
|
62
|
-
rspec-support (~> 3.
|
63
|
-
rspec-expectations (3.
|
58
|
+
rspec (3.8.0)
|
59
|
+
rspec-core (~> 3.8.0)
|
60
|
+
rspec-expectations (~> 3.8.0)
|
61
|
+
rspec-mocks (~> 3.8.0)
|
62
|
+
rspec-core (3.8.0)
|
63
|
+
rspec-support (~> 3.8.0)
|
64
|
+
rspec-expectations (3.8.2)
|
64
65
|
diff-lcs (>= 1.2.0, < 2.0)
|
65
|
-
rspec-support (~> 3.
|
66
|
-
rspec-mocks (3.
|
66
|
+
rspec-support (~> 3.8.0)
|
67
|
+
rspec-mocks (3.8.0)
|
67
68
|
diff-lcs (>= 1.2.0, < 2.0)
|
68
|
-
rspec-support (~> 3.
|
69
|
-
rspec-support (3.
|
70
|
-
rubocop (0.
|
69
|
+
rspec-support (~> 3.8.0)
|
70
|
+
rspec-support (3.8.0)
|
71
|
+
rubocop (0.66.0)
|
72
|
+
jaro_winkler (~> 1.5.1)
|
71
73
|
parallel (~> 1.10)
|
72
|
-
parser (>= 2.5)
|
73
|
-
|
74
|
+
parser (>= 2.5, != 2.5.1.1)
|
75
|
+
psych (>= 3.1.0)
|
74
76
|
rainbow (>= 2.2.2, < 4.0)
|
75
77
|
ruby-progressbar (~> 1.7)
|
76
|
-
unicode-display_width (
|
77
|
-
rubocop-rspec (1.
|
78
|
-
rubocop (>= 0.
|
79
|
-
ruby-progressbar (1.
|
78
|
+
unicode-display_width (>= 1.4.0, < 1.6)
|
79
|
+
rubocop-rspec (1.32.0)
|
80
|
+
rubocop (>= 0.60.0)
|
81
|
+
ruby-progressbar (1.10.0)
|
80
82
|
simplecov (0.16.1)
|
81
83
|
docile (~> 1.1)
|
82
84
|
json (>= 1.8, < 3)
|
@@ -85,7 +87,7 @@ GEM
|
|
85
87
|
thread_safe (0.3.6)
|
86
88
|
tzinfo (1.2.5)
|
87
89
|
thread_safe (~> 0.1)
|
88
|
-
unicode-display_width (1.
|
90
|
+
unicode-display_width (1.5.0)
|
89
91
|
url (0.3.2)
|
90
92
|
|
91
93
|
PLATFORMS
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[![codecov](https://codecov.io/gh/samesystem/graphql_rails/branch/master/graph/badge.svg)](https://codecov.io/gh/samesystem/graphql_rails)
|
5
5
|
[![Documentation](https://readthedocs.org/projects/ansicolortags/badge/?version=latest)](https://samesystem.github.io/graphql_rails)
|
6
6
|
|
7
|
-
Rails style structure for
|
7
|
+
Rails style structure for GraphQL API.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -104,7 +104,7 @@ MyGraphqlSchema = GraphqlRails::Router.draw do
|
|
104
104
|
end
|
105
105
|
```
|
106
106
|
|
107
|
-
## Testing your
|
107
|
+
## Testing your GraphqlRails::Controller in RSpec
|
108
108
|
|
109
109
|
### Setup
|
110
110
|
|
@@ -175,7 +175,6 @@ end
|
|
175
175
|
|
176
176
|
Check https://samesystem.github.io/graphql_rails for more details
|
177
177
|
|
178
|
-
|
179
178
|
## Development
|
180
179
|
|
181
180
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/docs/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# GraphqlRails
|
2
2
|
|
3
|
-
|
4
|
-
Rails style structure for GrapQL API.
|
3
|
+
Rails style structure for GraphQL API.
|
5
4
|
|
6
5
|
## Installation
|
7
6
|
|
@@ -101,7 +100,7 @@ MyGraphqlSchema = GraphqlRails::Router.draw do
|
|
101
100
|
end
|
102
101
|
```
|
103
102
|
|
104
|
-
## Testing your
|
103
|
+
## Testing your GraphqlRails::Controller in RSpec
|
105
104
|
|
106
105
|
### Setup
|
107
106
|
|
@@ -46,6 +46,26 @@ class UsersController < GraphqlRails::Controller
|
|
46
46
|
end
|
47
47
|
```
|
48
48
|
|
49
|
+
If your model has defined input, then you can provide your model as input type, like this:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class User
|
53
|
+
graphql.input do
|
54
|
+
c.attribute :name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class UsersController < GraphqlRails::Controller
|
59
|
+
action(:create).permit(create_params: 'User')
|
60
|
+
# this is equivalent to:
|
61
|
+
# `action(:create).permit(create_params: User.graphql.input)`
|
62
|
+
|
63
|
+
def create
|
64
|
+
User.create(params[:create_params])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
49
69
|
### *can_return_nil*
|
50
70
|
|
51
71
|
By default it is expected that each controller action returns model or array of models. `nil` is not allowed. You can change that by adding `can_return_nil` like this:
|
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{GraphQL server and client for rails}
|
13
13
|
spec.homepage = 'https://github.com/povilasjurcys/graphql_rails'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
data/lib/graphql_rails.rb
CHANGED
@@ -1,56 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'graphql'
|
4
|
-
require 'graphql_rails/
|
4
|
+
require 'graphql_rails/attribute/attributable'
|
5
5
|
|
6
6
|
module GraphqlRails
|
7
7
|
# contains info about single graphql attribute
|
8
8
|
class Attribute
|
9
|
-
|
9
|
+
include Attributable
|
10
|
+
|
11
|
+
attr_reader :property, :description
|
10
12
|
|
11
13
|
def initialize(name, type = nil, description: nil, property: name)
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@type_name = type.to_s
|
15
|
-
@graphql_field_type = parse_type(type || type_by_attribute_name)
|
14
|
+
@initial_type = type
|
15
|
+
@initial_name = name
|
16
16
|
@description = description
|
17
17
|
@property = property.to_s
|
18
18
|
end
|
19
19
|
|
20
|
-
def field_name
|
21
|
-
field =
|
22
|
-
if name.end_with?('?')
|
23
|
-
"is_#{name.remove(/\?\Z/)}"
|
24
|
-
else
|
25
|
-
name
|
26
|
-
end
|
27
|
-
|
28
|
-
field.camelize(:lower)
|
29
|
-
end
|
30
|
-
|
31
20
|
def field_args
|
32
21
|
[field_name, graphql_field_type, { property: property.to_sym, description: description }]
|
33
22
|
end
|
34
23
|
|
35
|
-
|
36
|
-
|
37
|
-
attr_reader :original_name
|
24
|
+
protected
|
38
25
|
|
39
|
-
|
40
|
-
case name
|
41
|
-
when 'id', /_id\Z/
|
42
|
-
GraphQL::ID_TYPE
|
43
|
-
when /\?\Z/
|
44
|
-
GraphQL::BOOLEAN_TYPE
|
45
|
-
else
|
46
|
-
GraphQL::STRING_TYPE
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def parse_type(type)
|
51
|
-
type = TypeParser.new(type).graphql_type
|
52
|
-
|
53
|
-
original_name['!'] ? type.to_non_null_type : type
|
54
|
-
end
|
26
|
+
attr_reader :initial_type, :initial_name
|
55
27
|
end
|
56
28
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql_rails/attribute/type_parser'
|
4
|
+
require 'graphql_rails/attribute/attribute_name_parser'
|
5
|
+
|
6
|
+
module GraphqlRails
|
7
|
+
class Attribute
|
8
|
+
# contains methods which are shared between various attribute-like classes
|
9
|
+
# expects `initial_name` and `initial_type` to be defined
|
10
|
+
module Attributable
|
11
|
+
def field_name
|
12
|
+
attribute_name_parser.field_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def type_name
|
16
|
+
@type_name ||= initial_type.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
attribute_name_parser.name
|
21
|
+
end
|
22
|
+
|
23
|
+
def required?
|
24
|
+
attribute_name_parser.required? || !initial_type.to_s[/!$/].nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def graphql_model
|
28
|
+
type_parser.graphql_model
|
29
|
+
end
|
30
|
+
|
31
|
+
def graphql_field_type
|
32
|
+
@graphql_field_type ||= \
|
33
|
+
if required?
|
34
|
+
nullable_type.to_non_null_type
|
35
|
+
else
|
36
|
+
nullable_type
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def nullable_type
|
43
|
+
type = type_parser.graphql_type
|
44
|
+
type.non_null? ? type.of_type : type
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def type_parser
|
50
|
+
@type_parser ||= TypeParser.new(initial_type || attribute_name_parser.graphql_type)
|
51
|
+
end
|
52
|
+
|
53
|
+
def attribute_name_parser
|
54
|
+
@attribute_name_parser ||= AttributeNameParser.new(initial_name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphqlRails
|
4
|
+
class Attribute
|
5
|
+
# Parses attribute name and can generates graphql scalar type,
|
6
|
+
# grapqhl name and etc. based on that
|
7
|
+
class AttributeNameParser
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize(original_name)
|
11
|
+
name = original_name.to_s
|
12
|
+
@required = !name['!'].nil?
|
13
|
+
@name = name.tr('!', '')
|
14
|
+
end
|
15
|
+
|
16
|
+
def field_name
|
17
|
+
@field_name ||= begin
|
18
|
+
field =
|
19
|
+
if name.end_with?('?')
|
20
|
+
"is_#{name.remove(/\?\Z/)}"
|
21
|
+
else
|
22
|
+
name
|
23
|
+
end
|
24
|
+
|
25
|
+
field.camelize(:lower)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def graphql_type
|
30
|
+
@graphql_type ||= \
|
31
|
+
case name
|
32
|
+
when 'id', /_id\Z/
|
33
|
+
GraphQL::ID_TYPE
|
34
|
+
when /\?\Z/
|
35
|
+
GraphQL::BOOLEAN_TYPE
|
36
|
+
else
|
37
|
+
GraphQL::STRING_TYPE
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def required?
|
42
|
+
@required
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql'
|
4
|
+
|
5
|
+
module GraphqlRails
|
6
|
+
class Attribute
|
7
|
+
# converts string value in to GraphQL type
|
8
|
+
class TypeParser
|
9
|
+
class UnknownTypeError < ArgumentError; end
|
10
|
+
|
11
|
+
TYPE_MAPPING = {
|
12
|
+
'id' => GraphQL::ID_TYPE,
|
13
|
+
|
14
|
+
'int' => GraphQL::INT_TYPE,
|
15
|
+
'integer' => GraphQL::INT_TYPE,
|
16
|
+
|
17
|
+
'string' => GraphQL::STRING_TYPE,
|
18
|
+
'str' => GraphQL::STRING_TYPE,
|
19
|
+
'text' => GraphQL::STRING_TYPE,
|
20
|
+
'time' => GraphQL::STRING_TYPE,
|
21
|
+
'date' => GraphQL::STRING_TYPE,
|
22
|
+
|
23
|
+
'bool' => GraphQL::BOOLEAN_TYPE,
|
24
|
+
'boolean' => GraphQL::BOOLEAN_TYPE,
|
25
|
+
|
26
|
+
'float' => GraphQL::FLOAT_TYPE,
|
27
|
+
'double' => GraphQL::FLOAT_TYPE,
|
28
|
+
'decimal' => GraphQL::FLOAT_TYPE
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
def initialize(unparsed_type)
|
32
|
+
@unparsed_type = unparsed_type
|
33
|
+
end
|
34
|
+
|
35
|
+
def graphql_type
|
36
|
+
return unparsed_type if raw_graphql_type?
|
37
|
+
|
38
|
+
if list?
|
39
|
+
parsed_list_type
|
40
|
+
else
|
41
|
+
parsed_inner_type
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def graphql_model
|
46
|
+
type_class = inner_type_name.safe_constantize
|
47
|
+
return unless type_class.respond_to?(:graphql)
|
48
|
+
|
49
|
+
type_class
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_reader :unparsed_type
|
55
|
+
|
56
|
+
def parsed_list_type
|
57
|
+
list_type = parsed_inner_type.to_list_type
|
58
|
+
|
59
|
+
if required_list_type?
|
60
|
+
list_type.to_non_null_type
|
61
|
+
else
|
62
|
+
list_type
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def parsed_inner_type
|
67
|
+
if required_inner_type?
|
68
|
+
type_by_name.to_non_null_type
|
69
|
+
else
|
70
|
+
type_by_name
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def required_inner_type?
|
75
|
+
!!unparsed_type[/\w!/] # rubocop:disable Style/DoubleNegation
|
76
|
+
end
|
77
|
+
|
78
|
+
def list?
|
79
|
+
unparsed_type.to_s.include?(']')
|
80
|
+
end
|
81
|
+
|
82
|
+
def required_list_type?
|
83
|
+
unparsed_type.to_s.include?(']!')
|
84
|
+
end
|
85
|
+
|
86
|
+
def raw_graphql_type?
|
87
|
+
unparsed_type.is_a?(GraphQL::BaseType) ||
|
88
|
+
unparsed_type.is_a?(GraphQL::ObjectType) ||
|
89
|
+
unparsed_type.is_a?(GraphQL::InputObjectType) ||
|
90
|
+
(defined?(GraphQL::Schema::Member) && unparsed_type.is_a?(Class) && unparsed_type < GraphQL::Schema::Member)
|
91
|
+
end
|
92
|
+
|
93
|
+
def inner_type_name
|
94
|
+
unparsed_type.to_s.tr('[]!', '')
|
95
|
+
end
|
96
|
+
|
97
|
+
def type_by_name
|
98
|
+
TYPE_MAPPING.fetch(inner_type_name.downcase) do
|
99
|
+
dynamicly_defined_type || raise(
|
100
|
+
UnknownTypeError,
|
101
|
+
"Type #{unparsed_type.inspect} is not supported. Supported scalar types are: #{TYPE_MAPPING.keys}." \
|
102
|
+
' All the classes that includes `GraphqlRails::Model` are also supported as types.'
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def dynamicly_defined_type
|
108
|
+
type_class = graphql_model
|
109
|
+
return unless type_class
|
110
|
+
|
111
|
+
type_class.graphql.graphql_type
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -60,6 +60,7 @@ module GraphqlRails
|
|
60
60
|
|
61
61
|
def default_type
|
62
62
|
return default_collection_type if route.collection?
|
63
|
+
|
63
64
|
default_inner_return_type
|
64
65
|
end
|
65
66
|
|
@@ -104,6 +105,7 @@ module GraphqlRails
|
|
104
105
|
[namespace, model_name].join('::').constantize
|
105
106
|
rescue NameError => err
|
106
107
|
raise unless err.message.match?(/uninitialized constant/)
|
108
|
+
|
107
109
|
nil
|
108
110
|
end
|
109
111
|
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'active_support/core_ext/string/filters'
|
4
|
-
require 'graphql_rails/type_parser'
|
4
|
+
require 'graphql_rails/attribute/type_parser'
|
5
5
|
require 'graphql_rails/attribute'
|
6
|
+
require 'graphql_rails/model/input_attribute'
|
6
7
|
|
7
8
|
module GraphqlRails
|
8
9
|
class Controller
|
@@ -79,12 +80,12 @@ module GraphqlRails
|
|
79
80
|
end
|
80
81
|
|
81
82
|
def type_parser
|
82
|
-
TypeParser.new(custom_return_type)
|
83
|
+
GraphqlRails::Attribute::TypeParser.new(custom_return_type)
|
83
84
|
end
|
84
85
|
|
85
86
|
def permit_attribute(name, type = nil)
|
86
87
|
field_name = name.to_s.remove(/!\Z/)
|
87
|
-
attributes[field_name] =
|
88
|
+
attributes[field_name] = Model::InputAttribute.new(name.to_s, type)
|
88
89
|
end
|
89
90
|
end
|
90
91
|
end
|
data/lib/graphql_rails/model.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'graphql_rails/model/configuration'
|
4
4
|
|
5
5
|
module GraphqlRails
|
6
|
-
# this module allows to convert any ruby class in to
|
6
|
+
# this module allows to convert any ruby class in to graphql type object
|
7
7
|
#
|
8
8
|
# usage:
|
9
9
|
# class YourModel
|
@@ -15,7 +15,7 @@ module GraphqlRails
|
|
15
15
|
# end
|
16
16
|
# end
|
17
17
|
#
|
18
|
-
# YourModel.new.
|
18
|
+
# YourModel.new.graphql_type # => type with [:id, :title] attributes
|
19
19
|
module Model
|
20
20
|
def self.included(base)
|
21
21
|
base.extend(ClassMethods)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphqlRails
|
4
|
+
module Model
|
5
|
+
# contains methods which are shared between various configurations
|
6
|
+
# expects `default_name` to be defined
|
7
|
+
module Configurable
|
8
|
+
def attributes
|
9
|
+
@attributes ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def name(type_name = nil)
|
13
|
+
@name = type_name if type_name
|
14
|
+
@name || default_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def description(new_description = nil)
|
18
|
+
@description = new_description if new_description
|
19
|
+
@description
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'graphql_rails/attribute'
|
4
4
|
require 'graphql_rails/model/graphql_type_builder'
|
5
|
+
require 'graphql_rails/model/input'
|
6
|
+
require 'graphql_rails/model/configurable'
|
5
7
|
|
6
8
|
module GraphqlRails
|
7
9
|
module Model
|
8
10
|
# stores information about model specific config, like attributes and types
|
9
11
|
class Configuration
|
10
|
-
|
12
|
+
include Configurable
|
11
13
|
|
12
14
|
COUNT_TOTAL_ITEMS = lambda do |obj, _args, _ctx|
|
13
15
|
obj_nodes = obj.nodes
|
@@ -17,17 +19,6 @@ module GraphqlRails
|
|
17
19
|
|
18
20
|
def initialize(model_class)
|
19
21
|
@model_class = model_class
|
20
|
-
@attributes = {}
|
21
|
-
end
|
22
|
-
|
23
|
-
def name(type_name = nil)
|
24
|
-
@name = type_name if type_name
|
25
|
-
@name || name_by_class_name
|
26
|
-
end
|
27
|
-
|
28
|
-
def description(new_description = nil)
|
29
|
-
@description = new_description if new_description
|
30
|
-
@description
|
31
22
|
end
|
32
23
|
|
33
24
|
def attribute(attribute_name, type: nil, **attribute_options)
|
@@ -39,8 +30,22 @@ module GraphqlRails
|
|
39
30
|
)
|
40
31
|
end
|
41
32
|
|
33
|
+
def input(input_name = nil)
|
34
|
+
@input ||= {}
|
35
|
+
name = input_name.to_s
|
36
|
+
|
37
|
+
if block_given?
|
38
|
+
@input[name] ||= Model::Input.new(model_class, input_name)
|
39
|
+
yield(@input[name])
|
40
|
+
end
|
41
|
+
|
42
|
+
@input.fetch(name) do
|
43
|
+
raise("GraphQL input with name #{input_name.inspect} is not defined for #{model_class}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
42
47
|
def graphql_type
|
43
|
-
@graphql_type ||=
|
48
|
+
@graphql_type ||= GraphqlTypeBuilder.new(
|
44
49
|
name: name, description: description, attributes: attributes
|
45
50
|
).call
|
46
51
|
end
|
@@ -57,8 +62,8 @@ module GraphqlRails
|
|
57
62
|
|
58
63
|
attr_reader :model_class
|
59
64
|
|
60
|
-
def
|
61
|
-
@
|
65
|
+
def default_name
|
66
|
+
@default_name ||= model_class.name.split('::').last
|
62
67
|
end
|
63
68
|
end
|
64
69
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphqlRails
|
4
|
+
module Model
|
5
|
+
# stores information about model specific config, like attributes and types
|
6
|
+
class GraphqlInputTypeBuilder
|
7
|
+
def initialize(name:, description: nil, attributes:)
|
8
|
+
@name = name
|
9
|
+
@attributes = attributes
|
10
|
+
@description = description
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
type_name = name
|
15
|
+
type_description = description
|
16
|
+
type_attributes = attributes
|
17
|
+
|
18
|
+
Class.new(GraphQL::Schema::InputObject) do
|
19
|
+
graphql_name(type_name)
|
20
|
+
description(type_description)
|
21
|
+
|
22
|
+
type_attributes.each_value do |type_attribute|
|
23
|
+
argument(*type_attribute.input_argument_args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :model_configuration, :attributes, :name, :description
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql_rails/model/graphql_input_type_builder'
|
4
|
+
require 'graphql_rails/model/configurable'
|
5
|
+
|
6
|
+
module GraphqlRails
|
7
|
+
module Model
|
8
|
+
# stores information about model input specific config, like attributes and types
|
9
|
+
class Input
|
10
|
+
include Configurable
|
11
|
+
|
12
|
+
def initialize(model_class, input_name_suffix)
|
13
|
+
@model_class = model_class
|
14
|
+
@input_name_suffix = input_name_suffix
|
15
|
+
end
|
16
|
+
|
17
|
+
def graphql_input_type
|
18
|
+
@graphql_input_type ||= GraphqlInputTypeBuilder.new(
|
19
|
+
name: name, description: description, attributes: attributes
|
20
|
+
).call
|
21
|
+
end
|
22
|
+
|
23
|
+
def attribute(attribute_name, type: nil, **attribute_options)
|
24
|
+
attributes[attribute_name.to_s] = \
|
25
|
+
InputAttribute.new(
|
26
|
+
attribute_name,
|
27
|
+
type,
|
28
|
+
attribute_options
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
attr_reader :input_name_suffix, :model_class
|
35
|
+
|
36
|
+
def default_name
|
37
|
+
@default_name ||= begin
|
38
|
+
suffix = input_name_suffix ? input_name_suffix.to_s.tableize : ''
|
39
|
+
"#{model_class.name.split('::').last}#{suffix}Input"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphqlRails
|
4
|
+
module Model
|
5
|
+
# contains info about single graphql input attribute
|
6
|
+
class InputAttribute
|
7
|
+
include GraphqlRails::Attribute::Attributable
|
8
|
+
|
9
|
+
attr_reader :description
|
10
|
+
|
11
|
+
def initialize(name, type = nil, description: nil)
|
12
|
+
@initial_name = name
|
13
|
+
@initial_type = type
|
14
|
+
@description = description
|
15
|
+
end
|
16
|
+
|
17
|
+
def function_argument_args
|
18
|
+
[field_name, graphql_input_type, { description: description }]
|
19
|
+
end
|
20
|
+
|
21
|
+
def input_argument_args
|
22
|
+
type = raw_input_type || model_input_type || nullable_type
|
23
|
+
[field_name, type, { required: required?, description: description }]
|
24
|
+
end
|
25
|
+
|
26
|
+
def graphql_input_type
|
27
|
+
raw_input_type || model_input_type || graphql_field_type
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :initial_name, :initial_type
|
33
|
+
|
34
|
+
def raw_input_type
|
35
|
+
return initial_type if initial_type.is_a?(GraphQL::InputObjectType)
|
36
|
+
return initial_type.graphql_input_type if initial_type.is_a?(Model::Input)
|
37
|
+
end
|
38
|
+
|
39
|
+
def model_input_type
|
40
|
+
return unless graphql_model
|
41
|
+
|
42
|
+
graphql_model.graphql.input.graphql_input_type
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Povilas Jurčys
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03
|
11
|
+
date: 2019-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- ".rubocop.yml"
|
108
108
|
- ".ruby-version"
|
109
109
|
- ".travis.yml"
|
110
|
+
- CHANGELOG.md
|
110
111
|
- CODE_OF_CONDUCT.md
|
111
112
|
- Gemfile
|
112
113
|
- Gemfile.lock
|
@@ -128,6 +129,9 @@ files:
|
|
128
129
|
- graphql_rails.gemspec
|
129
130
|
- lib/graphql_rails.rb
|
130
131
|
- lib/graphql_rails/attribute.rb
|
132
|
+
- lib/graphql_rails/attribute/attributable.rb
|
133
|
+
- lib/graphql_rails/attribute/attribute_name_parser.rb
|
134
|
+
- lib/graphql_rails/attribute/type_parser.rb
|
131
135
|
- lib/graphql_rails/controller.rb
|
132
136
|
- lib/graphql_rails/controller/action.rb
|
133
137
|
- lib/graphql_rails/controller/action_configuration.rb
|
@@ -141,8 +145,12 @@ files:
|
|
141
145
|
- lib/graphql_rails/errors/execution_error.rb
|
142
146
|
- lib/graphql_rails/errors/validation_error.rb
|
143
147
|
- lib/graphql_rails/model.rb
|
148
|
+
- lib/graphql_rails/model/configurable.rb
|
144
149
|
- lib/graphql_rails/model/configuration.rb
|
150
|
+
- lib/graphql_rails/model/graphql_input_type_builder.rb
|
145
151
|
- lib/graphql_rails/model/graphql_type_builder.rb
|
152
|
+
- lib/graphql_rails/model/input.rb
|
153
|
+
- lib/graphql_rails/model/input_attribute.rb
|
146
154
|
- lib/graphql_rails/router.rb
|
147
155
|
- lib/graphql_rails/router/mutation_route.rb
|
148
156
|
- lib/graphql_rails/router/query_route.rb
|
@@ -150,7 +158,6 @@ files:
|
|
150
158
|
- lib/graphql_rails/router/route.rb
|
151
159
|
- lib/graphql_rails/router/schema_builder.rb
|
152
160
|
- lib/graphql_rails/rspec_controller_helpers.rb
|
153
|
-
- lib/graphql_rails/type_parser.rb
|
154
161
|
- lib/graphql_rails/version.rb
|
155
162
|
homepage: https://github.com/povilasjurcys/graphql_rails
|
156
163
|
licenses:
|
@@ -175,5 +182,5 @@ rubyforge_project:
|
|
175
182
|
rubygems_version: 2.7.7
|
176
183
|
signing_key:
|
177
184
|
specification_version: 4
|
178
|
-
summary:
|
185
|
+
summary: GraphQL server and client for rails
|
179
186
|
test_files: []
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'graphql'
|
4
|
-
|
5
|
-
module GraphqlRails
|
6
|
-
# converts string value in to GraphQL type
|
7
|
-
class TypeParser
|
8
|
-
class UnknownTypeError < ArgumentError; end
|
9
|
-
|
10
|
-
TYPE_MAPPING = {
|
11
|
-
'id' => GraphQL::ID_TYPE,
|
12
|
-
|
13
|
-
'int' => GraphQL::INT_TYPE,
|
14
|
-
'integer' => GraphQL::INT_TYPE,
|
15
|
-
|
16
|
-
'string' => GraphQL::STRING_TYPE,
|
17
|
-
'str' => GraphQL::STRING_TYPE,
|
18
|
-
'text' => GraphQL::STRING_TYPE,
|
19
|
-
'time' => GraphQL::STRING_TYPE,
|
20
|
-
'date' => GraphQL::STRING_TYPE,
|
21
|
-
|
22
|
-
'bool' => GraphQL::BOOLEAN_TYPE,
|
23
|
-
'boolean' => GraphQL::BOOLEAN_TYPE,
|
24
|
-
|
25
|
-
'float' => GraphQL::FLOAT_TYPE,
|
26
|
-
'double' => GraphQL::FLOAT_TYPE,
|
27
|
-
'decimal' => GraphQL::FLOAT_TYPE
|
28
|
-
}.freeze
|
29
|
-
|
30
|
-
def initialize(unparsed_type)
|
31
|
-
@unparsed_type = unparsed_type
|
32
|
-
end
|
33
|
-
|
34
|
-
def graphql_type
|
35
|
-
return unparsed_type if raw_graphql_type?
|
36
|
-
|
37
|
-
if list?
|
38
|
-
parsed_list_type
|
39
|
-
else
|
40
|
-
parsed_inner_type
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def graphql_model
|
45
|
-
type_class = inner_type_name.safe_constantize
|
46
|
-
return unless type_class.respond_to?(:graphql)
|
47
|
-
type_class
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
attr_reader :unparsed_type
|
53
|
-
|
54
|
-
def parsed_list_type
|
55
|
-
list_type = parsed_inner_type.to_list_type
|
56
|
-
|
57
|
-
if required_list_type?
|
58
|
-
list_type.to_non_null_type
|
59
|
-
else
|
60
|
-
list_type
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def parsed_inner_type
|
65
|
-
if required_inner_type?
|
66
|
-
type_by_name.to_non_null_type
|
67
|
-
else
|
68
|
-
type_by_name
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def required_inner_type?
|
73
|
-
!!unparsed_type[/\w!/] # rubocop:disable Style/DoubleNegation
|
74
|
-
end
|
75
|
-
|
76
|
-
def list?
|
77
|
-
unparsed_type.to_s.include?(']')
|
78
|
-
end
|
79
|
-
|
80
|
-
def required_list_type?
|
81
|
-
unparsed_type.to_s.include?(']!')
|
82
|
-
end
|
83
|
-
|
84
|
-
def raw_graphql_type?
|
85
|
-
unparsed_type.is_a?(GraphQL::BaseType) ||
|
86
|
-
unparsed_type.is_a?(GraphQL::ObjectType) ||
|
87
|
-
(defined?(GraphQL::Schema::Member) && unparsed_type.is_a?(Class) && unparsed_type < GraphQL::Schema::Member)
|
88
|
-
end
|
89
|
-
|
90
|
-
def inner_type_name
|
91
|
-
unparsed_type.to_s.tr('[]!', '')
|
92
|
-
end
|
93
|
-
|
94
|
-
def type_by_name
|
95
|
-
TYPE_MAPPING.fetch(inner_type_name.downcase) do
|
96
|
-
dynamicly_defined_type || raise(
|
97
|
-
UnknownTypeError,
|
98
|
-
"Type #{unparsed_type.inspect} is not supported. Supported scalar types are: #{TYPE_MAPPING.keys}." \
|
99
|
-
' All the classes that includes `GraphqlRails::Model` are also supported as types.'
|
100
|
-
)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def dynamicly_defined_type
|
105
|
-
type_class = graphql_model
|
106
|
-
return unless type_class
|
107
|
-
|
108
|
-
type_class.graphql.graphql_type
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|