graphql 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/lib/graphql.rb +24 -15
- data/lib/graphql/call.rb +1 -0
- data/lib/graphql/connection.rb +44 -0
- data/lib/graphql/field.rb +72 -7
- data/lib/graphql/field_definer.rb +6 -0
- data/lib/graphql/parser.rb +3 -0
- data/lib/graphql/query.rb +3 -1
- data/lib/graphql/root_call.rb +41 -28
- data/lib/graphql/root_call_argument.rb +1 -0
- data/lib/graphql/root_call_argument_definer.rb +1 -0
- data/lib/graphql/schema.rb +1 -1
- data/lib/graphql/transform.rb +1 -0
- data/lib/graphql/version.rb +1 -1
- data/readme.md +7 -7
- data/spec/graphql/field_spec.rb +1 -4
- data/spec/spec_helper.rb +3 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6184108ff2ba0151d12bfaeb02feeacbdeba74cc
|
4
|
+
data.tar.gz: 2a9cb034382d28f96a7e29024814848b63596a49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bb555f0b19ce78ea3f79ba7388f31509c26e2518fc1c207a25e83bcdd4f38e3670194bcb26a1447dc134a5949e58d10e12da79846bb2b3fb4dab0d688561a8a
|
7
|
+
data.tar.gz: 695837ba820b7709453584800eaa6d3f4082edc9d443055ab52d42e0db3b895189c2c10113a04d43e44c70726365621b99a878cc68a371acd85b46aeb05b925a
|
data/lib/graphql.rb
CHANGED
@@ -5,20 +5,21 @@ require "parslet"
|
|
5
5
|
require "singleton"
|
6
6
|
|
7
7
|
module GraphQL
|
8
|
-
autoload(:Call,
|
9
|
-
autoload(:Connection,
|
10
|
-
autoload(:Field,
|
11
|
-
autoload(:FieldDefiner,
|
12
|
-
autoload(:Node,
|
13
|
-
autoload(:Parser,
|
14
|
-
autoload(:Query,
|
15
|
-
autoload(:RootCall,
|
8
|
+
autoload(:Call, "graphql/call")
|
9
|
+
autoload(:Connection, "graphql/connection")
|
10
|
+
autoload(:Field, "graphql/field")
|
11
|
+
autoload(:FieldDefiner, "graphql/field_definer")
|
12
|
+
autoload(:Node, "graphql/node")
|
13
|
+
autoload(:Parser, "graphql/parser")
|
14
|
+
autoload(:Query, "graphql/query")
|
15
|
+
autoload(:RootCall, "graphql/root_call")
|
16
16
|
autoload(:RootCallArgument, "graphql/root_call_argument")
|
17
|
-
autoload(:RootCallArgumentDefiner,
|
18
|
-
autoload(:Schema,
|
19
|
-
autoload(:Transform,
|
20
|
-
autoload(:VERSION,
|
17
|
+
autoload(:RootCallArgumentDefiner, "graphql/root_call_argument_definer")
|
18
|
+
autoload(:Schema, "graphql/schema")
|
19
|
+
autoload(:Transform, "graphql/transform")
|
20
|
+
autoload(:VERSION, "graphql/version")
|
21
21
|
|
22
|
+
# These objects are used for introspections (eg, responding to `schema()` calls).
|
22
23
|
module Introspection
|
23
24
|
autoload(:CallNode, "graphql/introspection/call_node")
|
24
25
|
autoload(:Connection, "graphql/introspection/connection")
|
@@ -31,7 +32,7 @@ module GraphQL
|
|
31
32
|
autoload(:TypeNode, "graphql/introspection/type_node")
|
32
33
|
end
|
33
34
|
|
34
|
-
|
35
|
+
# These objects are skinny wrappers for going from the AST to actual {Node} and {Field} instances.
|
35
36
|
module Syntax
|
36
37
|
autoload(:Call, "graphql/syntax/call")
|
37
38
|
autoload(:Field, "graphql/syntax/field")
|
@@ -40,6 +41,7 @@ module GraphQL
|
|
40
41
|
autoload(:Variable, "graphql/syntax/variable")
|
41
42
|
end
|
42
43
|
|
44
|
+
# These fields wrap Ruby data types and some GraphQL internal values.
|
43
45
|
module Types
|
44
46
|
autoload(:BooleanField, "graphql/types/boolean_field")
|
45
47
|
autoload(:ConnectionField, "graphql/types/connection_field")
|
@@ -49,35 +51,41 @@ module GraphQL
|
|
49
51
|
autoload(:StringField, "graphql/types/string_field")
|
50
52
|
autoload(:TypeField, "graphql/types/type_field")
|
51
53
|
end
|
52
|
-
|
54
|
+
# @abstract
|
55
|
+
# Base class for all errors, so you can rescue from all graphql errors at once.
|
53
56
|
class Error < RuntimeError; end
|
57
|
+
# This node doesn't have a field with that name.
|
54
58
|
class FieldNotDefinedError < Error
|
55
59
|
def initialize(class_name, field_name)
|
56
60
|
super("#{class_name}##{field_name} was requested, but it isn't defined. Defined fields are: #{SCHEMA.field_names}")
|
57
61
|
end
|
58
62
|
end
|
63
|
+
# There's no Node defined for that kind of object.
|
59
64
|
class NodeNotDefinedError < Error
|
60
65
|
def initialize(node_name)
|
61
66
|
super("#{node_name} was requested but was not found. Defined nodes are: #{SCHEMA.type_names}")
|
62
67
|
end
|
63
68
|
end
|
69
|
+
# This node doesn't have a connection with that name.
|
64
70
|
class ConnectionNotDefinedError < Error
|
65
71
|
def initialize(node_name)
|
66
72
|
super("#{node_name} was requested but was not found. Defined connections are: #{SCHEMA.connection_names}")
|
67
73
|
end
|
68
74
|
end
|
75
|
+
# The root call of this query isn't in the schema.
|
69
76
|
class RootCallNotDefinedError < Error
|
70
77
|
def initialize(name)
|
71
78
|
super("Call '#{name}' was requested but was not found. Defined calls are: #{SCHEMA.call_names}")
|
72
79
|
end
|
73
80
|
end
|
81
|
+
# The query couldn't be parsed.
|
74
82
|
class SyntaxError < Error
|
75
83
|
def initialize(line, col, string)
|
76
84
|
lines = string.split("\n")
|
77
85
|
super("Syntax Error at (#{line}, #{col}), check usage: #{string}")
|
78
86
|
end
|
79
87
|
end
|
80
|
-
|
88
|
+
# This root call takes different arguments.
|
81
89
|
class RootCallArgumentError < Error
|
82
90
|
def initialize(declaration, actual)
|
83
91
|
super("Wrong type for #{declaration.name}: expected a #{declaration.type} but got #{actual}")
|
@@ -85,6 +93,7 @@ module GraphQL
|
|
85
93
|
end
|
86
94
|
|
87
95
|
PARSER = Parser.new
|
96
|
+
# This singleton contains all defined nodes and fields.
|
88
97
|
SCHEMA = Schema.instance
|
89
98
|
TRANSFORM = Transform.new
|
90
99
|
# preload these so they're in SCHEMA
|
data/lib/graphql/call.rb
CHANGED
data/lib/graphql/connection.rb
CHANGED
@@ -1,3 +1,44 @@
|
|
1
|
+
# {Connection}s wrap collections of objects.
|
2
|
+
#
|
3
|
+
# Out of the box, the only field it has is `edges`, which provides access to the members of the collection.
|
4
|
+
#
|
5
|
+
# You can define a custom {Connection} to use. This allows you to define fields at the collection level (rather than the item level)
|
6
|
+
#
|
7
|
+
# Custom fields can access the collection as {Field#items}.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class UpvotesConnection < GraphQL::Collection
|
11
|
+
# field.number(:count)
|
12
|
+
# field.boolean(:any)
|
13
|
+
#
|
14
|
+
# def count
|
15
|
+
# items.count
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def any
|
19
|
+
# items.any?
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # Then, this connection will be used for connections whose names match:
|
24
|
+
# class PostNode < GraphQL::Node
|
25
|
+
# field.connection(:upvotes)
|
26
|
+
# # ^^ uses `UpvotesConnection` based on naming convention
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # And you can use the fields in a query:
|
30
|
+
# <<QUERY
|
31
|
+
# find_post(10) {
|
32
|
+
# title,
|
33
|
+
# upvotes {
|
34
|
+
# count,
|
35
|
+
# any,
|
36
|
+
# edges {
|
37
|
+
# node { created_at }
|
38
|
+
# }
|
39
|
+
# }
|
40
|
+
# }
|
41
|
+
# QUERY
|
1
42
|
class GraphQL::Connection < GraphQL::Node
|
2
43
|
exposes "Array"
|
3
44
|
field.any(:edges)
|
@@ -10,6 +51,7 @@ class GraphQL::Connection < GraphQL::Node
|
|
10
51
|
@query = query
|
11
52
|
end
|
12
53
|
|
54
|
+
# Returns the members of the collection, after any calls on the corresponding {Field} have been applied
|
13
55
|
def items
|
14
56
|
@target
|
15
57
|
end
|
@@ -34,6 +76,8 @@ class GraphQL::Connection < GraphQL::Node
|
|
34
76
|
end
|
35
77
|
|
36
78
|
attr_accessor :default_connection
|
79
|
+
# Call this to make a the class the default connection
|
80
|
+
# when one isn't found by name.
|
37
81
|
def default_connection!
|
38
82
|
GraphQL::Connection.default_connection = self
|
39
83
|
end
|
data/lib/graphql/field.rb
CHANGED
@@ -1,3 +1,42 @@
|
|
1
|
+
# {Field}s are used to safely lookup values on {Node}s. When you define a custom field, you can access it from {Node.field}
|
2
|
+
#
|
3
|
+
# `graphql` has built-in fields for some Ruby data types:
|
4
|
+
# - `boolean`: {Types::BooleanField}
|
5
|
+
# - `number`: {Types::NumberField}
|
6
|
+
# - `string`: {Types::StringField}
|
7
|
+
#
|
8
|
+
# You can define custom fields that allow you to control how values are exposed.
|
9
|
+
# - {Field.type} defines how it can be used inside {Node.field} calls.
|
10
|
+
# - {Field.call} defines calls that can mutate the value before it is added to the response.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # For example, an `AddressField` which wraps a string but exposes address-specific information
|
14
|
+
# class AddressField < GraphQL::Field
|
15
|
+
# type :address
|
16
|
+
# # ^^ now you can use it with `field.address` in node definitions
|
17
|
+
#
|
18
|
+
# # calls can modify the value:
|
19
|
+
# # eg, get the numbers at the beginning:
|
20
|
+
# call :house_number, -> (prev_value) { prev_value[/^\d*/]}
|
21
|
+
# # get everything after a space:
|
22
|
+
# call :street_name, -> (prev_value) { prev_value[/\s.*$/].strip }
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # Then, use it in a node definition:
|
26
|
+
# class HouseNode < GraphQL::Node
|
27
|
+
# exposes("House")
|
28
|
+
# # create an `AddressField` for this node called `street_address`:
|
29
|
+
# field.address(:street_address)
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # Then, use the field in queries:
|
33
|
+
# <<QUERY
|
34
|
+
# find_house(1) {
|
35
|
+
# street_address,
|
36
|
+
# street_address.house_number() as number,
|
37
|
+
# street_address.street_name() as street,
|
38
|
+
# }
|
39
|
+
# QUERY
|
1
40
|
class GraphQL::Field
|
2
41
|
attr_reader :query, :owner, :calls, :fields
|
3
42
|
def initialize(query: nil, owner: nil, calls: [], fields: [])
|
@@ -8,7 +47,7 @@ class GraphQL::Field
|
|
8
47
|
end
|
9
48
|
|
10
49
|
def raw_value
|
11
|
-
owner.send(
|
50
|
+
owner.send(name)
|
12
51
|
end
|
13
52
|
|
14
53
|
def as_result
|
@@ -43,8 +82,6 @@ class GraphQL::Field
|
|
43
82
|
end
|
44
83
|
end
|
45
84
|
|
46
|
-
def method; name; end
|
47
|
-
|
48
85
|
class << self
|
49
86
|
def inherited(child_class)
|
50
87
|
GraphQL::SCHEMA.add_field(child_class)
|
@@ -72,7 +109,18 @@ class GraphQL::Field
|
|
72
109
|
super
|
73
110
|
end
|
74
111
|
end
|
75
|
-
|
112
|
+
# @param [Symbol] type_name the name used for getting this field from the {GraphQL::SCHEMA}.
|
113
|
+
# Defines the name used for getting fields of this type from the schema.
|
114
|
+
# @example
|
115
|
+
# # define the field with its type:
|
116
|
+
# class IPAddressField < GraphQL::Field
|
117
|
+
# type :ip_address
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# # then, attach fields of this type to your nodes:
|
121
|
+
# class ServerNode < GraphQL::Field
|
122
|
+
# field.ip_address(:static_ip_address)
|
123
|
+
# end
|
76
124
|
def type(value_type_name)
|
77
125
|
@value_type = value_type_name.to_s
|
78
126
|
GraphQL::SCHEMA.add_field(self)
|
@@ -103,14 +151,31 @@ class GraphQL::Field
|
|
103
151
|
rescue NoMethodError
|
104
152
|
{}
|
105
153
|
end
|
154
|
+
# @param [String] name the identifier for this call
|
155
|
+
# @param [lambda] operation the transformation this call makes
|
156
|
+
#
|
157
|
+
# Define a call that can be made on this field.
|
158
|
+
# The `lambda` receives arguments:
|
159
|
+
# - 1: `previous_value` -- the value of this field
|
160
|
+
# - *: arguments passed in the query (as strings)
|
161
|
+
#
|
162
|
+
# @example
|
163
|
+
# # upcase a string field:
|
164
|
+
# call :upcase, -> (prev_value) { prev_value.upcase }
|
165
|
+
# @example
|
166
|
+
# # tests a number field:
|
167
|
+
# call :greater_than, -> (prev_value, test_value) { prev_value > test_value.to_f }
|
168
|
+
# # (`test_value` is passed in as a string)
|
169
|
+
def call(name, lambda)
|
170
|
+
_calls[name.to_s] = GraphQL::Call.new(name: name.to_s, lambda: lambda)
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
106
174
|
|
107
175
|
def _calls
|
108
176
|
@calls ||= {}
|
109
177
|
end
|
110
178
|
|
111
|
-
def call(name, lambda)
|
112
|
-
_calls[name.to_s] = GraphQL::Call.new(name: name.to_s, lambda: lambda)
|
113
|
-
end
|
114
179
|
end
|
115
180
|
|
116
181
|
type :any
|
@@ -1,9 +1,13 @@
|
|
1
|
+
# Every {Node} class has a {FieldDefiner} instance that
|
2
|
+
# enables the `field.{something}` API.
|
1
3
|
class GraphQL::FieldDefiner
|
2
4
|
attr_reader :owner_class
|
3
5
|
def initialize(owner_class)
|
4
6
|
@owner_class = owner_class
|
5
7
|
end
|
6
8
|
|
9
|
+
# `method_name` is used as a field type and looked up against {GraphQL::SCHEMA}.
|
10
|
+
# `args[0]` is the name for the field of that type.
|
7
11
|
def method_missing(method_name, *args, &block)
|
8
12
|
type = GraphQL::SCHEMA.get_field(method_name)
|
9
13
|
if type.present?
|
@@ -13,6 +17,8 @@ class GraphQL::FieldDefiner
|
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
20
|
+
private
|
21
|
+
|
16
22
|
def create_field(field_name, type: nil, description: nil)
|
17
23
|
field_name = field_name.to_s
|
18
24
|
field_class = GraphQL::Field.create_class({
|
data/lib/graphql/parser.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# Parser is a [parslet](http://kschiess.github.io/parslet/) parser for parsing queries.
|
2
|
+
#
|
3
|
+
# If it failes to parse, a {SyntaxError} is raised.
|
1
4
|
class GraphQL::Parser < Parslet::Parser
|
2
5
|
root(:query)
|
3
6
|
rule(:query) { node.repeat.as(:nodes) >> variable.repeat.as(:variables) }
|
data/lib/graphql/query.rb
CHANGED
@@ -7,7 +7,9 @@
|
|
7
7
|
# result = query.as_result
|
8
8
|
|
9
9
|
class GraphQL::Query
|
10
|
-
|
10
|
+
# This is the object passed to {#initialize} as `context:`
|
11
|
+
attr_reader :context
|
12
|
+
attr_reader :query_string, :root
|
11
13
|
|
12
14
|
# @param [String] query_string the string to be parsed
|
13
15
|
# @param [Object] context an object which will be available to all nodes and fields in the schema
|
data/lib/graphql/root_call.rb
CHANGED
@@ -34,6 +34,8 @@
|
|
34
34
|
#
|
35
35
|
class GraphQL::RootCall
|
36
36
|
attr_reader :query, :arguments
|
37
|
+
|
38
|
+
# Validates arguments against declared {.argument}s
|
37
39
|
def initialize(query:, syntax_arguments:)
|
38
40
|
@query = query
|
39
41
|
|
@@ -46,18 +48,23 @@ class GraphQL::RootCall
|
|
46
48
|
syntax_arg
|
47
49
|
end
|
48
50
|
|
49
|
-
|
51
|
+
typecast(idx, value)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
55
|
+
# @param [Array] args (splat) all args provided in query string (as strings)
|
56
|
+
# This method is invoked with the arguments provided to the query.
|
57
|
+
# It should do work and return values matching the {.returns} declarations
|
53
58
|
def execute!(*args)
|
54
59
|
raise NotImplementedError, "Do work in this method"
|
55
60
|
end
|
56
61
|
|
62
|
+
# The object passed to {Query#initialize} as `context`
|
57
63
|
def context
|
58
64
|
query.context
|
59
65
|
end
|
60
66
|
|
67
|
+
# Executes the call, validates the return values against declared {.returns}, then returns the return values.
|
61
68
|
def as_result
|
62
69
|
return_declarations = self.class.return_declarations
|
63
70
|
raise "#{self.class.name} must declare returns" unless return_declarations.present?
|
@@ -123,7 +130,10 @@ class GraphQL::RootCall
|
|
123
130
|
end
|
124
131
|
|
125
132
|
# @return [GraphQL::RootCallArgumentDefiner] definer
|
126
|
-
# Use this object to declare arguments.
|
133
|
+
# Use this object to declare arguments. They must be declared in order
|
134
|
+
# @example
|
135
|
+
# argument.string("post_title")
|
136
|
+
# argument.object("comment_data") # allows a JSON object
|
127
137
|
def argument
|
128
138
|
@argument ||= GraphQL::RootCallArgumentDefiner.new(self)
|
129
139
|
end
|
@@ -138,39 +148,42 @@ class GraphQL::RootCall
|
|
138
148
|
rescue NoMethodError
|
139
149
|
own
|
140
150
|
end
|
151
|
+
end
|
141
152
|
|
142
|
-
|
143
|
-
if arguments.first.any_number
|
144
|
-
arguments.first
|
145
|
-
else
|
146
|
-
arguments[idx]
|
147
|
-
end
|
148
|
-
end
|
153
|
+
private
|
149
154
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
+
TYPE_CHECKS = {
|
156
|
+
"object" => Hash,
|
157
|
+
"number" => Numeric,
|
158
|
+
"string" => String,
|
159
|
+
}
|
155
160
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
161
|
+
def argument_for_index(idx)
|
162
|
+
if self.class.arguments.first.any_number
|
163
|
+
self.class.arguments.first
|
164
|
+
else
|
165
|
+
self.class.arguments[idx]
|
166
|
+
end
|
167
|
+
end
|
160
168
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
169
|
+
def typecast(idx, value)
|
170
|
+
arg_dec = argument_for_index(idx)
|
171
|
+
expected_type = arg_dec.type
|
172
|
+
expected_type_class = TYPE_CHECKS[expected_type]
|
166
173
|
|
167
|
-
|
168
|
-
|
169
|
-
|
174
|
+
if expected_type == "string"
|
175
|
+
parsed_value = value
|
176
|
+
else
|
177
|
+
parsed_value = JSON.parse('{ "value" : ' + value + '}')["value"]
|
178
|
+
end
|
170
179
|
|
171
|
-
|
172
|
-
rescue JSON::ParserError
|
180
|
+
if !parsed_value.is_a?(expected_type_class)
|
173
181
|
raise GraphQL::RootCallArgumentError.new(arg_dec, value)
|
174
182
|
end
|
183
|
+
|
184
|
+
parsed_value
|
185
|
+
rescue JSON::ParserError
|
186
|
+
raise GraphQL::RootCallArgumentError.new(arg_dec, value)
|
175
187
|
end
|
188
|
+
|
176
189
|
end
|
data/lib/graphql/schema.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# {GraphQL::SCHEMA} keeps track of defined nodes, fields and calls.
|
2
|
+
#
|
2
3
|
# Although you don't interact with it directly, it responds to queries for `schema()` and `__type__` info.
|
3
|
-
|
4
4
|
class GraphQL::Schema
|
5
5
|
include Singleton
|
6
6
|
attr_reader :types, :calls, :fields, :class_names, :connections
|
data/lib/graphql/transform.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# {Transform} is a [parslet](http://kschiess.github.io/parslet/) transform for for turning the AST into objects in {GraphQL::Syntax}.
|
1
2
|
class GraphQL::Transform < Parslet::Transform
|
2
3
|
# query
|
3
4
|
rule(nodes: sequence(:n), variables: sequence(:v)) { GraphQL::Syntax::Query.new(nodes: n, variables: v)}
|
data/lib/graphql/version.rb
CHANGED
data/readme.md
CHANGED
@@ -3,30 +3,31 @@
|
|
3
3
|
[](https://travis-ci.org/rmosolgo/graphql-ruby)
|
4
4
|
[](https://rubygems.org/gems/graphql)
|
5
5
|
[](https://gemnasium.com/rmosolgo/graphql-ruby)
|
6
|
+
[](https://codeclimate.com/github/rmosolgo/graphql-ruby)
|
7
|
+
[](https://codeclimate.com/github/rmosolgo/graphql-ruby)
|
8
|
+

|
6
9
|
|
10
|
+
Create a GraphQL interface by implementing [__nodes__](#nodes) and [__calls__](#calls), then running [__queries__](#queries).
|
7
11
|
|
8
|
-
|
12
|
+
API Docs: <http://rubydoc.info/gems/graphql>
|
9
13
|
|
10
14
|
## To do:
|
11
15
|
|
12
|
-
|
13
16
|
- Allow a default connection class, or some way to infer connection from name
|
14
17
|
- right now, `Introspection::Connection` isn't getting used, only `ApplicationConnection` is.
|
15
|
-
|
16
18
|
- How do you express failure? HTTP response? `errors` key?
|
17
|
-
- Handle blank objects in nested calls
|
19
|
+
- Handle blank objects in nested calls (how? wait for spec)
|
18
20
|
- Implement calls as arguments
|
19
21
|
- double-check how to handle `pals.first(3) { count }`
|
20
22
|
- Implement call argument introspection (wait for spec)
|
21
23
|
- For fields that return objects, can they be queried _without_ other fields? Or must they always have fields?
|
22
|
-
- __document__ (wait for spec)
|
23
24
|
|
24
25
|
## Example Implementation
|
25
26
|
|
26
27
|
- See test implementation in [`/spec/support/dummy_app/nodes.rb`](https://github.com/rmosolgo/graphql/blob/master/spec/support/nodes.rb)
|
27
28
|
- See `graphql-ruby-demo` with Rails on [github](https://github.com/rmosolgo/graphql-ruby-demo) or [heroku](http://graphql-ruby-demo.herokuapp.com/)
|
28
29
|
|
29
|
-
|
30
|
+
<a href="http://graphql-ruby-demo.herokuapp.com/" target="_blank"><img src="https://cloud.githubusercontent.com/assets/2231765/6217972/5d24edda-b5ce-11e4-9e07-3548304af862.png" style="max-width: 800px;"/></a>
|
30
31
|
|
31
32
|
|
32
33
|
## Usage
|
@@ -147,4 +148,3 @@ result
|
|
147
148
|
```
|
148
149
|
|
149
150
|
You could do something like this [inside a Rails controller](https://github.com/rmosolgo/graphql-ruby-demo/blob/master/app/controllers/queries_controller.rb#L5).
|
150
|
-
|
data/spec/graphql/field_spec.rb
CHANGED
@@ -9,11 +9,8 @@ describe GraphQL::Field do
|
|
9
9
|
it 'is present' do
|
10
10
|
assert_equal field.name, "high_fives"
|
11
11
|
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#method' do
|
15
12
|
it 'defaults to name' do
|
16
|
-
assert_equal "high_fives", field.
|
13
|
+
assert_equal "high_fives", field.name
|
17
14
|
end
|
18
15
|
end
|
19
16
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 1.6.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: codeclimate-test-reporter
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.4'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: pry
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,7 +218,7 @@ files:
|
|
204
218
|
- spec/spec_helper.rb
|
205
219
|
- spec/support/dummy_app.rb
|
206
220
|
- spec/support/nodes.rb
|
207
|
-
homepage: http://github.com/rmosolgo/graphql
|
221
|
+
homepage: http://github.com/rmosolgo/graphql-ruby
|
208
222
|
licenses:
|
209
223
|
- MIT
|
210
224
|
metadata: {}
|