Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require resolve_type for loads: #4678

Merged
merged 1 commit into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions guides/mutations/mutation_classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ end

In the above examples, `loads:` is provided a concrete type, but it also supports abstract types (i.e. interfaces and unions).

### Resolving the type of loaded objects

When `loads:` gets an object from {{ "Schema.object_from_id" | api_doc }}, it passes that object to {{ "Schema.resolve_type" | api_doc }} to confirm that it resolves to the same type originally configured with `loads:`.

### Handling failed loads

If `loads:` fails to find an object or if the loaded object isn't resolved to the specified `loads:` type (using {{ "Schema.resolve_type" | api_doc }}), a {{ "GraphQL::LoadApplicationObjectFailedError" | api_doc }} is raised and returned to the client.
Expand Down
2 changes: 2 additions & 0 deletions guides/schema/definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class MySchema < GraphQL::Schema
end
```

`resolve_type` is also used by `loads:` to confirm that loaded objects match the configured type.

__`object_from_id`__ is used by the `node(id: ID!): Node` field and `loads:` configuration. It receives a unique ID and must return the object for that ID, or `nil` if the object isn't found (or if it should be hidden from the current user).
__`id_from_object`__ is used to implement `Node.id`. It should return a unique ID for the given object. This ID will later be sent to `object_from_id` to refetch the object.

Expand Down
6 changes: 1 addition & 5 deletions lib/graphql/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -931,11 +931,7 @@ def resolve_type(type, obj, ctx)
end

def resolve_type(type, obj, ctx)
if type.kind.object?
type
else
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types or Interface types (tried to resolve: #{type.name})"
end
raise GraphQL::RequiredImplementationMissingError, "#{self.name}.resolve_type(type, obj, ctx) must be implemented to use Union types, Interface types, or `loads:` (tried to resolve: #{type.name})"
end
# rubocop:enable Lint/DuplicateMethods

Expand Down
4 changes: 4 additions & 0 deletions spec/graphql/dataloader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,10 @@ class Schema < GraphQL::Schema
def self.object_from_id(id, ctx)
ctx.dataloader.with(Example::FooSource).request(id)
end

def self.resolve_type(type, obj, ctx)
type
end
end
end

Expand Down
4 changes: 4 additions & 0 deletions spec/graphql/schema/argument_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ def self.object_from_id(id, ctx)
-> { Jazz::GloballyIdentifiableType.find(id) }
end

def self.resolve_type(type, obj, ctx)
-> { type } # just for `loads:`
end

orphan_types [Jazz::InstrumentType, UnauthorizedInstrumentType]
end
end
Expand Down
4 changes: 4 additions & 0 deletions spec/graphql/schema/resolver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,10 @@ def self.object_from_id(id, ctx)
end
end

def self.resolve_type(type, obj, ctx)
type # This will work for loaded objects well enough
end

rescue_from SpecialError do |err|
raise GraphQL::ExecutionError, "A special error was raised from #{err.id.inspect}"
end
Expand Down
4 changes: 4 additions & 0 deletions spec/graphql/schema/subscription_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ def self.object_from_id(id, ctx)
USERS[id]
end

def self.resolve_type(type, obj, ctx)
User
end

def self.unauthorized_field(err)
path = err.context[:last_path]
raise GraphQL::ExecutionError, "Can't subscribe to private user (#{path})"
Expand Down