graphql_rails 0.4.3 → 0.5.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 +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
|
[](https://codecov.io/gh/samesystem/graphql_rails)
|
|
5
5
|
[](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
|