README.md in graphql-relay-0.10.0 vs README.md in graphql-relay-0.11.0
- old
+ new
@@ -3,12 +3,13 @@
[![Gem Version](https://badge.fury.io/rb/graphql-relay.svg)](http://badge.fury.io/rb/graphql-relay)
[![Build Status](https://travis-ci.org/rmosolgo/graphql-relay-ruby.svg?branch=master)](https://travis-ci.org/rmosolgo/graphql-relay-ruby)
[![Code Climate](https://codeclimate.com/github/rmosolgo/graphql-relay-ruby/badges/gpa.svg)](https://codeclimate.com/github/rmosolgo/graphql-relay-ruby)
[![Test Coverage](https://codeclimate.com/github/rmosolgo/graphql-relay-ruby/badges/coverage.svg)](https://codeclimate.com/github/rmosolgo/graphql-relay-ruby/coverage)
-Helpers for using [`graphql`](https://github.com/rmosolgo/graphql-ruby) with Relay.
+Helpers for using [`graphql`](https://github.com/rmosolgo/graphql-ruby) with Relay. Includes support for serving Relay connections from `Array`s, `ActiveRecord::Relation`s and `Sequel::Dataset`s.
+
[API Documentation](http://www.rubydoc.info/github/rmosolgo/graphql-relay-ruby)
## Installation
```ruby
gem "graphql-relay"
@@ -113,11 +114,11 @@
`graphql-relay` will use those procs for interacting with global ids.
### Connections
-Connections provide pagination and `pageInfo` for `Array`s or `ActiveRecord::Relation`s.
+Connections provide pagination and `pageInfo` for `Array`s, `ActiveRecord::Relation`s or `Sequel::Dataset`s.
#### Connection fields
To define a connection field, use the `connection` helper. For a return type, get a type's `.connection_type`. For example:
@@ -134,10 +135,13 @@
You can also define custom arguments and a custom resolve function for connections, just like other fields:
```ruby
connection :featured_comments, CommentType.connection_type do
+ # Use a name to disambiguate this from `CommentType.connection_type`
+ name "CommentConnectionWithSince"
+
# Add an argument:
argument :since, types.String
# Return an Array or ActiveRecord::Relation
resolve -> (post, args, ctx) {
@@ -163,21 +167,124 @@
#### Connection types
You can customize a connection type with `.define_connection`:
```ruby
-PostType.define_connection do
+PostConnectionWithTotalCountType = PostType.define_connection do
field :totalCount do
type types.Int
# `obj` is the Connection, `obj.object` is the collection of Posts
resolve -> (obj, args, ctx) { obj.object.count }
end
end
+
```
-Now, `PostType.connection_type` will include a `totalCount` field.
+Now, you can use `PostConnectionWithTotalCountType` to define a connection with the "totalCount" field:
+```ruby
+AuthorType = GraphQL::ObjectType.define do
+ # Use the custom connection type:
+ connection :posts, PostConnectionWithTotalCountType
+end
+```
+
+#### Custom edge types
+
+If you need custom fields on `edge`s, you can define an edge type and pass it to a connection:
+
+```ruby
+# Person => Membership => Team
+MembershipSinceEdgeType = BaseType.define_edge do
+ name "MembershipSinceEdge"
+ field :memberSince, types.Int, "The date that this person joined this team" do
+ resolve -> (obj, args, ctx) {
+ obj # => GraphQL::Relay::Edge instnce
+ person = obj.parent
+ team = obj.node
+ membership = Membership.where(person: person, team: team).first
+ membership.created_at.to_i
+ }
+ end
+end
+```
+
+Then, pass the edge type when defining the connection type:
+
+```ruby
+TeamMembershipsConnectionType = TeamType.define_connection(edge_type: MembershipSinceEdgeType) do
+ # Use a name so it doesn't conflict with "TeamConnection"
+ name "TeamMembershipsConnection"
+end
+```
+
+Now, you can query custom fields on the `edge`:
+
+```graphql
+{
+ me {
+ teams {
+ edge {
+ memberSince # <= Here's your custom field
+ node {
+ teamName: name
+ }
+ }
+ }
+ }
+}
+```
+
+#### Custom Edge classes
+
+For more robust custom edges, you can define a custom edge class. It will be `obj` in the edge type's resolve function. For example, to define a membership edge:
+
+```ruby
+# Make sure to familiarize yourself with GraphQL::Relay::Edge --
+# you have to avoid naming conflicts here!
+class MembershipSinceEdge < GraphQL::Relay::Edge
+ # Cache `membership` to avoid multiple DB queries
+ def membership
+ @membership ||= begin
+ # "parent" and "node" are passed in from the surrounding Connection,
+ # See `Edge#initialize` for details
+ person = self.parent
+ team = self.node
+ Membership.where(person: person, team: team).first
+ end
+ end
+
+ def member_since
+ membership.created_at.to_i
+ end
+
+ def leader?
+ membership.leader?
+ end
+end
+```
+
+Then, hook it up with custom edge type and custom connection type:
+
+```ruby
+# Person => Membership => Team
+MembershipSinceEdgeType = BaseType.define_edge do
+ name "MembershipSinceEdge"
+ field :memberSince, types.Int, "The date that this person joined this team", property: :member_since
+ field :isPrimary, types.Boolean, "Is this person the team leader?". property: :primary?
+ end
+end
+
+TeamMembershipsConnectionType = TeamType.define_connection(
+ edge_class: MembershipSinceEdge,
+ edge_type: MembershipSinceEdgeType,
+ ) do
+ # Use a name so it doesn't conflict with "TeamConnection"
+ name "TeamMembershipsConnection"
+end
+```
+
#### Connection objects
Maybe you need to make a connection object yourself (for example, to return a connection type from a mutation). You can create a connection object like this:
```ruby
@@ -235,11 +342,10 @@
field = GraphQL::Field.new
# ... define the field
connection_field = GraphQL::Relay::ConnectionField.create(field)
```
-
### Mutations
Mutations allow Relay to mutate your system. They conform to a strict API which makes them predictable to the client.
### Mutation root
@@ -340,10 +446,9 @@
2. http://mgiroux.me/2015/getting-started-with-rails-graphql-relay/
3. http://mgiroux.me/2015/uploading-files-using-relay-with-rails/
## Todo
-- Allow custom edge fields (per connection type)
- `GlobalNodeIdentification.to_global_id` should receive the type name and _object_, not `id`. (Or, maintain the "`type_name, id` in, `type_name, id` out" pattern?)
- Make GlobalId a property of the schema, not a global
- Reduce duplication in ArrayConnection / RelationConnection
- Improve API for creating edges (better RANGE_ADD support)
- If the new edge isn't a member of the connection's objects, raise a nice error