graphql-rails-generators 1.1.0 → 1.1.1
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/README.md +83 -9
- data/lib/generators/gql/gql_generator_base.rb +62 -31
- data/lib/generators/gql/input_generator.rb +19 -5
- data/lib/generators/gql/model_search_base_generator.rb +9 -0
- data/lib/generators/gql/model_search_generator.rb +19 -0
- data/lib/generators/gql/model_type_generator.rb +20 -4
- data/lib/generators/gql/templates/model_search.rb +16 -0
- data/lib/generators/gql/templates/model_search_base.rb +7 -0
- data/lib/graphql-rails-generators/version.rb +1 -1
- metadata +5 -3
- data/lib/generators/gql/templates/input_type.rb +0 -9
- data/lib/generators/gql/templates/model_type.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b3e945d1874ce80d7b6869974c0ff1ed879ab4c05a0cf7c95f45e92a7353592
|
4
|
+
data.tar.gz: 303b4b236b892bdf7062153bbd502f198426ca666557a2a3edee34964be8edb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00fc8c39ac7fc1fbe52c5441af7c23992767837e6416466cb10265ef756195c241f3736aa90b7d8079536f3d75e2efb5ae3b098114be99bf51fbe1c7ed39d03b
|
7
|
+
data.tar.gz: eb88f4cc1003f4eedfecead2bfb983f1a47aa8ee318a20fd17436cfb03b995073baf456adb7ad76d535f3b9f9205a4294e9ef0a5d1c06915c171f7b9f2c1672b
|
data/README.md
CHANGED
@@ -2,11 +2,12 @@
|
|
2
2
|
|
3
3
|
A few generators to make it easy to integrate your Rails models with [graphql-ruby](https://github.com/rmosolgo/graphql-ruby). I created this because I was wasting too many keystrokes copying my model schema by hand to create graphql types.
|
4
4
|
|
5
|
-
This project contains
|
5
|
+
This project contains generators that look at your ActiveRecord model schema and generates graphql types for you.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
- `gql:model_type Post` - Generate a graphql type for a model
|
8
|
+
- `gql:input Post` - Generate a graphql input type for a model
|
9
|
+
- `gql:mutation Update Post` - Generate a graphql mutation class for a model
|
10
|
+
- `gql:search_object` - A search object based on [SearchObjectGraphQL](https://github.com/RStankov/SearchObjectGraphQL)
|
10
11
|
|
11
12
|
## Installation
|
12
13
|
|
@@ -28,7 +29,11 @@ Generate a model type from a model.
|
|
28
29
|
$ rails generate gql:model_type MODEL_CLASS
|
29
30
|
```
|
30
31
|
|
31
|
-
|
32
|
+
#### Options
|
33
|
+
|
34
|
+
* `--name` - customize the file/class name, useful if you don't want the default Type suffix.
|
35
|
+
|
36
|
+
#### Example
|
32
37
|
|
33
38
|
```ruby
|
34
39
|
# app/graphql/post_type.rb
|
@@ -51,7 +56,12 @@ Generate an input type from a model.
|
|
51
56
|
rails generate gql:input Post
|
52
57
|
```
|
53
58
|
|
54
|
-
|
59
|
+
#### Options
|
60
|
+
|
61
|
+
* `--name` - customize the file/class name, useful if you don't want the default Input suffix.
|
62
|
+
|
63
|
+
#### Example
|
64
|
+
|
55
65
|
```ruby
|
56
66
|
# app/graphql/types/post_input.rb
|
57
67
|
module Types
|
@@ -72,7 +82,8 @@ Generate create, update and delete mutations for a model.
|
|
72
82
|
rails generate gql:mutations Post
|
73
83
|
```
|
74
84
|
|
75
|
-
|
85
|
+
#### Example
|
86
|
+
|
76
87
|
```ruby
|
77
88
|
# app/graphql/types/post_input.rb
|
78
89
|
module Types
|
@@ -97,7 +108,8 @@ The mutation generator generates something akin to an "upsert" mutation. It take
|
|
97
108
|
rails generate gql:mutation Update Post
|
98
109
|
```
|
99
110
|
|
100
|
-
|
111
|
+
#### Example
|
112
|
+
|
101
113
|
```ruby
|
102
114
|
# app/graphql/mutations/update_post.rb
|
103
115
|
module Mutations
|
@@ -126,4 +138,66 @@ module Mutations
|
|
126
138
|
end
|
127
139
|
end
|
128
140
|
end
|
129
|
-
```
|
141
|
+
```
|
142
|
+
|
143
|
+
### gql:search_object MODEL_NAME
|
144
|
+
|
145
|
+
Generate a search object from a model using [SearchObjectGraphQL](https://github.com/RStankov/SearchObjectGraphQL)
|
146
|
+
|
147
|
+
If you have not yet created a base search resolver:
|
148
|
+
|
149
|
+
`rails g gql:model_search_base`
|
150
|
+
|
151
|
+
\*_Adds `gem 'search_object_graphql'` to gemfile_
|
152
|
+
|
153
|
+
#### Example
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
# app/graphql/resolvers/base_search_resolver.rb
|
157
|
+
module Resolvers
|
158
|
+
class BaseSearchResolver < GraphQL::Schema::Resolver
|
159
|
+
require 'search_object'
|
160
|
+
require 'search_object/plugin/graphql'
|
161
|
+
include SearchObject.module(:graphql)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
Then generate a search object for your model:
|
167
|
+
|
168
|
+
`rails g gql:model_search Post`
|
169
|
+
|
170
|
+
#### Example
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
# app/graphql/resolvers/post_search.rb
|
174
|
+
module Resolvers
|
175
|
+
class PostSearch < Resolvers::BaseSearchResolver
|
176
|
+
type [Types::PostType], null: false
|
177
|
+
description "Lists posts"
|
178
|
+
|
179
|
+
scope { Post.all }
|
180
|
+
|
181
|
+
option(:id, type: Int) { |scope, value| scope.where id: value }
|
182
|
+
option(:title, type: String) { |scope, value| scope.where title: value }
|
183
|
+
option(:body, type: Int) { |scope, value| scope.where rating: value }
|
184
|
+
option(:created_at, type: GraphQL::Types::ISO8601DateTime) { |scope, value| scope.where created_at: value }
|
185
|
+
option(:updated_at, type: GraphQL::Types::ISO8601DateTime) { |scope, value| scope.where updated_at: value }
|
186
|
+
|
187
|
+
def resolve
|
188
|
+
[]
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
```
|
194
|
+
|
195
|
+
This will also insert a search field into the beginning of query_type.rb
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
#app/graphql/types/query_type.rb
|
199
|
+
module Types
|
200
|
+
class QueryType < Types::BaseObject
|
201
|
+
field :posts, resolver: Resolvers::PostSearch
|
202
|
+
...
|
203
|
+
```
|
@@ -2,40 +2,71 @@ require 'rails/generators/base'
|
|
2
2
|
|
3
3
|
module Gql
|
4
4
|
module GqlGeneratorBase
|
5
|
-
|
5
|
+
protected
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
# Generate a namedspaced class name with the mutation prefix
|
8
|
+
def prefixed_class_name(prefix)
|
9
|
+
(class_path + ["#{prefix}_#{file_name}"]).map!(&:camelize).join("::")
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def type_map
|
13
|
+
{
|
14
|
+
integer: 'Int',
|
15
|
+
string: 'String',
|
16
|
+
boolean: 'Boolean',
|
17
|
+
decimal: 'Float',
|
18
|
+
datetime: 'GraphQL::Types::ISO8601DateTime',
|
19
|
+
date: 'GraphQL::Types::ISO8601Date',
|
20
|
+
hstore: 'GraphQL::Types::JSON',
|
21
|
+
text: 'String',
|
22
|
+
json: 'GraphQL::Types::JSON',
|
23
|
+
jsonb: 'GraphQL::Types::JSON'
|
24
|
+
}
|
25
|
+
end
|
14
26
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
27
|
+
def map_model_types(model_name)
|
28
|
+
klass = model_name.constantize
|
29
|
+
associations = klass.reflect_on_all_associations(:belongs_to)
|
30
|
+
bt_columns = associations.map(&:foreign_key)
|
31
|
+
|
32
|
+
klass.columns
|
33
|
+
.reject { |col| bt_columns.include?(col.name) }
|
34
|
+
.reject { |col| type_map[col.type].nil? }
|
35
|
+
.map do |col|
|
36
|
+
{
|
37
|
+
name: col.name,
|
38
|
+
null: col.null,
|
39
|
+
gql_type: klass.primary_key == col.name ? 'GraphQL::Types::ID' : type_map[col.type]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def root_directory(namespace)
|
45
|
+
"app/graphql/#{namespace.underscore}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def wrap_in_namespace(namespace)
|
49
|
+
namespace = namespace.split('::')
|
50
|
+
namespace.shift if namespace[0].empty?
|
51
|
+
|
52
|
+
code = namespace.each_with_index.map { |name, i| " " * i + "module #{name}" }.join("\n")
|
53
|
+
code << "\n" << yield(namespace.size) << "\n"
|
54
|
+
code << (namespace.size - 1).downto(0).map { |i| " " * i + "end" }.join("\n")
|
55
|
+
code
|
56
|
+
end
|
57
|
+
|
58
|
+
def class_with_fields(namespace, name, superclass, fields)
|
59
|
+
wrap_in_namespace(namespace) do |indent|
|
60
|
+
klass = []
|
61
|
+
klass << sprintf("%sclass %s < %s", " " * indent, name, superclass)
|
62
|
+
|
63
|
+
fields.each do |field|
|
64
|
+
klass << sprintf("%sfield :%s, %s, null: %s", " " * (indent + 1), field[:name], field[:gql_type], field[:null])
|
65
|
+
end
|
66
|
+
|
67
|
+
klass << sprintf("%send", " " * indent)
|
68
|
+
klass.join("\n")
|
38
69
|
end
|
39
70
|
end
|
40
71
|
end
|
41
|
-
end
|
72
|
+
end
|
@@ -3,15 +3,29 @@ module Gql
|
|
3
3
|
class InputGenerator < Rails::Generators::Base
|
4
4
|
include GqlGeneratorBase
|
5
5
|
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
6
7
|
argument :model_name, type: :string
|
7
|
-
|
8
|
+
|
9
|
+
class_option :name, type: :string
|
10
|
+
class_option :include_columns, type: :array, default: []
|
11
|
+
class_option :superclass, type: :string, default: 'Types::BaseInputObject'
|
12
|
+
class_option :namespace, type: :string, default: 'Types::Input'
|
13
|
+
|
8
14
|
def generate_input_type
|
9
|
-
|
15
|
+
name = options['name'].nil? ? "#{model_name}Input" : options['name']
|
16
|
+
superclass = options['superclass']
|
10
17
|
|
11
18
|
ignore = ['id', 'created_at', 'updated_at']
|
12
|
-
|
19
|
+
fields = map_model_types(model_name)
|
20
|
+
fields.reject! { |field| ignore.include?(field[:name]) }
|
21
|
+
if options['include_columns'].any?
|
22
|
+
fields.reject! { |field| !options['include_columns'].include?(field[:name]) }
|
23
|
+
end
|
24
|
+
|
25
|
+
code = class_with_fields(options['namespace'], name, superclass, fields)
|
26
|
+
file_name = File.join(root_directory(options['namespace']), "#{name.underscore}.rb")
|
13
27
|
|
14
|
-
|
28
|
+
create_file file_name, code
|
15
29
|
end
|
16
30
|
end
|
17
|
-
end
|
31
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Gql
|
2
|
+
class ModelSearchBaseGenerator < Rails::Generators::Base
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
def generate_model_search_base
|
5
|
+
gem 'search_object_graphql'
|
6
|
+
template('model_search_base.rb', "app/graphql/resolvers/base_search_resolver.rb")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'gql_generator_base'
|
2
|
+
module Gql
|
3
|
+
class ModelSearchGenerator < Rails::Generators::Base
|
4
|
+
include GqlGeneratorBase
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
argument :model_name, type: :string
|
7
|
+
|
8
|
+
def search
|
9
|
+
inject_into_file(
|
10
|
+
"app/graphql/types/query_type.rb",
|
11
|
+
"\t\tfield :#{model_name.downcase.pluralize}, resolver: Resolvers::#{model_name}Search \n",
|
12
|
+
:after => "class QueryType < Types::BaseObject\n"
|
13
|
+
)
|
14
|
+
file_name = "#{model_name.underscore}_search"
|
15
|
+
@fields = map_model_types(model_name)
|
16
|
+
template('model_search.rb', "app/graphql/resolvers/#{file_name}.rb")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -3,12 +3,28 @@ module Gql
|
|
3
3
|
class ModelTypeGenerator < Rails::Generators::Base
|
4
4
|
include GqlGeneratorBase
|
5
5
|
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
6
7
|
argument :model_name, type: :string
|
7
8
|
|
9
|
+
class_option :name, type: :string
|
10
|
+
class_option :include_columns, type: :array, default: []
|
11
|
+
class_option :superclass, type: :string, default: 'Types::BaseObject'
|
12
|
+
class_option :namespace, type: :string, default: 'Types'
|
13
|
+
|
8
14
|
def type
|
9
|
-
|
10
|
-
|
11
|
-
|
15
|
+
name = options['name'].nil? ? "#{model_name}Type" : options['name']
|
16
|
+
|
17
|
+
superclass = options['superclass']
|
18
|
+
|
19
|
+
fields = map_model_types(model_name)
|
20
|
+
if options['include_columns'].any?
|
21
|
+
fields.reject! { |field| !options['include_columns'].include?(field[:name]) }
|
22
|
+
end
|
23
|
+
|
24
|
+
code = class_with_fields(options['namespace'], name, superclass, fields)
|
25
|
+
file_name = File.join(root_directory(options['namespace']), "#{name.underscore}.rb")
|
26
|
+
|
27
|
+
create_file file_name, code
|
12
28
|
end
|
13
29
|
end
|
14
|
-
end
|
30
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Resolvers
|
2
|
+
class <%= @resolver_prefix %><%= @model_name %>Search < Resolvers::BaseSearchResolver
|
3
|
+
type [Types::<%= @model_name %>Type], null: false
|
4
|
+
description "Lists <%= @model_name.downcase.pluralize %>"
|
5
|
+
|
6
|
+
scope { <%= @model_name %>.all }
|
7
|
+
|
8
|
+
<% @fields.each do |field| -%>
|
9
|
+
option(:<%= field[:name] %>, type: <%= field[:gql_type] %>) { |scope, value| scope.where <%= field[:name] %>: value }
|
10
|
+
<% end %>
|
11
|
+
def resolve
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql-rails-generators
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Sharp
|
@@ -20,14 +20,16 @@ files:
|
|
20
20
|
- README.md
|
21
21
|
- lib/generators/gql/gql_generator_base.rb
|
22
22
|
- lib/generators/gql/input_generator.rb
|
23
|
+
- lib/generators/gql/model_search_base_generator.rb
|
24
|
+
- lib/generators/gql/model_search_generator.rb
|
23
25
|
- lib/generators/gql/model_type_generator.rb
|
24
26
|
- lib/generators/gql/mutation_generator.rb
|
25
27
|
- lib/generators/gql/mutations_generator.rb
|
26
28
|
- lib/generators/gql/templates/create_mutation.rb
|
27
29
|
- lib/generators/gql/templates/delete_mutation.rb
|
28
|
-
- lib/generators/gql/templates/input_type.rb
|
29
30
|
- lib/generators/gql/templates/model_mutation.rb
|
30
|
-
- lib/generators/gql/templates/
|
31
|
+
- lib/generators/gql/templates/model_search.rb
|
32
|
+
- lib/generators/gql/templates/model_search_base.rb
|
31
33
|
- lib/generators/gql/templates/update_mutation.rb
|
32
34
|
- lib/graphql-rails-generators/version.rb
|
33
35
|
homepage: https://github.com/ajsharp/graphql-rails-generators
|