rails-graphql 1.0.0.beta → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/gql_parser.c +1 -16
- data/ext/gql_parser.h +21 -0
- data/ext/shared.c +0 -5
- data/ext/shared.h +6 -6
- data/lib/generators/graphql/channel_generator.rb +27 -0
- data/lib/generators/graphql/controller_generator.rb +9 -4
- data/lib/generators/graphql/install_generator.rb +49 -0
- data/lib/generators/graphql/schema_generator.rb +9 -4
- data/lib/generators/graphql/templates/channel.erb +7 -0
- data/lib/generators/graphql/templates/config.rb +97 -0
- data/lib/generators/graphql/templates/controller.erb +2 -0
- data/lib/generators/graphql/templates/schema.erb +5 -3
- data/lib/gql_parser.so +0 -0
- data/lib/rails/graphql/alternative/field_set.rb +12 -0
- data/lib/rails/graphql/alternative/query.rb +9 -4
- data/lib/rails/graphql/alternative/subscription.rb +2 -1
- data/lib/rails/graphql/argument.rb +5 -3
- data/lib/rails/graphql/callback.rb +8 -7
- data/lib/rails/graphql/collectors/hash_collector.rb +12 -1
- data/lib/rails/graphql/collectors/json_collector.rb +21 -0
- data/lib/rails/graphql/config.rb +73 -57
- data/lib/rails/graphql/directive/include_directive.rb +0 -1
- data/lib/rails/graphql/directive/skip_directive.rb +0 -1
- data/lib/rails/graphql/directive/specified_by_directive.rb +24 -0
- data/lib/rails/graphql/directive.rb +30 -24
- data/lib/rails/graphql/event.rb +7 -6
- data/lib/rails/graphql/field/authorized_field.rb +0 -5
- data/lib/rails/graphql/field/input_field.rb +0 -5
- data/lib/rails/graphql/field/mutation_field.rb +5 -6
- data/lib/rails/graphql/field/output_field.rb +13 -2
- data/lib/rails/graphql/field/proxied_field.rb +5 -5
- data/lib/rails/graphql/field/resolved_field.rb +1 -1
- data/lib/rails/graphql/field/subscription_field.rb +35 -52
- data/lib/rails/graphql/field/typed_field.rb +26 -2
- data/lib/rails/graphql/field.rb +20 -19
- data/lib/rails/graphql/global_id.rb +5 -1
- data/lib/rails/graphql/helpers/inherited_collection/array.rb +1 -0
- data/lib/rails/graphql/helpers/inherited_collection/base.rb +2 -0
- data/lib/rails/graphql/helpers/inherited_collection/hash.rb +2 -1
- data/lib/rails/graphql/helpers/registerable.rb +1 -1
- data/lib/rails/graphql/helpers/with_arguments.rb +3 -2
- data/lib/rails/graphql/helpers/with_callbacks.rb +3 -3
- data/lib/rails/graphql/helpers/with_description.rb +10 -8
- data/lib/rails/graphql/helpers/with_directives.rb +5 -1
- data/lib/rails/graphql/helpers/with_events.rb +1 -0
- data/lib/rails/graphql/helpers/with_fields.rb +28 -22
- data/lib/rails/graphql/helpers/with_name.rb +3 -2
- data/lib/rails/graphql/helpers/with_schema_fields.rb +72 -48
- data/lib/rails/graphql/introspection.rb +1 -1
- data/lib/rails/graphql/railtie.rb +3 -2
- data/lib/rails/graphql/railties/app/base_channel.rb +10 -0
- data/lib/rails/graphql/railties/app/base_controller.rb +12 -0
- data/lib/rails/graphql/railties/app/views/_cable.js.erb +56 -0
- data/lib/rails/graphql/railties/app/views/_fetch.js.erb +20 -0
- data/lib/rails/graphql/railties/app/views/graphiql.html.erb +101 -0
- data/lib/rails/graphql/railties/base_generator.rb +3 -9
- data/lib/rails/graphql/railties/channel.rb +8 -8
- data/lib/rails/graphql/railties/controller.rb +45 -24
- data/lib/rails/graphql/request/arguments.rb +2 -1
- data/lib/rails/graphql/request/backtrace.rb +31 -10
- data/lib/rails/graphql/request/component/field.rb +15 -8
- data/lib/rails/graphql/request/component/fragment.rb +13 -7
- data/lib/rails/graphql/request/component/operation/subscription.rb +4 -6
- data/lib/rails/graphql/request/component/operation.rb +11 -4
- data/lib/rails/graphql/request/component/spread.rb +13 -4
- data/lib/rails/graphql/request/component/typename.rb +1 -1
- data/lib/rails/graphql/request/component.rb +2 -0
- data/lib/rails/graphql/request/context.rb +1 -1
- data/lib/rails/graphql/request/event.rb +6 -2
- data/lib/rails/graphql/request/helpers/directives.rb +1 -0
- data/lib/rails/graphql/request/helpers/selection_set.rb +10 -4
- data/lib/rails/graphql/request/helpers/value_writers.rb +8 -5
- data/lib/rails/graphql/request/prepared_data.rb +3 -1
- data/lib/rails/graphql/request/steps/organizable.rb +1 -1
- data/lib/rails/graphql/request/steps/preparable.rb +1 -1
- data/lib/rails/graphql/request/steps/resolvable.rb +1 -1
- data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +3 -3
- data/lib/rails/graphql/request/strategy.rb +18 -4
- data/lib/rails/graphql/request/subscription.rb +18 -16
- data/lib/rails/graphql/request.rb +67 -37
- data/lib/rails/graphql/schema.rb +39 -86
- data/lib/rails/graphql/shortcuts.rb +11 -5
- data/lib/rails/graphql/source/active_record/builders.rb +20 -21
- data/lib/rails/graphql/source/active_record_source.rb +93 -33
- data/lib/rails/graphql/source/base.rb +11 -39
- data/lib/rails/graphql/source/builder.rb +9 -22
- data/lib/rails/graphql/source/scoped_arguments.rb +10 -4
- data/lib/rails/graphql/source.rb +23 -37
- data/lib/rails/graphql/subscription/provider/action_cable.rb +10 -9
- data/lib/rails/graphql/subscription/provider/base.rb +6 -5
- data/lib/rails/graphql/subscription/store/base.rb +5 -9
- data/lib/rails/graphql/subscription/store/memory.rb +18 -9
- data/lib/rails/graphql/type/creator.rb +196 -0
- data/lib/rails/graphql/type/enum.rb +17 -9
- data/lib/rails/graphql/type/input.rb +20 -4
- data/lib/rails/graphql/type/interface.rb +15 -4
- data/lib/rails/graphql/type/object/directive_object.rb +6 -5
- data/lib/rails/graphql/type/object/input_value_object.rb +3 -4
- data/lib/rails/graphql/type/object/type_object.rb +40 -13
- data/lib/rails/graphql/type/object.rb +10 -5
- data/lib/rails/graphql/type/scalar/binary_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/date_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/date_time_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/decimal_scalar.rb +2 -0
- data/lib/rails/graphql/type/scalar/json_scalar.rb +3 -1
- data/lib/rails/graphql/type/scalar/time_scalar.rb +3 -1
- data/lib/rails/graphql/type/scalar.rb +1 -1
- data/lib/rails/graphql/type/union.rb +7 -2
- data/lib/rails/graphql/type.rb +10 -2
- data/lib/rails/graphql/type_map.rb +18 -7
- data/lib/rails/graphql/uri.rb +5 -4
- data/lib/rails/graphql/version.rb +6 -2
- data/lib/rails/graphql.rb +9 -7
- data/test/assets/introspection-mem.txt +1 -1
- data/test/assets/introspection.gql +2 -0
- data/test/assets/mem.gql +74 -60
- data/test/assets/mysql.gql +69 -55
- data/test/assets/sqlite.gql +78 -64
- data/test/assets/translate.gql +50 -39
- data/test/config.rb +2 -1
- data/test/graphql/schema_test.rb +2 -31
- data/test/graphql/source_test.rb +0 -10
- data/test/graphql/type/interface_test.rb +8 -5
- data/test/graphql/type/object_test.rb +8 -2
- data/test/graphql/type_map_test.rb +13 -16
- data/test/integration/global_id_test.rb +4 -4
- data/test/integration/memory/star_wars_validation_test.rb +2 -2
- data/test/integration/mysql/star_wars_introspection_test.rb +1 -1
- data/test/integration/resolver_precedence_test.rb +1 -1
- data/test/integration/schemas/memory.rb +3 -4
- data/test/integration/sqlite/star_wars_global_id_test.rb +27 -21
- data/test/integration/sqlite/star_wars_introspection_test.rb +1 -1
- data/test/integration/translate_test.rb +26 -14
- metadata +20 -7
data/lib/rails/graphql/config.rb
CHANGED
@@ -3,20 +3,22 @@
|
|
3
3
|
module Rails
|
4
4
|
module GraphQL
|
5
5
|
configure do |config|
|
6
|
-
# This helps to keep track of when things were cached and registered.
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# This helps to keep track of when things were cached and registered. Cached
|
7
|
+
# objects with mismatching versions need to be upgraded or simply reloaded.
|
8
|
+
# An excellent way to use this is to set it to the commit hash. TypePap will
|
9
|
+
# always use only the first 8 characters for simplicity.
|
10
10
|
config.version = nil
|
11
11
|
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
12
|
+
# The instance responsible for caching all the information generated by
|
13
|
+
# requests and all the other components. Manually setting this property
|
14
|
+
# means that the object in it complies with `ActiveSupport::Cache::Store`.
|
15
|
+
# This will map automatically to `Rails.cache` if kept as `nil`. This can
|
16
|
+
# also be set per Schema.
|
15
17
|
config.cache = nil
|
16
18
|
|
17
|
-
# If Rails cache is not properly defined
|
18
|
-
#
|
19
|
-
#
|
19
|
+
# If Rails cache is not properly defined or just set to use a NullStore,
|
20
|
+
# this fallback will set itself up with a memory store because cache is
|
21
|
+
# crucial, especially for subscriptions.
|
20
22
|
config.cache_fallback = -> do
|
21
23
|
::ActiveSupport::Cache::MemoryStore.new(max_prune_time: nil)
|
22
24
|
end
|
@@ -30,39 +32,44 @@ module Rails
|
|
30
32
|
config.paths = %w[directives fields sources enums inputs interfaces object
|
31
33
|
scalars unions].to_set
|
32
34
|
|
33
|
-
# This
|
35
|
+
# This is very similar to `ActiveRecord` verbose logs, which simply show the
|
36
|
+
# path of the file that started a GraphQL request.
|
34
37
|
config.verbose_logs = true
|
35
38
|
|
36
|
-
# The list of parameters to omit from logger when running a GraphQL
|
37
|
-
# request. Those values
|
38
|
-
#
|
39
|
+
# The list of parameters to omit from the logger when running a GraphQL
|
40
|
+
# request. Those values are displayed better in the internal runtime logger
|
41
|
+
# controller.
|
39
42
|
config.omit_parameters = %w[query operationName operation_name variables graphql]
|
40
43
|
|
41
|
-
#
|
42
|
-
#
|
44
|
+
# Identical to the one available on a Rails application, but exclusive for
|
45
|
+
# GraphQL operations. The list of parameters to display as filtered in the
|
46
|
+
# logs. When it is nil, it will use the same as the Rails application.
|
43
47
|
config.filter_parameters = nil
|
44
48
|
|
45
|
-
# A list of ActiveRecord adapters
|
46
|
-
#
|
49
|
+
# A list of all `ActiveRecord` adapters supported. When an adapter is
|
50
|
+
# supported, it will map the database types into GraphQL types using proper
|
51
|
+
# aliases. Plus, it will have the method to map models attributes to their
|
52
|
+
# equivalent fields.
|
47
53
|
config.ar_adapters = {
|
48
54
|
'Mysql2' => { key: :mysql, path: "#{__dir__}/adapters/mysql_adapter" },
|
49
55
|
'PostgreSQL' => { key: :pg, path: "#{__dir__}/adapters/pg_adapter" },
|
50
56
|
'SQLite' => { key: :sqlite, path: "#{__dir__}/adapters/sqlite_adapter" },
|
51
57
|
}
|
52
58
|
|
53
|
-
#
|
54
|
-
#
|
59
|
+
# The suffix that is added automatically to all the Input type objects. This
|
60
|
+
# prevents situations like `PointInputInput`. If your inputs have a
|
61
|
+
# different suffix, change this value to it.
|
55
62
|
config.auto_suffix_input_objects = 'Input'
|
56
63
|
|
57
|
-
# Introspection is enabled by default.
|
58
|
-
#
|
59
|
-
# set
|
60
|
-
config.enable_introspection =
|
64
|
+
# Introspection is enabled by default. It is recommended to only use
|
65
|
+
# introspection during development and tests, never in production.
|
66
|
+
# This can also be set per schema level.
|
67
|
+
config.enable_introspection = false
|
61
68
|
|
62
69
|
# Define the names of the schema/operations types. The single "_" is a
|
63
|
-
# suggestion
|
64
|
-
#
|
65
|
-
#
|
70
|
+
# suggestion. In an application that has a Subscription object, it will
|
71
|
+
# prevent the conflict. Plus, it is easy to spot that it is something
|
72
|
+
# internal. This can also be set per Schema.
|
66
73
|
config.schema_type_names = {
|
67
74
|
query: '_Query',
|
68
75
|
mutation: '_Mutation',
|
@@ -71,13 +78,15 @@ module Rails
|
|
71
78
|
|
72
79
|
# For performance purposes, this gem implements a
|
73
80
|
# {JsonCollector}[rdoc-ref:Rails::GraphQL::Collectors::JsonCollector].
|
74
|
-
#
|
75
|
-
#
|
81
|
+
# You can disable this option if you prefer to use the standard
|
82
|
+
# hash-to-string serialization provided by `ActiveSupport`.
|
83
|
+
# This can also be set per Schema.
|
76
84
|
config.enable_string_collector = true
|
77
85
|
|
78
86
|
# Set what is de default expected output type of GraphQL requests. String
|
79
|
-
# combined with the previous setting has the best performance. On
|
80
|
-
# it will automatically shift to
|
87
|
+
# combined with the previous setting has the best performance. On the
|
88
|
+
# console, it will automatically shift to Hash. This can also be set per
|
89
|
+
# Schema.
|
81
90
|
config.default_response_format = :string
|
82
91
|
|
83
92
|
# Specifies if the results of operations should be encoded with
|
@@ -85,60 +94,63 @@ module Rails
|
|
85
94
|
# See also https://github.com/rails/rails/blob/master/activesupport/lib/active_support/json/encoding.rb
|
86
95
|
config.encode_with_active_support = false
|
87
96
|
|
88
|
-
# Enable the ability of a callback to
|
97
|
+
# Enable the ability of a callback to inject arguments dynamically into the
|
89
98
|
# calling method.
|
90
99
|
config.callback_inject_arguments = true
|
91
100
|
|
92
|
-
# Enable the ability of a callback to
|
93
|
-
#
|
101
|
+
# Enable the ability of a callback to inject named arguments dynamically
|
102
|
+
# into the calling method.
|
94
103
|
config.callback_inject_named_arguments = true
|
95
104
|
|
96
|
-
# When importing fields
|
97
|
-
#
|
98
|
-
#
|
105
|
+
# When importing fields from modules or other objects, a warning is
|
106
|
+
# displayed for any given element that was not able to be correctly
|
107
|
+
# imported. You can silence such warnings by changing this option.
|
99
108
|
config.silence_import_warnings = false
|
100
109
|
|
101
|
-
# Enable the ability to
|
102
|
-
|
110
|
+
# Enable the ability to define the description of any object, field, or
|
111
|
+
# argument using I18n. It is recommended for multi-language documentation.
|
112
|
+
config.enable_i18n_descriptions = false
|
103
113
|
|
104
|
-
#
|
114
|
+
# The list of scopes that will be used to locate the descriptions.
|
105
115
|
config.i18n_scopes = [
|
106
116
|
'graphql.%{namespace}.%{kind}.%{parent}.%{name}',
|
107
117
|
'graphql.%{namespace}.%{kind}.%{name}',
|
108
118
|
'graphql.%{namespace}.%{name}',
|
109
119
|
'graphql.%{kind}.%{parent}.%{name}',
|
110
120
|
'graphql.%{kind}.%{name}',
|
111
|
-
'graphql.%{name}'
|
121
|
+
'graphql.%{name}',
|
112
122
|
]
|
113
123
|
|
114
|
-
# A list of execution strategies. Each application can add
|
115
|
-
#
|
124
|
+
# A list of execution strategies. Each application can add its own by
|
125
|
+
# appending a class, preferably as a string, in this list. This can also be
|
126
|
+
# set per Schema.
|
116
127
|
config.request_strategies = [
|
117
128
|
'Rails::GraphQL::Request::Strategy::MultiQueryStrategy',
|
118
129
|
'Rails::GraphQL::Request::Strategy::SequencedStrategy',
|
119
130
|
# 'Rails::GraphQL::Request::Strategy::CachedStrategy',
|
120
131
|
]
|
121
132
|
|
122
|
-
# A list of all possible
|
133
|
+
# A list of all possible ruby-to-graphql compatible sources.
|
123
134
|
config.sources = [
|
124
135
|
'Rails::GraphQL::Source::ActiveRecordSource',
|
125
136
|
]
|
126
137
|
|
127
|
-
# A list of all available subscription providers
|
128
|
-
# Rails::GraphQL::SubscriptionProvider::Base
|
138
|
+
# A list of all available subscription providers.
|
129
139
|
config.subscription_providers = [
|
130
140
|
'Rails::GraphQL::Subscription::Provider::ActionCable',
|
131
141
|
]
|
132
142
|
|
133
|
-
# The default subscription provider for all
|
143
|
+
# The default subscription provider for all schemas. This can also be set
|
144
|
+
# per Schema.
|
134
145
|
config.default_subscription_provider = config.subscription_providers.first
|
135
146
|
|
136
|
-
# The default value for fields about their ability
|
147
|
+
# The default value for fields about their ability to be broadcasted. This
|
148
|
+
# can also be set per Schema.
|
137
149
|
config.default_subscription_broadcastable = nil
|
138
150
|
|
139
151
|
# A list of known dependencies that can be requested and included in any
|
140
|
-
#
|
141
|
-
#
|
152
|
+
# Schema. This is the best place for other gems to add their own resources
|
153
|
+
# and allow users to enable them.
|
142
154
|
config.known_dependencies = {
|
143
155
|
scalar: {
|
144
156
|
any: "#{__dir__}/type/scalar/any_scalar",
|
@@ -150,18 +162,22 @@ module Rails
|
|
150
162
|
time: "#{__dir__}/type/scalar/time_scalar",
|
151
163
|
json: "#{__dir__}/type/scalar/json_scalar",
|
152
164
|
},
|
165
|
+
enum: {},
|
166
|
+
input: {},
|
167
|
+
interface: {},
|
168
|
+
object: {},
|
169
|
+
union: {},
|
153
170
|
directive: {
|
154
171
|
# cached: "#{__dir__}/directive/cached_directive",
|
155
172
|
},
|
156
173
|
}
|
157
174
|
|
158
|
-
# The method that should be used to parse literal input values when they
|
159
|
-
#
|
160
|
-
# to support keys without quotes,
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
# +->(value) { anything }+
|
175
|
+
# The method that should be used to parse literal input values when they are
|
176
|
+
# provided as Hash. `JSON.parse` only supports keys wrapped in quotes. You
|
177
|
+
# can use `Psych.method(:safe_load)` to support keys without quotes, which
|
178
|
+
# behaves closer to YAML. The received value is ensured to be wrapped in
|
179
|
+
# "{}". If that produces unexpected results, you can assign a proc and then
|
180
|
+
# parse the value in any other way.
|
165
181
|
config.literal_input_parser = JSON.method(:parse)
|
166
182
|
|
167
183
|
# TODO: To be implemented
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module GraphQL
|
5
|
+
# = GraphQL Spec Specified By Directive
|
6
|
+
#
|
7
|
+
# Provides a scalar specification URL for specifying the behavior of
|
8
|
+
# custom scalar types.
|
9
|
+
class Directive::SpecifiedByDirective < Directive
|
10
|
+
self.spec_object = true
|
11
|
+
|
12
|
+
placed_on :scalar
|
13
|
+
|
14
|
+
desc <<~DESC
|
15
|
+
A built-in directive used within the type system definition language to provide
|
16
|
+
a scalar specification URL for specifying the behavior of custom scalar types.
|
17
|
+
DESC
|
18
|
+
|
19
|
+
argument :url, :string, null: false, desc: <<~DESC
|
20
|
+
Point to a human-readable specification of the data format.
|
21
|
+
DESC
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -44,6 +44,13 @@ module Rails
|
|
44
44
|
:directive
|
45
45
|
end
|
46
46
|
|
47
|
+
# Ensure to return the directive class
|
48
|
+
def base_type
|
49
|
+
GraphQL::Directive
|
50
|
+
end
|
51
|
+
|
52
|
+
alias gid_base_class base_type
|
53
|
+
|
47
54
|
# Return the name of the object as a GraphQL name, ensure to use the
|
48
55
|
# first letter as lower case when being auto generated
|
49
56
|
def gql_name
|
@@ -71,11 +78,6 @@ module Rails
|
|
71
78
|
@locations = list.to_set
|
72
79
|
end
|
73
80
|
|
74
|
-
# Ensure to return the directive class
|
75
|
-
def gid_base_class
|
76
|
-
GraphQL::Directive
|
77
|
-
end
|
78
|
-
|
79
81
|
# A helper method that allows directives to be initialized while
|
80
82
|
# correctly parsing the arguments
|
81
83
|
def build(**xargs)
|
@@ -97,10 +99,11 @@ module Rails
|
|
97
99
|
def inspect
|
98
100
|
return super if eql?(GraphQL::Directive)
|
99
101
|
|
102
|
+
repeatable = ' [repeatable]' if repeatable?
|
100
103
|
args = all_arguments&.each_value&.map(&:inspect)
|
101
104
|
args = args.force if args.respond_to?(:force)
|
102
105
|
args = args.presence && "(#{args.join(', ')})"
|
103
|
-
+"#<GraphQL::Directive @#{gql_name}#{args}>"
|
106
|
+
+"#<GraphQL::Directive @#{gql_name}#{repeatable}#{args}>"
|
104
107
|
end
|
105
108
|
|
106
109
|
private
|
@@ -141,30 +144,23 @@ module Rails
|
|
141
144
|
Invalid locations for @#{gql_name}: #{invalid.force.to_sentence}.
|
142
145
|
MSG
|
143
146
|
end
|
144
|
-
|
145
|
-
# Allows checking value existence
|
146
|
-
def respond_to_missing?(method_name, *)
|
147
|
-
(const_defined?(method_name) rescue nil) || autoload?(method_name) || super
|
148
|
-
end
|
149
|
-
|
150
|
-
# Allow fast creation of values
|
151
|
-
def method_missing(method_name, *args, **xargs, &block)
|
152
|
-
const_get(method_name)&.new(*args, **xargs, &block) || super
|
153
|
-
rescue ::NameError
|
154
|
-
super
|
155
|
-
end
|
156
147
|
end
|
157
148
|
|
149
|
+
# Marks if the directive may be used repeatedly at a single location
|
150
|
+
class_attribute :repeatable, instance_accessor: false, default: false
|
151
|
+
|
158
152
|
self.abstract = true
|
159
153
|
|
160
154
|
autoload :DeprecatedDirective
|
161
155
|
autoload :IncludeDirective
|
162
156
|
autoload :SkipDirective
|
157
|
+
autoload :SpecifiedByDirective
|
163
158
|
|
164
159
|
autoload :CachedDirective
|
165
160
|
|
166
|
-
delegate :locations, :gql_name, :gid_base_class, to: :class
|
161
|
+
delegate :locations, :gql_name, :gid_base_class, :repeatable?, to: :class
|
167
162
|
|
163
|
+
# TODO: This filters are a bit confusing now, but `for` is working for @deprecated
|
168
164
|
event_filter(:for) do |options, event|
|
169
165
|
sanitize_objects(options).any?(&event.source.method(:of_type?))
|
170
166
|
end
|
@@ -177,7 +173,7 @@ module Rails
|
|
177
173
|
event.key?(:phase) && GraphQL.enumerate(options).include?(event[:phase])
|
178
174
|
end
|
179
175
|
|
180
|
-
attr_reader :args
|
176
|
+
attr_reader :args, :event
|
181
177
|
|
182
178
|
def initialize(args = nil, **xargs)
|
183
179
|
@args = args || OpenStruct.new(xargs.transform_keys { |key| key.to_s.underscore })
|
@@ -211,10 +207,11 @@ module Rails
|
|
211
207
|
|
212
208
|
# When fetching all the events, embed the actual instance as the context
|
213
209
|
# of the callback
|
210
|
+
# TODO: Maybe add a soft cached, based on the total number of events
|
214
211
|
def all_events
|
215
212
|
return unless self.class.events?
|
216
213
|
|
217
|
-
|
214
|
+
self.class.all_events.transform_values do |events|
|
218
215
|
events.map { |item| Callback.set_context(item, self) }
|
219
216
|
end
|
220
217
|
end
|
@@ -237,18 +234,27 @@ module Rails
|
|
237
234
|
MSG
|
238
235
|
end
|
239
236
|
|
237
|
+
# This allows combining directives
|
238
|
+
def +(other)
|
239
|
+
[self, other].flatten
|
240
|
+
end
|
241
|
+
|
242
|
+
alias_method :&, :+
|
243
|
+
|
240
244
|
def inspect
|
241
|
-
args = all_arguments&.
|
245
|
+
args = all_arguments&.filter_map do |name, arg|
|
242
246
|
+"#{arg.gql_name}: #{@args[name].inspect}" unless @args[name].nil?
|
243
|
-
end
|
247
|
+
end
|
244
248
|
|
245
249
|
args = args.presence && +"(#{args.join(', ')})"
|
250
|
+
repeatable = ' [repeatable]' if repeatable?
|
246
251
|
unbound = ' # unbound' unless defined?(@owner)
|
247
|
-
+"@#{gql_name}#{args}#{unbound}"
|
252
|
+
+"@#{gql_name}#{repeatable}#{args}#{unbound}"
|
248
253
|
end
|
249
254
|
|
250
255
|
%i[to_global_id to_gid to_gid_param].each do |method_name|
|
251
256
|
define_method(method_name) do
|
257
|
+
# TODO: The option is kind of broken, because they should always be a Hash
|
252
258
|
self.class.public_send(method_name, args_as_json&.compact || '')
|
253
259
|
end
|
254
260
|
end
|
data/lib/rails/graphql/event.rb
CHANGED
@@ -7,7 +7,7 @@ module Rails
|
|
7
7
|
# This class is responsible for triggering events. It also contains the
|
8
8
|
# +data+ that can be used on the event handlers.
|
9
9
|
class Event
|
10
|
-
attr_reader :source, :data, :
|
10
|
+
attr_reader :source, :data, :event_name, :object, :last_result
|
11
11
|
|
12
12
|
alias event itself
|
13
13
|
|
@@ -34,7 +34,7 @@ module Rails
|
|
34
34
|
@collect = data.delete(:collect?)
|
35
35
|
@reverse = data.delete(:reverse?)
|
36
36
|
|
37
|
-
@
|
37
|
+
@event_name = name
|
38
38
|
@data = data
|
39
39
|
@source = source
|
40
40
|
@layers = []
|
@@ -42,9 +42,10 @@ module Rails
|
|
42
42
|
|
43
43
|
# Check if the provided +other+ is equal to the source of the event. If
|
44
44
|
# other is a directive, then check if the source is using that directive
|
45
|
+
# TODO: Other cannot be an instance
|
45
46
|
def same_source?(other)
|
46
47
|
if other.is_a?(Directive) || (other.is_a?(Module) && other < Directive)
|
47
|
-
source.using?(other)
|
48
|
+
event_name == :attach || source.using?(other)
|
48
49
|
else
|
49
50
|
source == other
|
50
51
|
end
|
@@ -81,6 +82,8 @@ module Rails
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
85
|
+
alias on_instance set_on
|
86
|
+
|
84
87
|
# From the list of all given objects, run the +trigger_object+
|
85
88
|
def trigger_all(*objects)
|
86
89
|
catchable(:stack) do
|
@@ -102,7 +105,7 @@ module Rails
|
|
102
105
|
old_items, old_object, old_result, @object = @items, @object, @last_result, object
|
103
106
|
|
104
107
|
catchable(:object) do
|
105
|
-
events ||= object.all_events.try(:[],
|
108
|
+
events ||= object.all_events.try(:[], event_name)
|
106
109
|
stop if events.blank?
|
107
110
|
|
108
111
|
@items = @reverse ? events.reverse_each : events.each
|
@@ -136,8 +139,6 @@ module Rails
|
|
136
139
|
# Do not do anything when missing next/super
|
137
140
|
end
|
138
141
|
|
139
|
-
alias call_super call_next
|
140
|
-
|
141
142
|
protected
|
142
143
|
|
143
144
|
alias args_source itself
|
@@ -16,11 +16,6 @@ module Rails
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
# Just add the callbacks setup to the field
|
20
|
-
def self.included(other)
|
21
|
-
other.event_types(:authorize, append: true)
|
22
|
-
end
|
23
|
-
|
24
19
|
# Add either settings for authorization or a block to be executed. It
|
25
20
|
# returns +self+ for chain purposes
|
26
21
|
def authorize(*args, **xargs, &block)
|
@@ -28,11 +28,6 @@ module Rails
|
|
28
28
|
@default = deserialize(@default) if @default.is_a?(::GQLParser::Token)
|
29
29
|
end
|
30
30
|
|
31
|
-
# Prevent input fields from being further configured using a block
|
32
|
-
def configure
|
33
|
-
raise ArgumentError, +'Input fields can\'t be further configured using blocks'
|
34
|
-
end
|
35
|
-
|
36
31
|
# Allow change the default value for the input
|
37
32
|
def apply_changes(**xargs, &block)
|
38
33
|
@default = xargs[:default] if xargs.key?(:default)
|
@@ -5,7 +5,7 @@ module Rails
|
|
5
5
|
# = GraphQL Mutation Field
|
6
6
|
#
|
7
7
|
# This is an extension of a normal output field, which just add extra
|
8
|
-
# validation and
|
8
|
+
# validation and insurance that the +perform+ step can be executed
|
9
9
|
#
|
10
10
|
# ==== Options
|
11
11
|
#
|
@@ -58,17 +58,16 @@ module Rails
|
|
58
58
|
# Get the performer that can be already defined or used through the
|
59
59
|
# +method_name+ if that is callable
|
60
60
|
def performer
|
61
|
-
@performer
|
62
|
-
|
63
|
-
|
61
|
+
return @performer if defined?(@performer)
|
62
|
+
|
63
|
+
@performer = callable?(perform_method_name)
|
64
|
+
@performer = Callback.new(self, :perform, perform_method_name) if @performer
|
64
65
|
end
|
65
66
|
|
66
67
|
# Ensures that the performer is defined
|
67
68
|
def validate!(*)
|
68
69
|
super if defined? super
|
69
70
|
|
70
|
-
binding.pry unless performer.present?
|
71
|
-
|
72
71
|
raise ValidationError, (+<<~MSG).squish unless performer.present?
|
73
72
|
The "#{gql_name}" mutation field must have a perform action through a given
|
74
73
|
block or a method named #{method_name} on #{owner.class.name}.
|
@@ -29,10 +29,12 @@ module Rails
|
|
29
29
|
include Field::TypedField
|
30
30
|
|
31
31
|
module Proxied # :nodoc: all
|
32
|
+
Field.proxyable_methods %w[broadcastable?], klass: self
|
33
|
+
|
32
34
|
def all_arguments
|
33
35
|
inherited = field.all_arguments
|
34
36
|
return inherited unless defined?(@arguments)
|
35
|
-
inherited.blank? ? super : inherited
|
37
|
+
inherited.blank? ? super : inherited.merge(super)
|
36
38
|
end
|
37
39
|
|
38
40
|
def has_argument?(name)
|
@@ -43,12 +45,17 @@ module Rails
|
|
43
45
|
super || field.arguments?
|
44
46
|
end
|
45
47
|
|
48
|
+
# TODO: Break events into directive/type/local
|
49
|
+
# because type events should only be added
|
50
|
+
# from the proxy
|
46
51
|
def all_events
|
47
52
|
if (inherited = super).nil?
|
48
53
|
field.all_events
|
49
54
|
elsif (proxied = field.all_events).nil?
|
50
55
|
inherited
|
51
56
|
else
|
57
|
+
# The order is reversed because events from
|
58
|
+
# the proxy must come first
|
52
59
|
Helpers.merge_hash_array(proxied, inherited)
|
53
60
|
end
|
54
61
|
end
|
@@ -163,6 +170,10 @@ module Rails
|
|
163
170
|
defined?(@broadcastable) && @broadcastable
|
164
171
|
end
|
165
172
|
|
173
|
+
def entry_point?
|
174
|
+
owner.is_a?(Helpers::WithSchemaFields)
|
175
|
+
end
|
176
|
+
|
166
177
|
protected
|
167
178
|
|
168
179
|
# Check if the given +value+ is a valid array as output
|
@@ -177,7 +188,7 @@ module Rails
|
|
177
188
|
|
178
189
|
# Properly display the owner section when the field is owned by a Schema
|
179
190
|
def inspect_owner
|
180
|
-
|
191
|
+
entry_point? ? +"#{owner.name}[:#{schema_type}]" : super
|
181
192
|
end
|
182
193
|
|
183
194
|
def proxied
|
@@ -25,10 +25,9 @@ module Rails
|
|
25
25
|
# * <tt>:alias</tt> - Same as the +:as+ key (defaults to nil).
|
26
26
|
module Field::ProxiedField
|
27
27
|
delegate_missing_to :field
|
28
|
-
delegate :leaf_type?, :array?, :internal?, :
|
29
|
-
:to_json, :as_json, :deserialize, :valid?, :proxied_owner, to: :field
|
28
|
+
delegate :leaf_type?, :array?, :internal?, :proxied_owner, to: :field
|
30
29
|
|
31
|
-
Field.proxyable_methods %w[name gql_name method_name
|
30
|
+
Field.proxyable_methods %w[name gql_name method_name description
|
32
31
|
null? nullable? enabled?], klass: self
|
33
32
|
|
34
33
|
def initialize(field, owner:, **xargs, &block)
|
@@ -49,7 +48,7 @@ module Rails
|
|
49
48
|
super || field == other
|
50
49
|
end
|
51
50
|
|
52
|
-
# Allow
|
51
|
+
# Allow changing most of the general kind-independent initialize settings
|
53
52
|
def apply_changes(**xargs, &block)
|
54
53
|
if (deprecated = xargs[:deprecated])
|
55
54
|
xargs[:directives] = ::Array.wrap(xargs[:directives])
|
@@ -62,7 +61,8 @@ module Rails
|
|
62
61
|
@directives = GraphQL.directives_to_set(xargs[:directives], source: self) \
|
63
62
|
if xargs.key?(:directives)
|
64
63
|
|
65
|
-
|
64
|
+
self.description = xargs[:desc] if xargs.key?(:desc)
|
65
|
+
self.description = xargs[:description] if xargs.key?(:description)
|
66
66
|
@enabled = xargs.fetch(:enabled, !xargs.fetch(:disabled, false)) \
|
67
67
|
if xargs.key?(:enabled) || xargs.key?(:disabled)
|
68
68
|
|
@@ -18,7 +18,7 @@ module Rails
|
|
18
18
|
|
19
19
|
# Just add the callbacks setup to the field
|
20
20
|
def self.included(other)
|
21
|
-
other.
|
21
|
+
other.send(:expose_events!, :organized, :finalize, :prepared, :prepare)
|
22
22
|
other.alias_method(:before_resolve, :prepare)
|
23
23
|
other.alias_method(:after_resolve, :finalize)
|
24
24
|
end
|