rails-graphql 0.1.0

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.
Files changed (266) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +19 -0
  4. data/Rakefile +31 -0
  5. data/ext/depend +3 -0
  6. data/ext/extconf.rb +57 -0
  7. data/ext/graphqlparser/Ast.cpp +346 -0
  8. data/ext/graphqlparser/Ast.h +1214 -0
  9. data/ext/graphqlparser/AstNode.h +36 -0
  10. data/ext/graphqlparser/AstVisitor.h +137 -0
  11. data/ext/graphqlparser/GraphQLParser.cpp +76 -0
  12. data/ext/graphqlparser/GraphQLParser.h +55 -0
  13. data/ext/graphqlparser/JsonVisitor.cpp +161 -0
  14. data/ext/graphqlparser/JsonVisitor.cpp.inc +456 -0
  15. data/ext/graphqlparser/JsonVisitor.h +121 -0
  16. data/ext/graphqlparser/JsonVisitor.h.inc +110 -0
  17. data/ext/graphqlparser/VERSION +1 -0
  18. data/ext/graphqlparser/c/GraphQLAst.cpp +324 -0
  19. data/ext/graphqlparser/c/GraphQLAst.h +180 -0
  20. data/ext/graphqlparser/c/GraphQLAstForEachConcreteType.h +44 -0
  21. data/ext/graphqlparser/c/GraphQLAstNode.cpp +25 -0
  22. data/ext/graphqlparser/c/GraphQLAstNode.h +33 -0
  23. data/ext/graphqlparser/c/GraphQLAstToJSON.cpp +21 -0
  24. data/ext/graphqlparser/c/GraphQLAstToJSON.h +24 -0
  25. data/ext/graphqlparser/c/GraphQLAstVisitor.cpp +55 -0
  26. data/ext/graphqlparser/c/GraphQLAstVisitor.h +53 -0
  27. data/ext/graphqlparser/c/GraphQLParser.cpp +35 -0
  28. data/ext/graphqlparser/c/GraphQLParser.h +54 -0
  29. data/ext/graphqlparser/dump_json_ast.cpp +48 -0
  30. data/ext/graphqlparser/lexer.lpp +324 -0
  31. data/ext/graphqlparser/parser.ypp +693 -0
  32. data/ext/graphqlparser/parsergen/lexer.cpp +2633 -0
  33. data/ext/graphqlparser/parsergen/lexer.h +528 -0
  34. data/ext/graphqlparser/parsergen/location.hh +189 -0
  35. data/ext/graphqlparser/parsergen/parser.tab.cpp +3300 -0
  36. data/ext/graphqlparser/parsergen/parser.tab.hpp +646 -0
  37. data/ext/graphqlparser/parsergen/position.hh +179 -0
  38. data/ext/graphqlparser/parsergen/stack.hh +156 -0
  39. data/ext/graphqlparser/syntaxdefs.h +19 -0
  40. data/ext/libgraphqlparser/AstNode.h +36 -0
  41. data/ext/libgraphqlparser/CMakeLists.txt +148 -0
  42. data/ext/libgraphqlparser/CONTRIBUTING.md +23 -0
  43. data/ext/libgraphqlparser/GraphQLParser.cpp +76 -0
  44. data/ext/libgraphqlparser/GraphQLParser.h +55 -0
  45. data/ext/libgraphqlparser/JsonVisitor.cpp +161 -0
  46. data/ext/libgraphqlparser/JsonVisitor.h +121 -0
  47. data/ext/libgraphqlparser/LICENSE +22 -0
  48. data/ext/libgraphqlparser/README.clang-tidy +7 -0
  49. data/ext/libgraphqlparser/README.md +84 -0
  50. data/ext/libgraphqlparser/ast/ast.ast +203 -0
  51. data/ext/libgraphqlparser/ast/ast.py +61 -0
  52. data/ext/libgraphqlparser/ast/c.py +100 -0
  53. data/ext/libgraphqlparser/ast/c.pyc +0 -0
  54. data/ext/libgraphqlparser/ast/c_impl.py +61 -0
  55. data/ext/libgraphqlparser/ast/c_impl.pyc +0 -0
  56. data/ext/libgraphqlparser/ast/c_visitor_impl.py +39 -0
  57. data/ext/libgraphqlparser/ast/c_visitor_impl.pyc +0 -0
  58. data/ext/libgraphqlparser/ast/casing.py +26 -0
  59. data/ext/libgraphqlparser/ast/casing.pyc +0 -0
  60. data/ext/libgraphqlparser/ast/cxx.py +197 -0
  61. data/ext/libgraphqlparser/ast/cxx.pyc +0 -0
  62. data/ext/libgraphqlparser/ast/cxx_impl.py +61 -0
  63. data/ext/libgraphqlparser/ast/cxx_impl.pyc +0 -0
  64. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.py +42 -0
  65. data/ext/libgraphqlparser/ast/cxx_json_visitor_header.pyc +0 -0
  66. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.py +80 -0
  67. data/ext/libgraphqlparser/ast/cxx_json_visitor_impl.pyc +0 -0
  68. data/ext/libgraphqlparser/ast/cxx_visitor.py +64 -0
  69. data/ext/libgraphqlparser/ast/cxx_visitor.pyc +0 -0
  70. data/ext/libgraphqlparser/ast/js.py +65 -0
  71. data/ext/libgraphqlparser/ast/license.py +10 -0
  72. data/ext/libgraphqlparser/ast/license.pyc +0 -0
  73. data/ext/libgraphqlparser/c/GraphQLAstNode.cpp +25 -0
  74. data/ext/libgraphqlparser/c/GraphQLAstNode.h +33 -0
  75. data/ext/libgraphqlparser/c/GraphQLAstToJSON.cpp +21 -0
  76. data/ext/libgraphqlparser/c/GraphQLAstToJSON.h +24 -0
  77. data/ext/libgraphqlparser/c/GraphQLAstVisitor.cpp +55 -0
  78. data/ext/libgraphqlparser/c/GraphQLAstVisitor.h +53 -0
  79. data/ext/libgraphqlparser/c/GraphQLParser.cpp +35 -0
  80. data/ext/libgraphqlparser/c/GraphQLParser.h +54 -0
  81. data/ext/libgraphqlparser/clang-tidy-all.sh +3 -0
  82. data/ext/libgraphqlparser/cmake/version.cmake +16 -0
  83. data/ext/libgraphqlparser/dump_json_ast.cpp +48 -0
  84. data/ext/libgraphqlparser/go/README.md +20 -0
  85. data/ext/libgraphqlparser/go/callbacks.go +18 -0
  86. data/ext/libgraphqlparser/go/gotest.go +64 -0
  87. data/ext/libgraphqlparser/lexer.lpp +324 -0
  88. data/ext/libgraphqlparser/libgraphqlparser.pc.in +11 -0
  89. data/ext/libgraphqlparser/parser.ypp +693 -0
  90. data/ext/libgraphqlparser/parsergen/lexer.cpp +2633 -0
  91. data/ext/libgraphqlparser/parsergen/lexer.h +528 -0
  92. data/ext/libgraphqlparser/parsergen/location.hh +189 -0
  93. data/ext/libgraphqlparser/parsergen/parser.tab.cpp +3300 -0
  94. data/ext/libgraphqlparser/parsergen/parser.tab.hpp +646 -0
  95. data/ext/libgraphqlparser/parsergen/position.hh +179 -0
  96. data/ext/libgraphqlparser/parsergen/stack.hh +156 -0
  97. data/ext/libgraphqlparser/python/CMakeLists.txt +14 -0
  98. data/ext/libgraphqlparser/python/README.md +5 -0
  99. data/ext/libgraphqlparser/python/example.py +31 -0
  100. data/ext/libgraphqlparser/syntaxdefs.h +19 -0
  101. data/ext/libgraphqlparser/test/BuildCAPI.c +5 -0
  102. data/ext/libgraphqlparser/test/CMakeLists.txt +25 -0
  103. data/ext/libgraphqlparser/test/JsonVisitorTests.cpp +28 -0
  104. data/ext/libgraphqlparser/test/ParserTests.cpp +352 -0
  105. data/ext/libgraphqlparser/test/kitchen-sink.graphql +59 -0
  106. data/ext/libgraphqlparser/test/kitchen-sink.json +1 -0
  107. data/ext/libgraphqlparser/test/schema-kitchen-sink.graphql +78 -0
  108. data/ext/libgraphqlparser/test/schema-kitchen-sink.json +1 -0
  109. data/ext/libgraphqlparser/test/valgrind.supp +33 -0
  110. data/ext/version.cpp +21 -0
  111. data/lib/generators/graphql/controller_generator.rb +22 -0
  112. data/lib/generators/graphql/schema_generator.rb +22 -0
  113. data/lib/generators/graphql/templates/controller.erb +5 -0
  114. data/lib/generators/graphql/templates/schema.erb +6 -0
  115. data/lib/graphqlparser.so +0 -0
  116. data/lib/rails-graphql.rb +2 -0
  117. data/lib/rails/graphql.rake +1 -0
  118. data/lib/rails/graphql.rb +185 -0
  119. data/lib/rails/graphql/adapters/mysql_adapter.rb +0 -0
  120. data/lib/rails/graphql/adapters/pg_adapter.rb +50 -0
  121. data/lib/rails/graphql/adapters/sqlite_adapter.rb +39 -0
  122. data/lib/rails/graphql/argument.rb +220 -0
  123. data/lib/rails/graphql/callback.rb +124 -0
  124. data/lib/rails/graphql/collectors.rb +14 -0
  125. data/lib/rails/graphql/collectors/hash_collector.rb +83 -0
  126. data/lib/rails/graphql/collectors/idented_collector.rb +73 -0
  127. data/lib/rails/graphql/collectors/json_collector.rb +114 -0
  128. data/lib/rails/graphql/config.rb +61 -0
  129. data/lib/rails/graphql/directive.rb +203 -0
  130. data/lib/rails/graphql/directive/deprecated_directive.rb +59 -0
  131. data/lib/rails/graphql/directive/include_directive.rb +24 -0
  132. data/lib/rails/graphql/directive/skip_directive.rb +24 -0
  133. data/lib/rails/graphql/errors.rb +42 -0
  134. data/lib/rails/graphql/event.rb +141 -0
  135. data/lib/rails/graphql/field.rb +318 -0
  136. data/lib/rails/graphql/field/input_field.rb +92 -0
  137. data/lib/rails/graphql/field/mutation_field.rb +52 -0
  138. data/lib/rails/graphql/field/output_field.rb +96 -0
  139. data/lib/rails/graphql/field/proxied_field.rb +131 -0
  140. data/lib/rails/graphql/field/resolved_field.rb +96 -0
  141. data/lib/rails/graphql/field/scoped_config.rb +22 -0
  142. data/lib/rails/graphql/field/typed_field.rb +104 -0
  143. data/lib/rails/graphql/helpers.rb +40 -0
  144. data/lib/rails/graphql/helpers/attribute_delegator.rb +39 -0
  145. data/lib/rails/graphql/helpers/inherited_collection.rb +152 -0
  146. data/lib/rails/graphql/helpers/leaf_from_ar.rb +141 -0
  147. data/lib/rails/graphql/helpers/registerable.rb +103 -0
  148. data/lib/rails/graphql/helpers/with_arguments.rb +125 -0
  149. data/lib/rails/graphql/helpers/with_assignment.rb +113 -0
  150. data/lib/rails/graphql/helpers/with_callbacks.rb +55 -0
  151. data/lib/rails/graphql/helpers/with_directives.rb +126 -0
  152. data/lib/rails/graphql/helpers/with_events.rb +81 -0
  153. data/lib/rails/graphql/helpers/with_fields.rb +141 -0
  154. data/lib/rails/graphql/helpers/with_namespace.rb +40 -0
  155. data/lib/rails/graphql/helpers/with_owner.rb +35 -0
  156. data/lib/rails/graphql/helpers/with_schema_fields.rb +230 -0
  157. data/lib/rails/graphql/helpers/with_validator.rb +52 -0
  158. data/lib/rails/graphql/introspection.rb +53 -0
  159. data/lib/rails/graphql/native.rb +56 -0
  160. data/lib/rails/graphql/native/functions.rb +38 -0
  161. data/lib/rails/graphql/native/location.rb +41 -0
  162. data/lib/rails/graphql/native/pointers.rb +23 -0
  163. data/lib/rails/graphql/native/visitor.rb +349 -0
  164. data/lib/rails/graphql/railtie.rb +85 -0
  165. data/lib/rails/graphql/railties/base_generator.rb +35 -0
  166. data/lib/rails/graphql/railties/controller.rb +101 -0
  167. data/lib/rails/graphql/railties/controller_runtime.rb +40 -0
  168. data/lib/rails/graphql/railties/log_subscriber.rb +62 -0
  169. data/lib/rails/graphql/request.rb +343 -0
  170. data/lib/rails/graphql/request/arguments.rb +93 -0
  171. data/lib/rails/graphql/request/component.rb +100 -0
  172. data/lib/rails/graphql/request/component/field.rb +225 -0
  173. data/lib/rails/graphql/request/component/fragment.rb +118 -0
  174. data/lib/rails/graphql/request/component/operation.rb +178 -0
  175. data/lib/rails/graphql/request/component/operation/subscription.rb +16 -0
  176. data/lib/rails/graphql/request/component/spread.rb +119 -0
  177. data/lib/rails/graphql/request/component/typename.rb +82 -0
  178. data/lib/rails/graphql/request/context.rb +51 -0
  179. data/lib/rails/graphql/request/errors.rb +54 -0
  180. data/lib/rails/graphql/request/event.rb +112 -0
  181. data/lib/rails/graphql/request/helpers/directives.rb +64 -0
  182. data/lib/rails/graphql/request/helpers/selection_set.rb +87 -0
  183. data/lib/rails/graphql/request/helpers/value_writers.rb +115 -0
  184. data/lib/rails/graphql/request/steps/organizable.rb +146 -0
  185. data/lib/rails/graphql/request/steps/prepareable.rb +33 -0
  186. data/lib/rails/graphql/request/steps/resolveable.rb +32 -0
  187. data/lib/rails/graphql/request/strategy.rb +249 -0
  188. data/lib/rails/graphql/request/strategy/dynamic_instance.rb +41 -0
  189. data/lib/rails/graphql/request/strategy/multi_query_strategy.rb +36 -0
  190. data/lib/rails/graphql/request/strategy/sequenced_strategy.rb +28 -0
  191. data/lib/rails/graphql/schema.rb +272 -0
  192. data/lib/rails/graphql/shortcuts.rb +77 -0
  193. data/lib/rails/graphql/source.rb +371 -0
  194. data/lib/rails/graphql/source/active_record/builders.rb +154 -0
  195. data/lib/rails/graphql/source/active_record_source.rb +231 -0
  196. data/lib/rails/graphql/source/scoped_arguments.rb +87 -0
  197. data/lib/rails/graphql/to_gql.rb +368 -0
  198. data/lib/rails/graphql/type.rb +138 -0
  199. data/lib/rails/graphql/type/enum.rb +206 -0
  200. data/lib/rails/graphql/type/enum/directive_location_enum.rb +30 -0
  201. data/lib/rails/graphql/type/enum/type_kind_enum.rb +57 -0
  202. data/lib/rails/graphql/type/input.rb +134 -0
  203. data/lib/rails/graphql/type/interface.rb +82 -0
  204. data/lib/rails/graphql/type/object.rb +111 -0
  205. data/lib/rails/graphql/type/object/directive_object.rb +34 -0
  206. data/lib/rails/graphql/type/object/enum_value_object.rb +25 -0
  207. data/lib/rails/graphql/type/object/field_object.rb +54 -0
  208. data/lib/rails/graphql/type/object/input_value_object.rb +49 -0
  209. data/lib/rails/graphql/type/object/schema_object.rb +40 -0
  210. data/lib/rails/graphql/type/object/type_object.rb +136 -0
  211. data/lib/rails/graphql/type/scalar.rb +71 -0
  212. data/lib/rails/graphql/type/scalar/bigint_scalar.rb +34 -0
  213. data/lib/rails/graphql/type/scalar/binary_scalar.rb +30 -0
  214. data/lib/rails/graphql/type/scalar/boolean_scalar.rb +37 -0
  215. data/lib/rails/graphql/type/scalar/date_scalar.rb +34 -0
  216. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +32 -0
  217. data/lib/rails/graphql/type/scalar/decimal_scalar.rb +35 -0
  218. data/lib/rails/graphql/type/scalar/float_scalar.rb +32 -0
  219. data/lib/rails/graphql/type/scalar/id_scalar.rb +39 -0
  220. data/lib/rails/graphql/type/scalar/int_scalar.rb +36 -0
  221. data/lib/rails/graphql/type/scalar/string_scalar.rb +28 -0
  222. data/lib/rails/graphql/type/scalar/time_scalar.rb +40 -0
  223. data/lib/rails/graphql/type/union.rb +87 -0
  224. data/lib/rails/graphql/type_map.rb +347 -0
  225. data/lib/rails/graphql/version.rb +7 -0
  226. data/test/assets/introspection-db.json +0 -0
  227. data/test/assets/introspection-mem.txt +1 -0
  228. data/test/assets/introspection.gql +91 -0
  229. data/test/assets/luke.jpg +0 -0
  230. data/test/assets/mem.gql +428 -0
  231. data/test/assets/sqlite.gql +423 -0
  232. data/test/config.rb +80 -0
  233. data/test/graphql/request/context_test.rb +70 -0
  234. data/test/graphql/schema_test.rb +190 -0
  235. data/test/graphql/source_test.rb +237 -0
  236. data/test/graphql/type/enum_test.rb +203 -0
  237. data/test/graphql/type/input_test.rb +138 -0
  238. data/test/graphql/type/interface_test.rb +72 -0
  239. data/test/graphql/type/object_test.rb +104 -0
  240. data/test/graphql/type/scalar/bigint_scalar_test.rb +42 -0
  241. data/test/graphql/type/scalar/binary_scalar_test.rb +17 -0
  242. data/test/graphql/type/scalar/boolean_scalar_test.rb +40 -0
  243. data/test/graphql/type/scalar/date_scalar_test.rb +29 -0
  244. data/test/graphql/type/scalar/date_time_scalar_test.rb +29 -0
  245. data/test/graphql/type/scalar/decimal_scalar_test.rb +28 -0
  246. data/test/graphql/type/scalar/float_scalar_test.rb +22 -0
  247. data/test/graphql/type/scalar/id_scalar_test.rb +26 -0
  248. data/test/graphql/type/scalar/int_scalar_test.rb +26 -0
  249. data/test/graphql/type/scalar/string_scalar_test.rb +17 -0
  250. data/test/graphql/type/scalar/time_scalar_test.rb +36 -0
  251. data/test/graphql/type/scalar_test.rb +45 -0
  252. data/test/graphql/type/union_test.rb +82 -0
  253. data/test/graphql/type_map_test.rb +362 -0
  254. data/test/graphql/type_test.rb +68 -0
  255. data/test/graphql_test.rb +55 -0
  256. data/test/integration/config.rb +56 -0
  257. data/test/integration/memory/star_wars_introspection_test.rb +144 -0
  258. data/test/integration/memory/star_wars_query_test.rb +184 -0
  259. data/test/integration/memory/star_wars_validation_test.rb +99 -0
  260. data/test/integration/schemas/memory.rb +232 -0
  261. data/test/integration/schemas/sqlite.rb +82 -0
  262. data/test/integration/sqlite/star_wars_introspection_test.rb +15 -0
  263. data/test/integration/sqlite/star_wars_mutation_test.rb +82 -0
  264. data/test/integration/sqlite/star_wars_query_test.rb +71 -0
  265. data/test/test_ext.rb +48 -0
  266. metadata +509 -0
@@ -0,0 +1,232 @@
1
+ EPISODES = %w[new_hope empire jedi]
2
+
3
+ module MemoryTest
4
+ class Character
5
+ attr_accessor :id, :name
6
+ attr_writer :friends, :appears_in
7
+
8
+ def initialize(**data)
9
+ data.each { |k, v| send("#{k}=", v) }
10
+ end
11
+
12
+ def friends
13
+ @friends.map do |id|
14
+ STAR_WARS_DATA[:humans][id] || STAR_WARS_DATA[:droids][id]
15
+ end
16
+ end
17
+
18
+ def appears_in
19
+ @appears_in.map { |i| EPISODES[i].upcase }
20
+ end
21
+
22
+ def secret_backstory
23
+ raise 'Secret backstory is secret'
24
+ end
25
+ end
26
+
27
+ class Human < Character
28
+ attr_accessor :home_planet
29
+ end
30
+
31
+ class Droid < Character
32
+ attr_accessor :primary_function
33
+ end
34
+
35
+ STAR_WARS_DATA = {
36
+ humans: {
37
+ '1000' => Human.new(
38
+ id: '1000',
39
+ name: 'Luke Skywalker',
40
+ friends: ['1002', '1003', '2000', '2001'],
41
+ appears_in: [0, 1, 2],
42
+ home_planet: 'Tatooine'
43
+ ),
44
+ '1001' => Human.new(
45
+ id: '1001',
46
+ name: 'Darth Vader',
47
+ friends: ['1004'],
48
+ appears_in: [0, 1, 2],
49
+ home_planet: 'Tatooine'
50
+ ),
51
+ '1002' => Human.new(
52
+ id: '1002',
53
+ name: 'Han Solo',
54
+ friends: ['1000', '1003', '2001'],
55
+ appears_in: [0, 1, 2]
56
+ ),
57
+ '1003' => Human.new(
58
+ id: '1003',
59
+ name: 'Leia Organa',
60
+ friends: ['1000', '1002', '2000', '2001'],
61
+ appears_in: [0, 1, 2],
62
+ home_planet: 'Alderaan'
63
+ ),
64
+ '1004' => Human.new(
65
+ id: '1004',
66
+ name: 'Wilhuff Tarkin',
67
+ friends: ['1001'],
68
+ appears_in: [0]
69
+ ),
70
+ },
71
+ droids: {
72
+ '2000' => Droid.new(
73
+ id: '2000',
74
+ name: 'C-3PO',
75
+ friends: ['1000', '1002', '1003', '2001'],
76
+ appears_in: [0, 1, 2],
77
+ primary_function: 'Protocol'
78
+ ),
79
+ '2001' => Droid.new(
80
+ id: '2001',
81
+ name: 'R2-D2',
82
+ friends: ['1000', '1002', '1003'],
83
+ appears_in: [0, 1, 2],
84
+ primary_function: 'Astromech'
85
+ ),
86
+ },
87
+ }
88
+ end
89
+
90
+ class StartWarsMemSchema < GraphQL::Schema
91
+ namespace :start_wars_mem
92
+
93
+ configure do |config|
94
+ config.enable_string_collector = false
95
+ end
96
+
97
+ rescue_from('StandardError') do |exception|
98
+ !!field ? request.exception_to_error(exception, field) : raise
99
+ end
100
+
101
+ enum 'Episode' do
102
+ desc 'One of the films in the Star Wars Trilogy'
103
+
104
+ add 'NEW_HOPE', desc: 'Released in 1977.'
105
+ add 'EMPIRE', desc: 'Released in 1980.'
106
+ add 'JEDI', desc: 'Released in 1983.'
107
+ end
108
+
109
+ interface 'Character' do
110
+ desc 'A character in the Star Wars Trilogy'
111
+
112
+ field :id, :id, null: false,
113
+ desc: 'The id of the character'
114
+
115
+ field :name, :string,
116
+ desc: 'The name of the character'
117
+
118
+ field :friends, 'Character', array: true,
119
+ desc: 'The friends of the character, or an empty list if they have none'
120
+
121
+ field :appears_in, 'Episode', array: true,
122
+ desc: 'Which movies they appear in'
123
+
124
+ field :secret_backstory, :string,
125
+ desc: 'All secrets about their past'
126
+ end
127
+
128
+ object 'Human' do
129
+ self.assigned_to = MemoryTest::Human
130
+
131
+ implements 'Character'
132
+
133
+ desc 'A humanoid creature in the Star Wars universe'
134
+
135
+ change_field :id,
136
+ desc: 'The id of the human'
137
+
138
+ change_field :name,
139
+ desc: 'The name of the human'
140
+
141
+ change_field :friends,
142
+ desc: 'The friends of the human, or an empty list if they have none'
143
+
144
+ change_field :appears_in,
145
+ desc: 'Which movies they appear in'
146
+
147
+ change_field :secret_backstory,
148
+ desc: 'Where are they from and how they came to be who they are'
149
+
150
+ field :home_planet, :string,
151
+ desc: 'The home planet of the human, or null if unknown'
152
+ end
153
+
154
+ object 'Droid' do
155
+ self.assigned_to = MemoryTest::Droid
156
+
157
+ implements 'Character'
158
+
159
+ desc 'A mechanical creature in the Star Wars universe'
160
+
161
+ change_field :id,
162
+ desc: 'The id of the droid'
163
+
164
+ change_field :name,
165
+ desc: 'The name of the droid'
166
+
167
+ change_field :friends,
168
+ desc: 'The friends of the droid, or an empty list if they have none'
169
+
170
+ change_field :appears_in,
171
+ desc: 'Which movies they appear in'
172
+
173
+ change_field :secret_backstory,
174
+ desc: 'Construction date and the name of the designer'
175
+
176
+ field :primary_function, :string,
177
+ desc: 'The primary function of the droid'
178
+ end
179
+
180
+ query_fields do
181
+ field :hero, 'Character', method_name: :find_hero,
182
+ arguments: arg(:episode, 'Episode', desc: 'Return for a specific episode'),
183
+ desc: 'Find the hero of the whole saga'
184
+
185
+ field :human, 'Human', method_name: :find_human,
186
+ arguments: arg(:id, :id, null: false, desc: 'ID of the human'),
187
+ desc: 'Find a human character'
188
+
189
+ field :droid, 'Droid', method_name: :find_droid,
190
+ arguments: arg(:id, :id, null: false, desc: 'ID of the droid'),
191
+ desc: 'Find a droid character'
192
+ end
193
+
194
+ mutation_fields do
195
+ field :change_human, 'Character', full: true do
196
+ desc 'Change the episodes of a human and return a set of characters'
197
+
198
+ id_argument desc: 'The ID of the human to be changed'
199
+ argument :episodes, 'Episode', array: true, nullable: false
200
+
201
+ perform :change_episodes, :humans, episodes: %w[NEW_HOPE EMPIRE]
202
+ resolve :character_set
203
+ end
204
+ end
205
+
206
+ def find_hero(episode:)
207
+ episode.to_i === 1 \
208
+ ? MemoryTest::STAR_WARS_DATA[:humans]['1000'] \
209
+ : MemoryTest::STAR_WARS_DATA[:droids]['2001']
210
+ end
211
+
212
+ def find_human(id:)
213
+ MemoryTest::STAR_WARS_DATA[:humans][id]
214
+ end
215
+
216
+ def find_droid(id:)
217
+ MemoryTest::STAR_WARS_DATA[:droids][id]
218
+ end
219
+
220
+ def change_episodes(source, id:, episodes:)
221
+ MemoryTest::STAR_WARS_DATA[source][id].appears_in = episodes.map do |item|
222
+ EPISODES.index(item.downcase)
223
+ end
224
+ end
225
+
226
+ def character_set(id:)
227
+ [
228
+ MemoryTest::STAR_WARS_DATA[:humans][id],
229
+ MemoryTest::STAR_WARS_DATA[:droids]['2001'],
230
+ ]
231
+ end
232
+ end
@@ -0,0 +1,82 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
4
+
5
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
6
+ inflect.irregular 'base', 'bases'
7
+ end
8
+
9
+ ActiveRecord::Schema.define(version: 1) do
10
+ self.verbose = false
11
+
12
+ create_table 'lite_factions', force: :cascade do |t|
13
+ t.string 'name'
14
+ end
15
+
16
+ create_table 'lite_bases', force: :cascade do |t|
17
+ t.integer 'faction_id'
18
+ t.string 'name'
19
+ t.string 'planet'
20
+ end
21
+
22
+ create_table 'lite_ships', force: :cascade do |t|
23
+ t.integer 'faction_id'
24
+ t.string 'name'
25
+ end
26
+ end
27
+
28
+ class SQLiteRecord < ActiveRecord::Base
29
+ self.abstract_class = true
30
+ end
31
+
32
+ class LiteFaction < SQLiteRecord
33
+ has_many :bases, class_name: 'LiteBase', foreign_key: :faction_id
34
+ has_many :ships, class_name: 'LiteShip', foreign_key: :faction_id
35
+
36
+ accepts_nested_attributes_for :bases
37
+ accepts_nested_attributes_for :ships
38
+
39
+ REBELS = create!(name: 'Alliance to Restore the Republic')
40
+ EMPIRE = create!(name: 'Galactic Empire')
41
+ end
42
+
43
+ class LiteBase < SQLiteRecord
44
+ belongs_to :faction, class_name: 'LiteFaction', foreign_key: :faction_id
45
+
46
+ create!(name: 'Yavin', planet: 'Yavin 4', faction: LiteFaction::REBELS)
47
+ create!(name: 'Echo Base', planet: 'Hoth', faction: LiteFaction::REBELS)
48
+ create!(name: 'Secret Hideout', planet: 'Dantooine', faction: LiteFaction::REBELS)
49
+ create!(name: 'Death Star', planet: nil, faction: LiteFaction::EMPIRE)
50
+ create!(name: 'Shield Generator', planet: 'Endor', faction: LiteFaction::EMPIRE)
51
+ create!(name: 'Headquarters', planet: 'Coruscant', faction: LiteFaction::EMPIRE)
52
+ end
53
+
54
+ class LiteShip < SQLiteRecord
55
+ belongs_to :faction, class_name: 'LiteFaction', foreign_key: :faction_id
56
+
57
+ create!(name: 'X-Wing', faction: LiteFaction::REBELS)
58
+ create!(name: 'Y-Wing', faction: LiteFaction::REBELS)
59
+ create!(name: 'A-Wing', faction: LiteFaction::REBELS)
60
+ create!(name: 'Millenium Falcon', faction: LiteFaction::REBELS)
61
+ create!(name: 'Home One', faction: LiteFaction::REBELS)
62
+ create!(name: 'TIE Fighter', faction: LiteFaction::EMPIRE)
63
+ create!(name: 'TIE Interceptor', faction: LiteFaction::EMPIRE)
64
+ create!(name: 'Executor', faction: LiteFaction::EMPIRE)
65
+ end
66
+
67
+ class StartWarsSqliteSchema < GraphQL::Schema
68
+ namespace :start_wars_sqlite
69
+
70
+ configure do |config|
71
+ config.enable_string_collector = false
72
+ end
73
+
74
+ sources LiteFaction do
75
+ with_options on: 'liteFactions' do
76
+ scoped_argument(:order) { |o| order(name: o) }
77
+ end
78
+ end
79
+
80
+ sources LiteBase
81
+ sources LiteShip
82
+ end
@@ -0,0 +1,15 @@
1
+ require 'integration/config'
2
+
3
+ class Integration_SQLite_StarWarsIntrospectionTest < GraphQL::IntegrationTestCase
4
+ load_schema 'sqlite'
5
+
6
+ SCHEMA = ::StartWarsSqliteSchema
7
+
8
+ # There are some issues with the end sorting, so compare the string result
9
+ # with sorted characters, which will produce the exact match
10
+ def test_gql_introspection
11
+ # File.write('test/assets/sqlite.gql', SCHEMA.to_gql)
12
+ result = gql_file('sqlite').split('').sort.join.squish
13
+ assert_equal(result, SCHEMA.to_gql.split('').sort.join.squish)
14
+ end
15
+ end
@@ -0,0 +1,82 @@
1
+ require 'integration/config'
2
+
3
+ class Integration_SQLite_StarWarsMutationTest < GraphQL::IntegrationTestCase
4
+ load_schema 'sqlite'
5
+
6
+ SCHEMA = ::StartWarsSqliteSchema
7
+
8
+ def test_can_create_faction
9
+ args = { data: { name: 'Aliens' } }
10
+ record = { id: next_id, name: 'Aliens' }
11
+ assert_result({ data: { record: record } }, <<~GQL, args: args)
12
+ mutation($data: LiteFactionInput!) {
13
+ record: createLiteFaction(liteFaction: $data) { id name }
14
+ }
15
+ GQL
16
+
17
+ assert_equal(3, LiteFaction.count)
18
+ assert_equal('Aliens', LiteFaction.last.name)
19
+ LiteFaction.last.destroy!
20
+ end
21
+
22
+ def test_can_update_faction
23
+ args = { id: '1', data: { name: 'ARR' } }
24
+ record = { id: '1', name: 'ARR' }
25
+ assert_result({ data: { record: record } }, <<~GQL, args: args)
26
+ mutation($id: ID!, $data: LiteFactionInput!) {
27
+ record: updateLiteFaction(id: $id, liteFaction: $data) { id name }
28
+ }
29
+ GQL
30
+
31
+ assert_equal('ARR', LiteFaction.find(1).name)
32
+ LiteFaction.find(1).update(name: 'Alliance to Restore the Republic')
33
+ end
34
+
35
+ def test_can_create_and_delete_faction
36
+ args = { data: { name: 'Should not Exist' } }
37
+ record = { id: next_id, name: 'Should not Exist' }
38
+ assert_result({ data: { record: record } }, <<~GQL, args: args)
39
+ mutation($data: LiteFactionInput!) {
40
+ record: createLiteFaction(liteFaction: $data) { id name }
41
+ }
42
+ GQL
43
+
44
+ assert_equal(3, LiteFaction.count)
45
+ assert_equal('Should not Exist', LiteFaction.last.name)
46
+
47
+ assert_result({ data: { record: true } }, <<~GQL, args: { id: record[:id] })
48
+ mutation($id: ID!) { record: deleteLiteFaction(id: $id) }
49
+ GQL
50
+
51
+ assert_equal(2, LiteFaction.count)
52
+ refute_equal('Should not Exist', LiteFaction.last.name)
53
+ end
54
+
55
+ def test_can_create_faction_with_ships
56
+ ships = [{ name: 'Alpha' }, { name: 'Delta' }]
57
+ args = { data: { name: 'Emperor', ships_attributes: ships } }
58
+ record = { id: next_id, name: 'Emperor', ships: ships }
59
+ assert_result({ data: { record: record } }, <<~GQL, args: args)
60
+ mutation($data: LiteFactionInput!) {
61
+ record: createLiteFaction(liteFaction: $data) { id name ships { name } }
62
+ }
63
+ GQL
64
+
65
+ assert_equal(3, LiteFaction.count)
66
+ assert_equal('Emperor', LiteFaction.last.name)
67
+
68
+ assert_equal(10, LiteShip.count)
69
+ assert_equal(['Alpha', 'Delta'], LiteShip.last(2).map(&:name))
70
+
71
+ LiteShip.last(2).map(&:destroy!)
72
+ LiteFaction.last.destroy!
73
+ end
74
+
75
+ protected
76
+
77
+ def next_id
78
+ @@next_id ||= 2
79
+ @@next_id += 1
80
+ @@next_id.to_s
81
+ end
82
+ end
@@ -0,0 +1,71 @@
1
+ require 'integration/config'
2
+
3
+ class Integration_SQLite_StarWarsQueryTest < GraphQL::IntegrationTestCase
4
+ load_schema 'sqlite'
5
+
6
+ SCHEMA = ::StartWarsSqliteSchema
7
+
8
+ def test_query_factions
9
+ faction = named_list('Alliance to Restore the Republic', 'Galactic Empire')
10
+ assert_result({ data: { liteFactions: faction } }, <<~GQL)
11
+ query AllFactions { liteFactions { name } }
12
+ GQL
13
+ end
14
+
15
+ def test_query_single_faction
16
+ assert_result({ data: { liteFaction: { name: 'Galactic Empire' } } }, <<~GQL)
17
+ query FindEmpireFaction { liteFaction(id: "2") { name } }
18
+ GQL
19
+ end
20
+
21
+ def test_base_with_faction
22
+ faction = { name: 'Alliance to Restore the Republic' }
23
+ base = { name: 'Yavin', planet: 'Yavin 4', faction: faction }
24
+ assert_result({ data: { liteBase: base } }, <<~GQL)
25
+ query YavinBaseAndFaction { liteBase(id: "1") { name planet faction { name } } }
26
+ GQL
27
+ end
28
+
29
+ def test_faction_with_bases_and_ships
30
+ ships = named_list('TIE Fighter', 'TIE Interceptor', 'Executor')
31
+ bases = named_list('Death Star', 'Shield Generator', 'Headquarters')
32
+ faction = { name: 'Galactic Empire', bases: bases, ships: ships }
33
+ assert_result({ data: { liteFaction: faction } }, <<~GQL)
34
+ query EmpireFleet { liteFaction(id: "2") { name bases { name } ships { name } } }
35
+ GQL
36
+ end
37
+
38
+ def test_full_data
39
+ ships1 = named_list('X-Wing', 'Y-Wing', 'A-Wing', 'Millenium Falcon', 'Home One')
40
+ bases1 = named_list('Yavin', 'Echo Base', 'Secret Hideout')
41
+
42
+ ships2 = named_list('TIE Fighter', 'TIE Interceptor', 'Executor')
43
+ bases2 = named_list('Death Star', 'Shield Generator', 'Headquarters')
44
+
45
+ factions = [
46
+ { name: 'Alliance to Restore the Republic', bases: bases1, ships: ships1 },
47
+ { name: 'Galactic Empire', bases: bases2, ships: ships2 },
48
+ ]
49
+
50
+ assert_result({ data: { liteFactions: factions } }, <<~GQL)
51
+ query FullData { liteFactions { name bases { name } ships { name } } }
52
+ GQL
53
+ end
54
+
55
+ def test_data_recusivity
56
+ faction = { name: 'Galactic Empire' }
57
+ bases = named_list('Death Star', 'Shield Generator', 'Headquarters', faction: faction.dup)
58
+ faction[:bases] = bases
59
+
60
+ assert_result({ data: { liteFaction: faction } }, <<~GQL)
61
+ query EmpireFleet { liteFaction(id: "2") { name bases { name faction { name } } } }
62
+ GQL
63
+ end
64
+
65
+ def test_factions_scoped_argument
66
+ faction = named_list('Galactic Empire', 'Alliance to Restore the Republic')
67
+ assert_result({ data: { liteFactions: faction } }, <<~GQL, args: { order: 'desc' })
68
+ query AllFactions($order: String!) { liteFactions(order: $order) { name } }
69
+ GQL
70
+ end
71
+ end