Skip to content

Commit

Permalink
Merge pull request #5116 from Shopify/elvin/fix-extension-instantiation
Browse files Browse the repository at this point in the history
bug fix: extensions can register more extensions via apply method
  • Loading branch information
rmosolgo authored Oct 4, 2024
2 parents 6d57bba + ca493a0 commit cbebcfa
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 11 deletions.
23 changes: 12 additions & 11 deletions lib/graphql/schema/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CON
@ast_node = ast_node
@method_conflict_warning = method_conflict_warning
@fallback_value = fallback_value
@definition_block = nil
@definition_block = definition_block

arguments.each do |name, arg|
case arg
Expand All @@ -332,14 +332,15 @@ def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CON
@subscription_scope = subscription_scope

@extensions = EMPTY_ARRAY
@call_after_define = false
set_pagination_extensions(connection_extension: connection_extension)
# Do this last so we have as much context as possible when initializing them:
if extensions.any?
self.extensions(extensions, call_after_define: false)
self.extensions(extensions)
end

if resolver_class && resolver_class.extensions.any?
self.extensions(resolver_class.extensions, call_after_define: false)
self.extensions(resolver_class.extensions)
end

if directives.any?
Expand All @@ -352,10 +353,9 @@ def initialize(type: nil, name: nil, owner: nil, null: nil, description: NOT_CON
self.validates(validates)
end

if block_given?
@definition_block = definition_block
else
if @definition_block.nil?
self.extensions.each(&:after_define_apply)
@call_after_define = true
end
end

Expand All @@ -372,6 +372,7 @@ def ensure_loaded
instance_eval(&@definition_block)
end
self.extensions.each(&:after_define_apply)
@call_after_define = true
@definition_block = nil
end
self
Expand Down Expand Up @@ -435,14 +436,14 @@ def comment(text = nil)
#
# @param extensions [Array<Class, Hash<Class => Hash>>] Add extensions to this field. For hash elements, only the first key/value is used.
# @return [Array<GraphQL::Schema::FieldExtension>] extensions to apply to this field
def extensions(new_extensions = nil, call_after_define: !@definition_block)
def extensions(new_extensions = nil)
if new_extensions
new_extensions.each do |extension_config|
if extension_config.is_a?(Hash)
extension_class, options = *extension_config.to_a[0]
self.extension(extension_class, call_after_define: call_after_define, **options)
self.extension(extension_class, **options)
else
self.extension(extension_config, call_after_define: call_after_define)
self.extension(extension_config)
end
end
end
Expand All @@ -460,12 +461,12 @@ def extensions(new_extensions = nil, call_after_define: !@definition_block)
# @param extension_class [Class] subclass of {Schema::FieldExtension}
# @param options [Hash] if provided, given as `options:` when initializing `extension`.
# @return [void]
def extension(extension_class, call_after_define: !@definition_block, **options)
def extension(extension_class, **options)
extension_inst = extension_class.new(field: self, options: options)
if @extensions.frozen?
@extensions = @extensions.dup
end
if call_after_define
if @call_after_define
extension_inst.after_define_apply
end
@extensions << extension_inst
Expand Down
21 changes: 21 additions & 0 deletions spec/graphql/schema/field_extension_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ def after_resolve(value:, object:, **_args)
end
end

class AddNestedExtensionExtension < GraphQL::Schema::FieldExtension
def apply
field.extension(NestedExtension)
end

class NestedExtension < GraphQL::Schema::FieldExtension
def resolve(**_args)
1
end
end
end

class BaseObject < GraphQL::Schema::Object
end

Expand Down Expand Up @@ -154,6 +166,8 @@ def pass_thru_without_splat(input:)
end

field :object_class_test, [String], null: false, extensions: [ObjectClassExtension]

field :nested_extension, Integer, null: false, extensions: [AddNestedExtensionExtension]
end

class Schema < GraphQL::Schema
Expand Down Expand Up @@ -236,6 +250,13 @@ def exec_query(query_str, **kwargs)
end
end

describe "nested extension in apply method" do
it "applies the nested extension" do
res = exec_query("{ nestedExtension }")
assert_equal 1, res["data"]["nestedExtension"]
end
end

describe "after_define" do
class AfterDefineThing < GraphQL::Schema::Object
class AfterDefineExtension < GraphQL::Schema::FieldExtension
Expand Down

0 comments on commit cbebcfa

Please sign in to comment.