graphql_rails 2.1.0 → 2.3.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/.ruby-version +1 -1
  4. data/CHANGELOG.md +14 -0
  5. data/Gemfile.lock +117 -116
  6. data/docs/README.md +23 -45
  7. data/docs/_sidebar.md +0 -1
  8. data/docs/components/controller.md +15 -1
  9. data/docs/components/decorator.md +1 -1
  10. data/docs/components/model.md +62 -0
  11. data/docs/components/routes.md +45 -8
  12. data/lib/graphql_rails/attributes/attribute.rb +8 -14
  13. data/lib/graphql_rails/attributes/attribute_configurable.rb +15 -0
  14. data/lib/graphql_rails/attributes/input_attribute.rb +17 -1
  15. data/lib/graphql_rails/attributes/type_parseable.rb +1 -7
  16. data/lib/graphql_rails/controller/build_controller_action_resolver.rb +2 -0
  17. data/lib/graphql_rails/controller/log_controller_action.rb +7 -2
  18. data/lib/graphql_rails/controller.rb +1 -1
  19. data/lib/graphql_rails/decorator/relation_decorator.rb +22 -18
  20. data/lib/graphql_rails/decorator.rb +12 -4
  21. data/lib/graphql_rails/errors/system_error.rb +11 -1
  22. data/lib/graphql_rails/errors/validation_error.rb +14 -1
  23. data/lib/graphql_rails/input_configurable.rb +1 -1
  24. data/lib/graphql_rails/model/find_or_build_graphql_type.rb +1 -5
  25. data/lib/graphql_rails/router/build_schema_action_type.rb +112 -0
  26. data/lib/graphql_rails/router/mutation_route.rb +4 -0
  27. data/lib/graphql_rails/router/query_route.rb +4 -0
  28. data/lib/graphql_rails/router/resource_routes_builder.rb +8 -0
  29. data/lib/graphql_rails/router/route.rb +3 -2
  30. data/lib/graphql_rails/router/schema_builder.rb +14 -18
  31. data/lib/graphql_rails/router/subscription_route.rb +22 -0
  32. data/lib/graphql_rails/router.rb +32 -10
  33. data/lib/graphql_rails/version.rb +1 -1
  34. metadata +5 -4
  35. data/docs/getting_started/quick_start.md +0 -62
@@ -5,12 +5,14 @@ module GraphqlRails
5
5
  # builds GraphQL::Schema based on previously defined grahiti data
6
6
  class SchemaBuilder
7
7
  require_relative './plain_cursor_encoder'
8
+ require_relative './build_schema_action_type'
8
9
 
9
- attr_reader :queries, :mutations, :raw_actions
10
+ attr_reader :queries, :mutations, :subscriptions, :raw_actions
10
11
 
11
- def initialize(queries:, mutations:, raw_actions:, group: nil)
12
+ def initialize(queries:, mutations:, subscriptions:, raw_actions:, group: nil)
12
13
  @queries = queries
13
14
  @mutations = mutations
15
+ @subscriptions = subscriptions
14
16
  @raw_actions = raw_actions
15
17
  @group = group
16
18
  end
@@ -18,6 +20,7 @@ module GraphqlRails
18
20
  def call
19
21
  query_type = build_group_type('Query', queries)
20
22
  mutation_type = build_group_type('Mutation', mutations)
23
+ subscription_type = build_group_type('Subscription', subscriptions)
21
24
  raw = raw_actions
22
25
 
23
26
  Class.new(GraphQL::Schema) do
@@ -30,6 +33,7 @@ module GraphqlRails
30
33
 
31
34
  query(query_type) if query_type
32
35
  mutation(mutation_type) if mutation_type
36
+ subscription(subscription_type) if subscription_type
33
37
  end
34
38
  end
35
39
 
@@ -39,24 +43,16 @@ module GraphqlRails
39
43
 
40
44
  def build_group_type(type_name, routes)
41
45
  group_name = group
42
- group_routes = routes.select { |route| route.show_in_group?(group_name) }
43
- return if group_routes.empty?
46
+ group_routes =
47
+ routes
48
+ .select { |route| route.show_in_group?(group_name) }
49
+ .reverse
50
+ .uniq(&:name)
51
+ .reverse
44
52
 
45
- build_type(type_name, group_routes)
46
- end
47
-
48
- def build_type(type_name, group_routes)
49
- Class.new(GraphQL::Schema::Object) do
50
- graphql_name(type_name)
53
+ return if group_routes.empty? && type_name != 'Query'
51
54
 
52
- group_routes.each do |route|
53
- field(*route.name, **route.field_options)
54
- end
55
-
56
- def self.inspect
57
- "#{GraphQL::Schema::Object}(#{graphql_name})"
58
- end
59
- end
55
+ BuildSchemaActionType.call(type_name: type_name, routes: group_routes)
60
56
  end
61
57
  end
62
58
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'route'
4
+
5
+ module GraphqlRails
6
+ class Router
7
+ # stores subscription type graphql action info
8
+ class SubscriptionRoute < Route
9
+ def query?
10
+ false
11
+ end
12
+
13
+ def mutation?
14
+ false
15
+ end
16
+
17
+ def subscription?
18
+ true
19
+ end
20
+ end
21
+ end
22
+ end
@@ -5,6 +5,7 @@ require 'active_support/core_ext/string/inflections'
5
5
  require 'graphql_rails/router/schema_builder'
6
6
  require 'graphql_rails/router/mutation_route'
7
7
  require 'graphql_rails/router/query_route'
8
+ require 'graphql_rails/router/subscription_route'
8
9
  require 'graphql_rails/router/resource_routes_builder'
9
10
 
10
11
  module GraphqlRails
@@ -20,13 +21,15 @@ module GraphqlRails
20
21
  end
21
22
  end
22
23
 
23
- attr_reader :routes, :namespace_name, :raw_graphql_actions
24
+ attr_reader :routes, :namespace_name, :raw_graphql_actions, :scope_names
24
25
 
25
- def initialize(module_name: '', group_names: [])
26
+ def initialize(module_name: '', group_names: [], scope_names: [])
27
+ @scope_names = scope_names
26
28
  @module_name = module_name
27
29
  @group_names = group_names
28
30
  @routes ||= Set.new
29
31
  @raw_graphql_actions ||= []
32
+ @graphql_schema = {}
30
33
  end
31
34
 
32
35
  def group(*group_names, &block)
@@ -35,13 +38,16 @@ module GraphqlRails
35
38
  routes.merge(scoped_router.routes)
36
39
  end
37
40
 
38
- def scope(**options, &block)
39
- full_module_name = [module_name, options[:module]].reject(&:empty?).join('/')
40
- scoped_router = router_with(module_name: full_module_name)
41
+ def scope(new_scope_name = nil, **options, &block)
42
+ scoped_router = router_with_scope_params(new_scope_name, **options)
41
43
  scoped_router.instance_eval(&block)
42
44
  routes.merge(scoped_router.routes)
43
45
  end
44
46
 
47
+ def namespace(namespace_name, &block)
48
+ scope(path: namespace_name, module: namespace_name, &block)
49
+ end
50
+
45
51
  def resources(name, **options, &block)
46
52
  builder_options = full_route_options(options)
47
53
  routes_builder = ResourceRoutesBuilder.new(name, **builder_options)
@@ -57,6 +63,10 @@ module GraphqlRails
57
63
  routes << build_route(MutationRoute, name, **options)
58
64
  end
59
65
 
66
+ def subscription(name, **options)
67
+ routes << build_route(SubscriptionRoute, name, **options)
68
+ end
69
+
60
70
  RAW_ACTION_NAMES.each do |action_name|
61
71
  define_method(action_name) do |*args, &block|
62
72
  add_raw_action(action_name, *args, &block)
@@ -64,30 +74,42 @@ module GraphqlRails
64
74
  end
65
75
 
66
76
  def graphql_schema(group = nil)
67
- @graphql_schema ||= {}
68
77
  @graphql_schema[group&.to_sym] ||= SchemaBuilder.new(
69
78
  queries: routes.select(&:query?),
70
79
  mutations: routes.select(&:mutation?),
80
+ subscriptions: routes.select(&:subscription?),
71
81
  raw_actions: raw_graphql_actions,
72
82
  group: group
73
83
  ).call
74
84
  end
75
85
 
76
86
  def reload_schema
77
- @graphql_schema = nil
87
+ @graphql_schema.clear
78
88
  end
79
89
 
80
90
  private
81
91
 
82
92
  attr_reader :module_name, :group_names
83
93
 
94
+ def router_with_scope_params(new_scope_name, **options)
95
+ new_scope_name ||= options[:path]
96
+
97
+ full_module_name = [module_name, options[:module]].select(&:present?).join('/')
98
+ full_scope_names = [*scope_names, new_scope_name].select(&:present?)
99
+
100
+ router_with(module_name: full_module_name, scope_names: full_scope_names)
101
+ end
102
+
84
103
  def router_with(new_router_options = {})
85
- default_options = { module_name: module_name, group_names: group_names }
86
- full_options = default_options.merge(new_router_options)
104
+ full_options = default_router_options.merge(new_router_options)
87
105
 
88
106
  self.class.new(**full_options)
89
107
  end
90
108
 
109
+ def default_router_options
110
+ { module_name: module_name, group_names: group_names, scope_names: scope_names }
111
+ end
112
+
91
113
  def add_raw_action(name, *args, &block)
92
114
  raw_graphql_actions << { name: name, args: args, block: block }
93
115
  end
@@ -105,7 +127,7 @@ module GraphqlRails
105
127
  end
106
128
 
107
129
  def default_route_options
108
- { module: module_name, on: :member }
130
+ { module: module_name, on: :member, scope_names: scope_names }
109
131
  end
110
132
  end
111
133
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlRails
4
- VERSION = '2.1.0'
4
+ VERSION = '2.3.0'
5
5
  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: 2.1.0
4
+ version: 2.3.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: 2022-01-12 00:00:00.000000000 Z
11
+ date: 2022-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: graphql
@@ -156,7 +156,6 @@ files:
156
156
  - docs/components/decorator.md
157
157
  - docs/components/model.md
158
158
  - docs/components/routes.md
159
- - docs/getting_started/quick_start.md
160
159
  - docs/getting_started/setup.md
161
160
  - docs/index.html
162
161
  - docs/logging_and_monitoring/logging_and_monitoring.md
@@ -220,12 +219,14 @@ files:
220
219
  - lib/graphql_rails/query_runner.rb
221
220
  - lib/graphql_rails/railtie.rb
222
221
  - lib/graphql_rails/router.rb
222
+ - lib/graphql_rails/router/build_schema_action_type.rb
223
223
  - lib/graphql_rails/router/mutation_route.rb
224
224
  - lib/graphql_rails/router/plain_cursor_encoder.rb
225
225
  - lib/graphql_rails/router/query_route.rb
226
226
  - lib/graphql_rails/router/resource_routes_builder.rb
227
227
  - lib/graphql_rails/router/route.rb
228
228
  - lib/graphql_rails/router/schema_builder.rb
229
+ - lib/graphql_rails/router/subscription_route.rb
229
230
  - lib/graphql_rails/rspec_controller_helpers.rb
230
231
  - lib/graphql_rails/tasks/dump_graphql_schema.rb
231
232
  - lib/graphql_rails/tasks/dump_graphql_schemas.rb
@@ -254,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
255
  - !ruby/object:Gem::Version
255
256
  version: '0'
256
257
  requirements: []
257
- rubygems_version: 3.2.15
258
+ rubygems_version: 3.3.7
258
259
  signing_key:
259
260
  specification_version: 4
260
261
  summary: Rails style structure for GraphQL API.
@@ -1,62 +0,0 @@
1
- # Quick Start
2
-
3
- ## Generate initial code
4
-
5
- ```bash
6
- bundle exec rails g graphql_rails:install
7
- ```
8
-
9
- ## Define GraphQL schema as RoR routes
10
-
11
- ```ruby
12
- # config/graphql/routes.rb
13
- GraphqlRails::Router.draw do
14
- # will create createUser, updateUser, destroyUser mutations and user, users queries.
15
- # expects that UsersController class exist
16
- resources :users
17
-
18
- # if you want custom queries or mutation
19
- query 'searchLogs', to: 'logs#search' # redirects request to LogsController
20
- mutation 'changeUserPassword', to: 'users#change_password'
21
- end
22
- ```
23
-
24
- ## Define your Graphql model
25
-
26
- ```ruby
27
- class User # works with any class including ActiveRecord
28
- include GraphqlRails::Model
29
-
30
- graphql do |c|
31
- # most common attributes, like :id, :name, :title has default type, so you don't have to specify it (but you can!)
32
- c.attribute :id
33
-
34
- c.attribute :email, :string
35
- c.attribute :surname, :string
36
- end
37
- end
38
- ```
39
-
40
- ## Define controller
41
-
42
- ```ruby
43
- class UsersController < ApplicationGraphqlController
44
- # graphql requires to describe which attributes controller action accepts and which returns
45
- action(:change_user_password)
46
- .permit(:password!, :id!) # Bang (!) indicates that attribute is required
47
-
48
- def change_user_password
49
- user = User.find(params[:id])
50
- user.update!(password: params[:password])
51
-
52
- # returned value needs to have all methods defined in model `graphql do` part
53
- user # or SomeDecorator.new(user)
54
- end
55
-
56
- action(:search).permit(search_fields!: SearchFieldsInput) # you can specify your own input fields
57
- def search
58
- end
59
- end
60
- ```
61
-
62
- Congrats, you are done!