graphql 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/graph_ql/argument.rb +38 -4
  3. data/lib/graph_ql/boolean_type.rb +3 -5
  4. data/lib/graph_ql/definition_helpers.rb +1 -0
  5. data/lib/graph_ql/definition_helpers/defined_by_config.rb +20 -0
  6. data/lib/graph_ql/enum_type.rb +52 -16
  7. data/lib/graph_ql/field.rb +79 -14
  8. data/lib/graph_ql/float_type.rb +3 -3
  9. data/lib/graph_ql/id_type.rb +3 -5
  10. data/lib/graph_ql/input_object_type.rb +41 -4
  11. data/lib/graph_ql/int_type.rb +3 -5
  12. data/lib/graph_ql/interface_type.rb +36 -8
  13. data/lib/graph_ql/introspection/arguments_field.rb +4 -4
  14. data/lib/graph_ql/introspection/directive_type.rb +9 -11
  15. data/lib/graph_ql/introspection/enum_value_type.rb +9 -12
  16. data/lib/graph_ql/introspection/enum_values_field.rb +6 -8
  17. data/lib/graph_ql/introspection/field_type.rb +11 -15
  18. data/lib/graph_ql/introspection/fields_field.rb +5 -7
  19. data/lib/graph_ql/introspection/input_fields_field.rb +5 -5
  20. data/lib/graph_ql/introspection/input_value_type.rb +7 -9
  21. data/lib/graph_ql/introspection/interfaces_field.rb +4 -4
  22. data/lib/graph_ql/introspection/of_type_field.rb +5 -5
  23. data/lib/graph_ql/introspection/possible_types_field.rb +4 -4
  24. data/lib/graph_ql/introspection/schema_field.rb +6 -8
  25. data/lib/graph_ql/introspection/schema_type.rb +19 -25
  26. data/lib/graph_ql/introspection/type_by_name_field.rb +7 -1
  27. data/lib/graph_ql/introspection/type_kind_enum.rb +4 -4
  28. data/lib/graph_ql/introspection/type_type.rb +18 -18
  29. data/lib/graph_ql/introspection/typename_field.rb +6 -10
  30. data/lib/graph_ql/object_type.rb +87 -12
  31. data/lib/graph_ql/scalar_type.rb +22 -0
  32. data/lib/graph_ql/schema.rb +1 -1
  33. data/lib/graph_ql/string_type.rb +3 -5
  34. data/lib/graph_ql/union_type.rb +24 -3
  35. data/lib/graph_ql/version.rb +1 -1
  36. data/lib/graphql.rb +1 -1
  37. data/readme.md +66 -64
  38. data/spec/graph_ql/field_spec.rb +3 -3
  39. data/spec/support/dairy_app.rb +119 -133
  40. data/spec/support/dairy_data.rb +1 -1
  41. data/spec/support/star_wars_schema.rb +50 -57
  42. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a35f790dd696036b5c7ea909517a2108891d2732
4
- data.tar.gz: 795e06d90a94be917cf6ffaf911d00e5c14faade
3
+ metadata.gz: 9a73d6da0ba5269a9b68a0bdd479058ac4b65783
4
+ data.tar.gz: fb49181fff74d8a45fa7ac2d6ef941ce9a20eedd
5
5
  SHA512:
6
- metadata.gz: e62e25e0fedcbb6509d55d8f539f766d82429bafa3d278dde5fa3ca45420bc2a6cbbc3262b465a6f936ec76fcbb8296f4c7977cb8fdfd4581b818503570be372
7
- data.tar.gz: e863e0d3699bb9233f96da31af72e42422cc18c0f1765f2446851f65e76c67a7c16bcd1862b863e048aced999fca335c0a7d1c6dfbbefb3a0981499c74bfa84a
6
+ metadata.gz: 7fc070deec02d1ad30a5f6807692010920a0ee69395205a1cf11f1dd98ec3ebb1ea55ca228c60e5165d03644cdf38a8a1649c9025e00d46cdb72e715acd2e586
7
+ data.tar.gz: b22f2cbe6338c2d30f1a6b1ca6d772d49d6ba396370f519b473105c61ae512e5605e891ca1f53936f8f41d08d49e4e8d1615f759cc34ebb646a22ad20cc0d755
@@ -1,10 +1,44 @@
1
1
  # Used for defined arguments ({Field}, {InputObjectType})
2
2
  #
3
- # Created by {ArgumentDefiner}
3
+ # @example defining an argument for a field
4
+ # GraphQL::Field.define do
5
+ # # ...
6
+ # argument :favoriteFood, types.String, "Favorite thing to eat", default_value: "pizza"
7
+ # end
8
+ #
9
+ # @example defining an input field for an {InputObjectType}
10
+ # GraphQL::InputObjectType.define do
11
+ # input_field :newName, !types.String
12
+ # end
13
+ #
4
14
  class GraphQL::Argument
5
- attr_reader :type, :description, :default_value
6
- attr_accessor :name
7
- def initialize(type:, description: nil, default_value: nil, name: nil)
15
+ attr_accessor :name, :type, :description, :default_value
16
+
17
+ include GraphQL::DefinitionHelpers::DefinedByConfig
18
+
19
+ # This object is `self` when you're defining arguments with a block.
20
+ # @example `argument` helper's `self` is a DefinitionConfig
21
+ #
22
+ # argument :name do
23
+ # puts self.class.name
24
+ # end
25
+ # # => GraphQL::Argument::DefinitionConfig
26
+ #
27
+ class DefinitionConfig
28
+ extend GraphQL::DefinitionHelpers::Definable
29
+ attr_definable :type, :description, :default_value, :name
30
+
31
+ def to_instance
32
+ GraphQL::Argument.new(
33
+ type: type,
34
+ description: description,
35
+ default_value: default_value,
36
+ name: name,
37
+ )
38
+ end
39
+ end
40
+
41
+ def initialize(type: nil, description: nil, default_value: nil, name: nil)
8
42
  @type = type
9
43
  @description = description,
10
44
  @default_value = default_value
@@ -1,6 +1,4 @@
1
- GraphQL::BOOLEAN_TYPE = GraphQL::ScalarType.new do |t|
2
- t.name "Boolean"
3
- def t.coerce(value)
4
- !!value
5
- end
1
+ GraphQL::BOOLEAN_TYPE = GraphQL::ScalarType.define do
2
+ name "Boolean"
3
+ coerce -> (value) { !!value }
6
4
  end
@@ -6,5 +6,6 @@ require 'graph_ql/definition_helpers/argument_definer'
6
6
  require 'graph_ql/definition_helpers/definable'
7
7
  require 'graph_ql/definition_helpers/field_definer'
8
8
  require 'graph_ql/definition_helpers/non_null_with_bang'
9
+ require 'graph_ql/definition_helpers/defined_by_config'
9
10
  require 'graph_ql/definition_helpers/string_named_hash'
10
11
  require 'graph_ql/definition_helpers/type_definer'
@@ -0,0 +1,20 @@
1
+ # Provide a two-step definition process.
2
+ #
3
+ # 1. Use a config object to gather definitions
4
+ # 2. Transfer definitions to an actual instance of an object
5
+ #
6
+ module GraphQL::DefinitionHelpers::DefinedByConfig
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ # Pass the block to this class's `DefinitionConfig`,
13
+ # The return the result of {DefinitionConfig#to_instance}
14
+ def define(&block)
15
+ config = self.const_get(:DefinitionConfig).new
16
+ block && config.instance_eval(&block)
17
+ config.to_instance
18
+ end
19
+ end
20
+ end
@@ -3,36 +3,68 @@
3
3
  #
4
4
  # @example An enum of programming languages
5
5
  #
6
- # LanguageEnum = GraphQL::EnumType.new do |e|
7
- # e.name("Languages")
8
- # e.descriptions("Programming languages for Web projects")
9
- # e.value("PYTHON", "A dynamic, function-oriented language")
10
- # e.value("RUBY", "A very dynamic language aimed at programmer happiness")
11
- # e.value("JAVASCRIPT", "Accidental lingua franca of the web")
6
+ # LanguageEnum = GraphQL::EnumType.define do
7
+ # name "Languages"
8
+ # description "Programming languages for Web projects"
9
+ # value("PYTHON", "A dynamic, function-oriented language")
10
+ # value("RUBY", "A very dynamic language aimed at programmer happiness")
11
+ # value("JAVASCRIPT", "Accidental lingua franca of the web")
12
12
  # end
13
13
  class GraphQL::EnumType
14
14
  include GraphQL::DefinitionHelpers::NonNullWithBang
15
+ include GraphQL::DefinitionHelpers::DefinedByConfig
15
16
  extend GraphQL::DefinitionHelpers::Definable
16
17
  attr_definable :name, :description
17
- attr_reader :values
18
+ attr_accessor :values
19
+
20
+ class DefinitionConfig
21
+ extend GraphQL::DefinitionHelpers::Definable
22
+ # These are deprecated:
23
+ attr_definable :name, :description
24
+ attr_reader :values
25
+ def initialize
26
+ @values = {}
27
+ end
28
+
29
+ def types
30
+ GraphQL::DefinitionHelpers::TypeDefiner.instance
31
+ end
32
+
33
+ def value(name, desc = nil, deprecation_reason: nil, value: name)
34
+ value = EnumValue.new(name: name, description: description, deprecation_reason: deprecation_reason, value: value)
35
+ values[name] = value
36
+ end
37
+
38
+ def to_instance
39
+ object = GraphQL::EnumType.new
40
+ object.name = name
41
+ object.description = description
42
+ object.values = values
43
+ object
44
+ end
45
+ end
46
+
18
47
  def initialize
19
48
  @values = {}
20
- yield(
21
- self,
22
- GraphQL::DefinitionHelpers::TypeDefiner.instance,
23
- GraphQL::DefinitionHelpers::FieldDefiner.instance,
24
- GraphQL::DefinitionHelpers::ArgumentDefiner.instance
25
- )
49
+ if block_given?
50
+ yield(
51
+ self,
52
+ GraphQL::DefinitionHelpers::TypeDefiner.instance,
53
+ GraphQL::DefinitionHelpers::FieldDefiner.instance,
54
+ GraphQL::DefinitionHelpers::ArgumentDefiner.instance
55
+ )
56
+ warn("Initializing with .new is deprecated, use .define instead! (see #{self})")
57
+ end
26
58
  end
27
59
 
28
60
  # Define a value within this enum
29
- #
61
+ # @deprecated use {.define} API instead
30
62
  # @param name [String] the string representation of this value
31
63
  # @param description [String]
32
64
  # @param deprecation_reason [String] if provided, `deprecated?` will be true
33
65
  # @param value [Object] the underlying value for this enum value
34
66
  def value(name, description=nil, deprecation_reason: nil, value: name)
35
- @values[name] = EnumValue.new(name: name, description: description, deprecation_reason: deprecation_reason, value: value)
67
+ values[name] = EnumValue.new(name: name, description: description, deprecation_reason: deprecation_reason, value: value)
36
68
  end
37
69
 
38
70
  def kind
@@ -48,7 +80,11 @@ class GraphQL::EnumType
48
80
  # @param value_name [String] the string representation of this enum value
49
81
  # @return [Object] the underlying value for this enum value
50
82
  def coerce(value_name)
51
- @values[value_name].value
83
+ values[value_name].value
84
+ end
85
+
86
+ def to_s
87
+ name
52
88
  end
53
89
 
54
90
  # A value within an {EnumType}
@@ -1,28 +1,83 @@
1
- # These are valid values for a type's `fields` hash.
1
+ # {Field}s belong to {ObjectType}s and {InterfaceType}s.
2
+ #
3
+ # They're usually created with the `field` helper.
2
4
  #
3
- # You can also use {FieldDefiner#build} to create fields.
4
5
  #
5
6
  # @example creating a field
6
- # name_field = GraphQL::Field.new do |f, types|
7
- # f.name("Name")
8
- # f.type(!types.String)
9
- # f.description("The name of this thing")
10
- # f.resolve -> (object, arguments, context) { object.name }
7
+ # GraphQL::ObjectType.define do
8
+ # field :name, types.String, "The name of this thing "
9
+ # end
10
+ #
11
+ # @example creating a field that accesses a different property on the object
12
+ # GraphQL::ObjectType.define do
13
+ # # use the `property` option:
14
+ # field :firstName, types.String, property: :first_name
15
+ # end
16
+ #
17
+ # @example defining a field, then attaching it to a type
18
+ # name_field = GraphQL::Field.define do
19
+ # name("Name")
20
+ # type(!types.String)
21
+ # description("The name of this thing")
22
+ # resolve -> (object, arguments, context) { object.name }
23
+ # end
24
+ #
25
+ # NamedType = GraphQL::ObjectType.define do
26
+ # # use the `field` option:
27
+ # field :name, field: name_field
11
28
  # end
12
29
  #
13
30
  class GraphQL::Field
31
+ DEFAULT_RESOLVE = -> (o, a, c) { GraphQL::Query::DEFAULT_RESOLVE }
32
+ include GraphQL::DefinitionHelpers::DefinedByConfig
33
+ # These are deprecated:
14
34
  extend GraphQL::DefinitionHelpers::Definable
15
35
  attr_definable(:arguments, :deprecation_reason, :name, :description, :type)
16
36
 
37
+ class DefinitionConfig
38
+ extend GraphQL::DefinitionHelpers::Definable
39
+ attr_definable :name, :description, :type, :deprecation_reason, :resolve
40
+ def initialize
41
+ @arguments = {}
42
+ end
43
+
44
+ def types
45
+ GraphQL::DefinitionHelpers::TypeDefiner.instance
46
+ end
47
+
48
+ def argument(name, type, description = nil, default_value: nil)
49
+ @arguments[name.to_s] = GraphQL::Argument.new(
50
+ name: name.to_s,
51
+ type: type,
52
+ description: description,
53
+ default_value: nil,
54
+ )
55
+ end
56
+
57
+ def to_instance
58
+ object = GraphQL::Field.new
59
+ object.name = name
60
+ object.type = type
61
+ object.description = description
62
+ object.deprecation_reason = deprecation_reason
63
+ object.resolve = resolve
64
+ object.arguments = @arguments
65
+ object
66
+ end
67
+ end
68
+
17
69
  def initialize
18
70
  @arguments = {}
19
- @resolve_proc = -> (o, a, c) { GraphQL::Query::DEFAULT_RESOLVE }
20
- yield(
21
- self,
22
- GraphQL::DefinitionHelpers::TypeDefiner.instance,
23
- GraphQL::DefinitionHelpers::FieldDefiner.instance,
24
- GraphQL::DefinitionHelpers::ArgumentDefiner.instance
25
- )
71
+ @resolve_proc = DEFAULT_RESOLVE
72
+ if block_given?
73
+ yield(
74
+ self,
75
+ GraphQL::DefinitionHelpers::TypeDefiner.instance,
76
+ GraphQL::DefinitionHelpers::FieldDefiner.instance,
77
+ GraphQL::DefinitionHelpers::ArgumentDefiner.instance
78
+ )
79
+ warn("Initializing with .new is deprecated, use .define instead! (see #{self})")
80
+ end
26
81
  end
27
82
 
28
83
  def arguments(new_arguments=nil)
@@ -38,6 +93,7 @@ class GraphQL::Field
38
93
  end
39
94
 
40
95
  # @overload resolve(definition_proc)
96
+ # @deprecated use {.define} API instead
41
97
  # Define this field to return a value with `definition_proc`
42
98
  # @example defining the resolve method
43
99
  # field.resolve -> (obj, args, ctx) { obj.get_value }
@@ -59,7 +115,12 @@ class GraphQL::Field
59
115
  end
60
116
  end
61
117
 
118
+ def resolve=(resolve_proc)
119
+ @resolve_proc = resolve_proc || DEFAULT_RESOLVE
120
+ end
121
+
62
122
  # @overload type(return_type)
123
+ # @deprecated use {.define} API instead
63
124
  # Define the return type for this field
64
125
  # @param return_type [GraphQL::ObjectType, GraphQL::ScalarType] The type this field returns
65
126
  #
@@ -79,4 +140,8 @@ class GraphQL::Field
79
140
  end
80
141
  @type
81
142
  end
143
+
144
+ def to_s
145
+ "<Field: #{name || "not-named"}>"
146
+ end
82
147
  end
@@ -1,6 +1,6 @@
1
- GraphQL::FLOAT_TYPE = GraphQL::ScalarType.new do |t|
2
- t.name "Float"
3
- def t.coerce(value)
1
+ GraphQL::FLOAT_TYPE = GraphQL::ScalarType.define do
2
+ name "Float"
3
+ coerce -> (value) do
4
4
  value.respond_to?(:to_f) ? value.to_f : nil
5
5
  end
6
6
  end
@@ -1,6 +1,4 @@
1
- GraphQL::ID_TYPE = GraphQL::ScalarType.new do |t|
2
- t.name "ID"
3
- def t.coerce(value)
4
- value.to_s
5
- end
1
+ GraphQL::ID_TYPE = GraphQL::ScalarType.define do
2
+ name "ID"
3
+ coerce -> (value) { value.to_s }
6
4
  end
@@ -10,9 +10,44 @@
10
10
  # end
11
11
  #
12
12
  class GraphQL::InputObjectType < GraphQL::ObjectType
13
+ # Deprecated:
13
14
  attr_definable :input_fields
14
15
 
16
+ class DefinitionConfig
17
+ extend GraphQL::DefinitionHelpers::Definable
18
+ attr_definable :name, :description, :input_fields
19
+ def initialize
20
+ @input_fields = {}
21
+ end
22
+
23
+ def types
24
+ GraphQL::DefinitionHelpers::TypeDefiner.instance
25
+ end
26
+
27
+ def input_field(name, type = nil, desc = nil, default_value: nil, &block)
28
+ argument = if block_given?
29
+ GraphQL::Argument.define(&block)
30
+ else
31
+ GraphQL::Argument.new
32
+ end
33
+ argument.name = name
34
+ type && argument.type = type
35
+ desc && argument.desc = desc
36
+ default_value && argument.default_value = default_value
37
+ @input_fields[name.to_s] = argument
38
+ end
39
+
40
+ def to_instance
41
+ object = GraphQL::InputObjectType.new
42
+ object.name = name
43
+ object.description = description
44
+ object.input_fields = @input_fields
45
+ object
46
+ end
47
+ end
48
+
15
49
  # @overload input_fields(new_fields)
50
+ # @deprecated use {.define} API instead
16
51
  # Define allowed fields, normalized with {StringNamedHash}
17
52
  # @param new_fields [Hash] allowed fields for this input object type
18
53
  #
@@ -21,10 +56,12 @@ class GraphQL::InputObjectType < GraphQL::ObjectType
21
56
  # @return [Hash] allowed fields for this input object type
22
57
  #
23
58
  def input_fields(new_fields=nil)
24
- if !new_fields.nil?
25
- @new_fields = GraphQL::DefinitionHelpers::StringNamedHash.new(new_fields).to_h
26
- end
27
- @new_fields
59
+ new_fields && self.input_fields = new_fields
60
+ @input_fields
61
+ end
62
+
63
+ def input_fields=(new_fields)
64
+ @input_fields = GraphQL::DefinitionHelpers::StringNamedHash.new(new_fields).to_h
28
65
  end
29
66
 
30
67
  def kind
@@ -1,6 +1,4 @@
1
- GraphQL::INT_TYPE = GraphQL::ScalarType.new do |t|
2
- t.name "Int"
3
- def t.coerce(value)
4
- value.is_a?(Numeric) ? value.to_i : nil
5
- end
1
+ GraphQL::INT_TYPE = GraphQL::ScalarType.define do
2
+ name "Int"
3
+ coerce -> (value) { value.is_a?(Numeric) ? value.to_i : nil }
6
4
  end
@@ -1,14 +1,13 @@
1
1
  # A collection of types which implement the same fields
2
2
  #
3
3
  # @example An interface with three required fields
4
- # DeviceInterface = GraphQL::InterfaceType.new do |i, types, fields|
5
- # i.name("Device")
6
- # i.description("Hardware devices for computing")
7
- # i.fields({
8
- # ram: fields.build(type: types.String),
9
- # processor: fields.build(type: ProcessorType),
10
- # release_year: fields.build(type: types.Int),
11
- # })
4
+ # DeviceInterface = GraphQL::InterfaceType.define do
5
+ # name("Device")
6
+ # description("Hardware devices for computing")
7
+ #
8
+ # field :ram, types.String
9
+ # field :processor, ProcessorType
10
+ # field :release_year, types.Int
12
11
  # end
13
12
  #
14
13
  class GraphQL::InterfaceType < GraphQL::ObjectType
@@ -16,6 +15,35 @@ class GraphQL::InterfaceType < GraphQL::ObjectType
16
15
  GraphQL::TypeKinds::INTERFACE
17
16
  end
18
17
 
18
+ class DefinitionConfig
19
+ extend GraphQL::DefinitionHelpers::Definable
20
+ attr_definable :name, :description
21
+
22
+ def initialize
23
+ @fields = {}
24
+ end
25
+
26
+ def types
27
+ GraphQL::DefinitionHelpers::TypeDefiner.instance
28
+ end
29
+
30
+ def field(name, type = nil, desc = nil, property: nil, field: nil, &block)
31
+ field ||= GraphQL::Field.define(&block)
32
+ type && field.type = type
33
+ desc && field.description = desc
34
+ field.name ||= name.to_s
35
+ @fields[name.to_s] = field
36
+ end
37
+
38
+ def to_instance
39
+ object = GraphQL::InterfaceType.new
40
+ object.name = name
41
+ object.description = description
42
+ object.fields = @fields
43
+ object
44
+ end
45
+ end
46
+
19
47
  # @return [Array<GraphQL::ObjectType>] Types which declare that they implement this interface
20
48
  def possible_types
21
49
  @possible_types ||= []