graphql-rails-generators 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38981ddd6d3252268196ca9c333672436e63ee24badf5fa54e72915c4bbcfeb5
4
- data.tar.gz: cbe8ba3110f66a30c2dbba7e2301b33e7ab52bd7deb2b6f7e4d37afc0b1bb9f0
3
+ metadata.gz: 5b3e945d1874ce80d7b6869974c0ff1ed879ab4c05a0cf7c95f45e92a7353592
4
+ data.tar.gz: 303b4b236b892bdf7062153bbd502f198426ca666557a2a3edee34964be8edb1
5
5
  SHA512:
6
- metadata.gz: e359081f8e02097e84af9d00fdc507e6d42fdc6d2b9727fb8732fc5f8b420da9d6279e62b99f79ab6f5b5bdf055484499a74df2cc9c4b9f829533afa1d046949
7
- data.tar.gz: d28b879ad5152567bd3e66b58dfe5713c3920f315553c5b94e0e8836f790914de8c1b5b5bd4886abd908f076712967e479eadc053bbd0d6f58738265f3446d57
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 three generators that look at your ActiveRecord model schema and generates graphql types for you.
5
+ This project contains generators that look at your ActiveRecord model schema and generates graphql types for you.
6
6
 
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
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
- Result:
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
- Result:
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
- Result:
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
- Result:
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
- extend ActiveSupport::Concern
5
+ protected
6
6
 
7
- included do
8
- protected
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
- # Generate a namedspaced class name with the mutation prefix
11
- def prefixed_class_name(prefix)
12
- (class_path + ["#{prefix}_#{file_name}"]).map!(&:camelize).join("::")
13
- end
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
- def type_map
16
- {
17
- integer: 'Int',
18
- string: 'String',
19
- boolean: 'Boolean',
20
- decimal: 'Float',
21
- datetime: 'GraphQL::Types::ISO8601DateTime',
22
- date: 'GraphQL::Types::ISO8601Date',
23
- hstore: 'GraphQL::Types::JSON',
24
- text: 'String',
25
- json: 'GraphQL::Types::JSON'
26
- }
27
- end
28
-
29
- def map_model_types(model_name)
30
- klass = model_name.constantize
31
- associations = klass.reflect_on_all_associations(:belongs_to)
32
- bt_columns = associations.map(&:foreign_key)
33
-
34
- klass.columns
35
- .reject { |col| bt_columns.include?(col.name) }
36
- .reject { |col| type_map[col.type].nil? }
37
- .map { |col| {name: col.name, gql_type: type_map[col.type]} }
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
- file_name = model_name
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
- @fields = map_model_types(model_name).reject { |field| ignore.include?(field[:name]) }
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
- template('input_type.rb', "app/graphql/types/input/#{file_name.underscore}_input.rb")
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
- file_name = "#{model_name.underscore}_type"
10
- @fields = map_model_types(model_name)
11
- template('model_type.rb', "app/graphql/types/#{file_name}.rb")
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
@@ -0,0 +1,7 @@
1
+ module Resolvers
2
+ class BaseSearchResolver < GraphQL::Schema::Resolver
3
+ require 'search_object'
4
+ require 'search_object/plugin/graphql'
5
+ include SearchObject.module(:graphql)
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module GraphqlRailsGenerators
2
- VERSION = '1.1.0'
2
+ VERSION = '1.1.1'
3
3
  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.0
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/model_type.rb
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
@@ -1,9 +0,0 @@
1
- module Types
2
- module Input
3
- class <%= @model_name %>Input < Types::BaseInputObject
4
- <% @fields.each do |field| -%>
5
- argument :<%= field[:name] %>, <%= field[:gql_type] %>, required: false
6
- <% end %>
7
- end
8
- end
9
- end
@@ -1,7 +0,0 @@
1
- module Types
2
- class <%= @model_name %>Type < Types::BaseObject
3
- <% @fields.each do |field| -%>
4
- field :<%= field[:name] %>, <%= field[:gql_type] %>, null: true
5
- <% end %>
6
- end
7
- end