rails-graphql 1.0.0.rc1 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/graphql/templates/config.rb +2 -2
  3. data/lib/gql_parser.so +0 -0
  4. data/lib/rails/graphql/alternative/query.rb +4 -4
  5. data/lib/rails/graphql/alternative.rb +4 -0
  6. data/lib/rails/graphql/callback.rb +2 -1
  7. data/lib/rails/graphql/config.rb +13 -2
  8. data/lib/rails/graphql/directive.rb +1 -1
  9. data/lib/rails/graphql/field/proxied_field.rb +1 -1
  10. data/lib/rails/graphql/helpers/inherited_collection/base.rb +1 -1
  11. data/lib/rails/graphql/helpers/with_assignment.rb +5 -5
  12. data/lib/rails/graphql/helpers/with_fields.rb +1 -1
  13. data/lib/rails/graphql/helpers/with_schema_fields.rb +3 -3
  14. data/lib/rails/graphql/railties/controller.rb +10 -6
  15. data/lib/rails/graphql/request/component/operation.rb +1 -1
  16. data/lib/rails/graphql/request.rb +4 -4
  17. data/lib/rails/graphql/source/active_record/builders.rb +3 -4
  18. data/lib/rails/graphql/source/active_record_source.rb +5 -3
  19. data/lib/rails/graphql/source/base.rb +3 -2
  20. data/lib/rails/graphql/source/builder.rb +9 -4
  21. data/lib/rails/graphql/source.rb +8 -1
  22. data/lib/rails/graphql/type/creator.rb +8 -6
  23. data/lib/rails/graphql/type/input.rb +10 -3
  24. data/lib/rails/graphql/type/object.rb +1 -1
  25. data/lib/rails/graphql/type/scalar/date_scalar.rb +1 -1
  26. data/lib/rails/graphql/type/scalar/date_time_scalar.rb +1 -1
  27. data/lib/rails/graphql/type/scalar/time_scalar.rb +1 -1
  28. data/lib/rails/graphql/type/scalar.rb +1 -1
  29. data/lib/rails/graphql/type_map.rb +7 -5
  30. data/lib/rails/graphql/version.rb +1 -1
  31. data/lib/rails/graphql.rb +2 -1
  32. data/test/assets/mysql.gql +3 -3
  33. data/test/assets/sqlite.gql +3 -3
  34. data/test/graphql/source_test.rb +1 -1
  35. data/test/integration/global_id_test.rb +2 -2
  36. data/test/integration/resolver_precedence_test.rb +1 -1
  37. data/test/integration/sqlite/star_wars_global_id_test.rb +1 -1
  38. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4567d054599bcd2c6c93008cd8e82cad8259bf15db57a508eb5ebc671faf64e1
4
- data.tar.gz: d75085b1ccf8125a31a442369b13628bab65cd6aaa7b8c48ebb85016156a19d4
3
+ metadata.gz: 3c29232c14870c44aeab62fba29beda42f8f99a8047bf83f717149e6fc2e5d7c
4
+ data.tar.gz: 196468f3151958620774998650fe7a5f70e0b3204fdb5a028b31c634d21a9cb0
5
5
  SHA512:
6
- metadata.gz: f7349679b342745edc2bbf8c89b2c1c3687db9331de6883d042eb1523c3a77566cc0485382b5f1eb6dc3656cee4aed7b77f22ce268417b77564f702185415601
7
- data.tar.gz: 38dc53be74565810ce48c474c3c4ea2ceb01cdbb947dfe771647032f7cdc314cb645daf226b32f3d2d62b2f4fe62db3cfab1815481d218b9ac24e37c4c47a203
6
+ metadata.gz: a17d0f98a0473afd6d221d98b967068ae9d97da363e44e92817729e23a204510768c72bed50a858816e9d7eeda8b0fcdefe83c56d9782e8abe06d71bea6e0f75
7
+ data.tar.gz: c4258dfce30c7aedba8a3f2c1a9a6c20b0eca30ae520888efac8dfeb3f5267654d74e2992b9794bdb892a2f84d8f1be68d6d71e637ebaa48ee780d3b019ccf25
@@ -40,7 +40,7 @@ Rails::GraphQL.configure do |config|
40
40
  # Introspection is enabled by default. It is recommended to only use
41
41
  # introspection during development and tests, never in production.
42
42
  # This can also be set per schema level.
43
- config.enable_introspection = true
43
+ config.enable_introspection = !Rails.env.production?
44
44
 
45
45
  # Define the names of the schema/operations types. The single "_" is a
46
46
  # suggestion. In an application that has a Subscription object, it will
@@ -93,5 +93,5 @@ Rails::GraphQL.configure do |config|
93
93
  # behaves closer to YAML. The received value is ensured to be wrapped in
94
94
  # "{}". If that produces unexpected results, you can assign a proc and then
95
95
  # parse the value in any other way.
96
- # config.literal_input_parser = JSON.method(:parse)
96
+ # config.literal_input_parser = Psych.method(:safe_load)
97
97
  end
data/lib/gql_parser.so CHANGED
Binary file
@@ -15,9 +15,9 @@ module Rails
15
15
  self.abstract = true
16
16
 
17
17
  class << self
18
- delegate :gql_name, :to_sym, :desc, :argument, :ref_argument, :id_argument,
19
- :use, :internal?, :disabled?, :enabled?, :disable!, :enable!, :rename!,
20
- :authorize, :on, :description=, :description, to: :field
18
+ delegate :gql_name, :to_sym, :desc, :arguments, :argument, :ref_argument, :id_argument,
19
+ :use, :internal?, :disabled?, :enabled?, :disable!, :enable!, :rename!, :authorize,
20
+ :on, :description=, :description, to: :field
21
21
 
22
22
  # Returns the type of the field class
23
23
  def type_field_class
@@ -85,7 +85,7 @@ module Rails
85
85
  def field_class
86
86
  return @field.class if defined?(@field)
87
87
  list = Helpers::WithSchemaFields::TYPE_FIELD_CLASS
88
- GraphQL::Field.const_get(list[type_field_class])
88
+ GraphQL::Field.const_get(list[type_field_class], false)
89
89
  end
90
90
  end
91
91
  end
@@ -10,6 +10,10 @@ module Rails
10
10
  autoload :Mutation
11
11
  autoload :Subscription
12
12
 
13
+ autoload_at "#{__dir__}/alternative/query" do
14
+ autoload :Field
15
+ end
16
+
13
17
  autoload_at "#{__dir__}/alternative/field_set" do
14
18
  autoload :FieldSet
15
19
  autoload :MutationSet
@@ -83,7 +83,8 @@ module Rails
83
83
  # Find the proper owner of the symbol based callback
84
84
  def owner
85
85
  @owner ||= target.all_owners.find do |item|
86
- item.is_a?(Class) ? item.method_defined?(block) : item.respond_to?(block)
86
+ item.is_a?(Class) && item.included_modules.include?(Helpers::Instantiable) &&
87
+ item.method_defined?(block)
87
88
  end || target
88
89
  end
89
90
 
@@ -29,8 +29,8 @@ module Rails
29
29
 
30
30
  # The list of nested paths inside of the graphql folder that does not
31
31
  # require to be in their own namespace.
32
- config.paths = %w[directives fields sources enums inputs interfaces object
33
- scalars unions].to_set
32
+ config.paths = %w[directives fields sources enums inputs interfaces objects
33
+ scalars unions concerns].to_set
34
34
 
35
35
  # This is very similar to `ActiveRecord` verbose logs, which simply show the
36
36
  # path of the file that started a GraphQL request.
@@ -180,6 +180,17 @@ module Rails
180
180
  # parse the value in any other way.
181
181
  config.literal_input_parser = JSON.method(:parse)
182
182
 
183
+ # A mapping for the internal parameters and where they should be taken
184
+ # from. You can point to nested values using dot notation.
185
+ # TODO: Needs implementation
186
+ config.params_mapping = {
187
+ query: 'query',
188
+ variables: 'variables',
189
+ operation_name: 'operation_name',
190
+ query_cache_key: 'extensions.persistedQuery.sha256Hash',
191
+ query_cache_version: 'extensions.persistedQuery.version',
192
+ }
193
+
183
194
  # TODO: To be implemented
184
195
  # allow_query_serialization
185
196
  end
@@ -129,7 +129,7 @@ module Rails
129
129
  GraphQL.enumerate(setting).map do |item|
130
130
  next item unless item.is_a?(String) || item.is_a?(Symbol)
131
131
  GraphQL.type_map.fetch(item, namespaces: namespaces) ||
132
- ::GraphQL.const_get(item)
132
+ ::GraphQL.const_get(item, false)
133
133
  end
134
134
  end
135
135
 
@@ -72,7 +72,7 @@ module Rails
72
72
 
73
73
  # Override this to include proxied owners
74
74
  def all_owners
75
- super + proxied_owner.all_owners
75
+ super + @field.all_owners
76
76
  end
77
77
 
78
78
  # Return the proxied field
@@ -12,7 +12,7 @@ module Rails
12
12
  # Just a little helper to initialize the iterator form a given +source+
13
13
  def self.handle(source, ivar, type)
14
14
  klass = (type == :array || type == :set) ? :Array : :Hash
15
- InheritedCollection.const_get(klass).new(source, ivar, type)
15
+ InheritedCollection.const_get(klass, false).new(source, ivar, type)
16
16
  end
17
17
 
18
18
  def initialize(source, ivar, type)
@@ -61,12 +61,12 @@ module Rails
61
61
  return if abstract?
62
62
  return super unless assigned?
63
63
 
64
- result = super
65
- return result unless (klass = safe_assigned_class)
66
- return result if GraphQL.type_map.exist?(klass, namespaces: namespaces)
64
+ super.tap do
65
+ break unless (klass = safe_assigned_class)
66
+ break if GraphQL.type_map.exist?(klass, namespaces: namespaces)
67
67
 
68
- GraphQL.type_map.register_alias(klass, to_sym, namespaces: namespaces)
69
- result
68
+ GraphQL.type_map.register_alias(klass, gql_name, namespaces: namespaces)
69
+ end
70
70
  end
71
71
 
72
72
  protected
@@ -159,7 +159,7 @@ module Rails
159
159
  # Import a module containing several classes to be imported
160
160
  def import_all(mod, recursive: false, **xargs)
161
161
  mod.constants.each do |const_name|
162
- object = mod.const_get(const_name)
162
+ object = mod.const_get(const_name, false)
163
163
 
164
164
  import(object, **xargs) if object.is_a?(Class)
165
165
  import_all(object, recursive: recursive, **xargs) if recursive && object.is_a?(Module)
@@ -105,7 +105,7 @@ module Rails
105
105
  # Add a new field of the give +type+
106
106
  # See {OutputField}[rdoc-ref:Rails::GraphQL::OutputField] class.
107
107
  def add_field(type, *args, **xargs, &block)
108
- klass = Field.const_get(TYPE_FIELD_CLASS[type])
108
+ klass = Field.const_get(TYPE_FIELD_CLASS[type], false)
109
109
  object = klass.new(*args, **xargs, owner: self, &block)
110
110
 
111
111
  raise DuplicatedError, (+<<~MSG).squish if has_field?(type, object.name)
@@ -126,7 +126,7 @@ module Rails
126
126
  A #{field.schema_type} field cannot be added as a #{type} field.
127
127
  MSG
128
128
 
129
- klass = Field.const_get(TYPE_FIELD_CLASS[type])
129
+ klass = Field.const_get(TYPE_FIELD_CLASS[type], false)
130
130
  raise ArgumentError, (+<<~MSG).squish unless field.is_a?(klass)
131
131
  The #{field.class.name} is not a valid field for #{type} fields.
132
132
  MSG
@@ -236,7 +236,7 @@ module Rails
236
236
  # TODO: Maybe add deepness into the recursive value
237
237
  def import_all_into(type, mod, recursive: false, **xargs)
238
238
  mod.constants.each do |const_name|
239
- object = mod.const_get(const_name)
239
+ object = mod.const_get(const_name, false)
240
240
 
241
241
  import_into(type, object, **xargs) if object.is_a?(Class)
242
242
  import_all_into(type, object, recursive: recursive, **xargs) if recursive && object.is_a?(Module)
@@ -33,8 +33,12 @@ module Rails
33
33
  end
34
34
 
35
35
  # GET /describe
36
- def describe
37
- render plain: gql_schema_header + gql_describe_schema + gql_schema_footer
36
+ def describe(schema = gql_schema)
37
+ render plain: [
38
+ gql_schema_header(schema),
39
+ gql_describe_schema(schema),
40
+ gql_schema_footer,
41
+ ].join
38
42
  end
39
43
 
40
44
  # GET /graphiql
@@ -128,7 +132,7 @@ module Rails
128
132
  end
129
133
 
130
134
  # Shows a text representation of the schema
131
- def gql_describe_schema(schema = gql_schema)
135
+ def gql_describe_schema(schema)
132
136
  schema.to_gql(
133
137
  with_descriptions: !params.key?(:without_descriptions),
134
138
  with_spec: !params.key?(:without_spec),
@@ -137,9 +141,9 @@ module Rails
137
141
 
138
142
  # Print a header of the current schema for the description process
139
143
  # TODO: Maybe add a way to detect from which file the schema is being loaded
140
- def gql_schema_header
141
- ns = +" [#{gql_schema.namespace}]" if gql_schema.namespace != :base
142
- +"#{DESCRIBE_HEADER}# Schema #{gql_schema.name}#{ns}\n"
144
+ def gql_schema_header(schema)
145
+ ns = +" [#{schema.namespace}]" if schema.namespace != :base
146
+ +"#{DESCRIBE_HEADER}# Schema #{schema.name}#{ns}\n"
143
147
  end
144
148
 
145
149
  # Show the footer of the describe page
@@ -18,7 +18,7 @@ module Rails
18
18
 
19
19
  # Helper method to initialize an operation given the node
20
20
  def build(request, node)
21
- request.build(const_get(node.type.to_s.classify), request, node)
21
+ request.build(const_get(node.type.to_s.classify, false), request, node)
22
22
  end
23
23
 
24
24
  # Rewrite the kind to always return +:operation+
@@ -95,12 +95,12 @@ module Rails
95
95
 
96
96
  # Allow accessing component-based objects through the request
97
97
  def const_defined?(name, *)
98
- Component.const_defined?(name) || super
98
+ Component.const_defined?(name, false) || super
99
99
  end
100
100
 
101
101
  # Allow accessing component-based objects through the request
102
102
  def const_missing(name)
103
- Component.const_defined?(name) ? Component.const_get(name) : super
103
+ Component.const_defined?(name, false) ? Component.const_get(name, false) : super
104
104
  end
105
105
  end
106
106
 
@@ -476,13 +476,13 @@ module Rails
476
476
  modules.each do |mod|
477
477
  mod.constants.each do |const_name|
478
478
  const_name = const_name.to_s
479
- const = mod.const_get(const_name)
479
+ const = mod.const_get(const_name, false)
480
480
  next unless const.is_a?(Module)
481
481
 
482
482
  # Find the related request class to extend
483
483
  klass = const_name === 'Request' ? self.class : begin
484
484
  const_name.split('_').inject(self.class) do |k, next_const|
485
- k.const_defined?(next_const) ? k.const_get(next_const) : break
485
+ k.const_defined?(next_const) ? k.const_get(next_const, false) : break
486
486
  end
487
487
  end
488
488
 
@@ -66,7 +66,7 @@ module Rails
66
66
  return remove_instance_variable(:@enums) if enums.blank?
67
67
 
68
68
  @enums = enums.each_with_object({}) do |(attribute, setting), hash|
69
- class_name = base_name + attribute.to_s.classify
69
+ class_name = base_name.tr('_', '') + attribute.to_s.classify
70
70
  hash[attribute.to_s] = create_enum(class_name, setting)
71
71
  rescue DuplicatedError
72
72
  next
@@ -75,15 +75,14 @@ module Rails
75
75
 
76
76
  # Build all necessary attribute fields into the given +holder+
77
77
  def build_attribute_fields(holder, **field_options)
78
- each_attribute(holder) do |key, type, **options|
79
- next if holder.has_field?(key) || skip_field?(key, on: holder.kind)
80
78
 
79
+ each_attribute(holder) do |key, type, **options|
81
80
  str_key = key.to_s
82
81
  type = (defined?(@enums) && @enums.key?(str_key) && @enums[str_key]) ||
83
82
  (id_columns.include?(str_key) && :id) || type
84
83
 
85
84
  options[:null] = !attr_required?(key) unless options.key?(:null)
86
- holder.field(key, type, **options.merge(field_options[key] || {}))
85
+ holder.safe_field(key, type, **options.merge(field_options[key] || {}))
87
86
  end
88
87
  end
89
88
 
@@ -30,7 +30,7 @@ module Rails
30
30
 
31
31
  # Marks if the source should be threated as an interface, meaning that
32
32
  # no object will be created, instead an interface will
33
- class_attribute :act_as_interface, instance_accessor: false, default: false
33
+ class_attribute :act_as_interface, instance_accessor: false
34
34
 
35
35
  # The name of the class (or the class itself) to be used as superclass for
36
36
  # the generate GraphQL interface type of this source
@@ -125,7 +125,8 @@ module Rails
125
125
 
126
126
  # Set the assignment to a model with a similar name as the source
127
127
  def assigned_to
128
- @assigned_to ||= name.delete_prefix('GraphQL::')[0..-7]
128
+ return @assigned_to if defined?(@assigned_to)
129
+ @assigned_to = base_name.gsub('_', '::')
129
130
  end
130
131
 
131
132
  # Stores columns associated with enums so that the fields can have a
@@ -147,7 +148,8 @@ module Rails
147
148
 
148
149
  # Checks if the source is building an interface instead of an object
149
150
  def interface?
150
- defined?(@interface) || act_as_interface? || sti_interface?
151
+ defined?(@interface) || act_as_interface == true ||
152
+ (act_as_interface != false && sti_interface?)
151
153
  end
152
154
 
153
155
  # Provides access to the default plural query field, for associations interconnection
@@ -62,17 +62,18 @@ module Rails
62
62
  xargs[:values] = enumerator.sort_by(&:last).map(&:first)
63
63
  xargs[:indexed] = enumerator.first.last.is_a?(Numeric)
64
64
 
65
- create_type(:enum, enum_name.classify, **xargs, &block)
65
+ create_type(:enum, enum_name.to_s.classify, **xargs, &block)
66
66
  end
67
67
 
68
68
  # Helper method to create a class based on the given +type+ and
69
69
  # allows several other settings to be executed on it
70
- def create_type(type = nil, name = base_name, **xargs, &block)
70
+ def create_type(type = nil, name = nil, **xargs, &block)
71
71
  xargs[:owner] ||= self
72
72
  xargs[:namespaces] = namespaces
73
73
  xargs[:assigned_to] = safe_assigned_class
74
74
  superclass = xargs.delete(:superclass) || type
75
75
 
76
+ name ||= base_name.tr('_', '')
76
77
  GraphQL::Type.create!(self, name, superclass, **xargs, &block)
77
78
  end
78
79
 
@@ -21,13 +21,13 @@ module Rails
21
21
  build_all! unless abstract?
22
22
  end
23
23
 
24
- # Allows building anything that is in hooks
24
+ # Make sure to properly indicate about build methods
25
25
  def respond_to_missing?(method_name, *)
26
26
  return super unless method_name.to_s.start_with?('build_') &&
27
27
  hook_names.include?(method_name.to_s[6..-1].to_sym)
28
28
  end
29
29
 
30
- # Allow fast creation of values
30
+ # Allows all sorts of building methods to be called
31
31
  def method_missing(method_name, *args, **xargs, &block)
32
32
  return super unless method_name.to_s.start_with?('build_')
33
33
 
@@ -47,6 +47,11 @@ module Rails
47
47
  @built ||= Set.new
48
48
  end
49
49
 
50
+ # Mark as built before running the hooks
51
+ def run_hooks(type, *)
52
+ built.add(type)
53
+ end
54
+
50
55
  private
51
56
 
52
57
  # Import all options-based settings for skipping field
@@ -93,7 +98,6 @@ module Rails
93
98
  # Build all the objects associated with this source
94
99
  def build!(type)
95
100
  ensure_build!(type)
96
- built << type
97
101
 
98
102
  schema_type = Helpers::WithSchemaFields::TYPE_FIELD_CLASS.key?(type)
99
103
  catch(:skip) { run_hooks(:start) } unless built?(:start)
@@ -106,7 +110,8 @@ module Rails
106
110
  def hook_scope_for(type, schema_type)
107
111
  type = type.to_sym
108
112
  klass = schema_type ? 'WithSchemaFields::ScopedConfig' : 'AttributeDelegator'
109
- Source::ScopedConfig.new(self, Helpers.const_get(klass).new(self, type), type)
113
+ klass = Helpers.const_get(klass, false).new(self, type)
114
+ Source::ScopedConfig.new(self, klass, type)
110
115
  end
111
116
 
112
117
  end
@@ -85,7 +85,13 @@ module Rails
85
85
 
86
86
  # Get the main name of the source
87
87
  def base_name
88
- name.demodulize[0..-7]
88
+ @base_name ||= begin
89
+ nested = "::#{Type::Creator::NESTED_MODULE}::"
90
+
91
+ value = name.delete_prefix('GraphQL::')
92
+ value = name.split(nested).last if name.include?(nested)
93
+ value.chomp('Source')
94
+ end
89
95
  end
90
96
 
91
97
  # :singleton-method:
@@ -214,6 +220,7 @@ module Rails
214
220
 
215
221
  # Run a list of hooks using the +source+ as the instance of the block
216
222
  def run_hooks(hook_name, source = self)
223
+ super
217
224
  all_hooks.try(:[], hook_name.to_sym)&.reverse_each do |block|
218
225
  source.instance_exec(&block)
219
226
  end
@@ -127,10 +127,10 @@ module Rails
127
127
 
128
128
  # Create the class under the nested module
129
129
  return base.const_set(name, Class.new(superclass)) \
130
- unless base.const_defined?(name)
130
+ unless base.const_defined?(name, false)
131
131
 
132
132
  # Get the existing class and check for the once setting
133
- klass = base.const_get(name)
133
+ klass = base.const_get(name, false)
134
134
  return klass unless !once? && klass < superclass
135
135
 
136
136
  # Created once or not from the same superclass
@@ -141,7 +141,7 @@ module Rails
141
141
 
142
142
  # Make sure to properly get the superclass
143
143
  def sanitize_superclass(value)
144
- value = Type.const_get(value.to_s.classify) unless value.is_a?(Class)
144
+ value = Type.const_get(value.to_s.classify, false) unless value.is_a?(Class)
145
145
 
146
146
  valid_class = value.is_a?(Class) && value.respond_to?(:kind)
147
147
  valid_class &= SUPPORTED_KINDS.include?(value.kind)
@@ -155,7 +155,7 @@ module Rails
155
155
  # Let's clean up the name
156
156
  def sanitize_name(name_or_object)
157
157
  name = name_or_object.is_a?(Module) ? name_or_object.name : name_or_object.to_s
158
- name = name.classify.gsub(/::/, '_')
158
+ name = name.classify.delete_prefix('GraphQL::').gsub(/::/, '_')
159
159
  name.end_with?(name_suffix) ? name : name + name_suffix
160
160
  end
161
161
 
@@ -174,9 +174,11 @@ module Rails
174
174
  def base_module
175
175
  base = @from.is_a?(Module) ? @from : @from.class
176
176
  if base.const_defined?(NESTED_MODULE, false)
177
- base.const_get(NESTED_MODULE)
177
+ base.const_get(NESTED_MODULE, false)
178
178
  else
179
- base.const_set(NESTED_MODULE, Module.new)
179
+ base.const_set(NESTED_MODULE, Module.new).tap do
180
+ base.private_constant(NESTED_MODULE)
181
+ end
180
182
  end
181
183
  end
182
184
 
@@ -114,7 +114,7 @@ module Rails
114
114
  delegate_missing_to :resource
115
115
 
116
116
  def initialize(args = nil, **xargs)
117
- @args = args || OpenStruct.new(xargs.transform_keys { |key| key.to_s.underscore })
117
+ @args = args || build_ostruct(xargs)
118
118
  @args.freeze
119
119
 
120
120
  validate! if args.nil?
@@ -135,7 +135,7 @@ module Rails
135
135
 
136
136
  # Just return the arguments as an hash
137
137
  def params
138
- parametrize(self)
138
+ parametrize(@args.to_h)
139
139
  end
140
140
 
141
141
  # Correctly turn all the arguments into their +as_json+ version and
@@ -184,12 +184,19 @@ module Rails
184
184
  end
185
185
  end
186
186
 
187
+ protected
188
+
189
+ # A helper to turn a hash into a proper Open Struct instance
190
+ def build_ostruct(hash)
191
+ OpenStruct.new(hash.transform_keys { |key| key.to_s.underscore })
192
+ end
193
+
187
194
  private
188
195
 
189
196
  # Make sure to turn inputs into params
190
197
  def parametrize(input)
191
198
  case input
192
- when Type::Input then parametrize(input.args.to_h)
199
+ when Type::Input then input.params
193
200
  when Array then input.map(&method(:parametrize))
194
201
  when Hash then input.transform_values(&method(:parametrize))
195
202
  else input
@@ -77,7 +77,7 @@ module Rails
77
77
 
78
78
  def inspect
79
79
  return super if self.eql?(Type::Object)
80
- fields = @fields.values.map(&:inspect)
80
+ fields = @fields&.values&.map(&:inspect)
81
81
  fields = fields.presence && +" {#{fields.join(', ')}}"
82
82
 
83
83
  directives = inspect_directives
@@ -7,7 +7,7 @@ module Rails
7
7
  class Scalar::DateScalar < Scalar
8
8
  desc 'The Date scalar type represents a ISO 8601 string value.'
9
9
 
10
- use :specified_by, url: 'https://www.rfc-editor.org/rfc/rfc3339'
10
+ use :specified_by, url: 'https://en.wikipedia.org/wiki/ISO_8601'
11
11
 
12
12
  class << self
13
13
  def valid_input?(value)
@@ -9,7 +9,7 @@ module Rails
9
9
 
10
10
  desc 'The DateTime scalar type represents a ISO 8601 string value.'
11
11
 
12
- use :specified_by, url: 'https://www.rfc-editor.org/rfc/rfc3339'
12
+ use :specified_by, url: 'https://en.wikipedia.org/wiki/ISO_8601'
13
13
 
14
14
  class << self
15
15
  def valid_input?(value)
@@ -13,7 +13,7 @@ module Rails
13
13
  minutes, seconds, and milliseconds.
14
14
  MSG
15
15
 
16
- use :specified_by, url: 'https://www.rfc-editor.org/rfc/rfc3339'
16
+ use :specified_by, url: 'https://en.wikipedia.org/wiki/ISO_8601'
17
17
 
18
18
  # A +base_object+ helps to identify what methods are actually available
19
19
  # to work as resolvers
@@ -48,7 +48,7 @@ module Rails
48
48
 
49
49
  # Transforms the given value to its representation in a JSON string
50
50
  def to_json(value)
51
- as_json(value)&.inspect
51
+ as_json(value).inspect
52
52
  end
53
53
 
54
54
  # Transforms the given value to its representation in a Hash object
@@ -19,6 +19,7 @@ module Rails
19
19
  extend ActiveSupport::Autoload
20
20
 
21
21
  FILTER_REGISTER_TRACE = /((inherited|initialize)'$|schema\.rb:\d+)/.freeze
22
+ NESTED_MODULE = Type::Creator::NESTED_MODULE
22
23
 
23
24
  # Store all the base classes that are managed by the Type Map
24
25
  mattr_accessor :base_classes, instance_writer: false,
@@ -97,6 +98,8 @@ module Rails
97
98
  ns = @module_namespaces[mod]
98
99
  break ns unless ns.nil?
99
100
  end
101
+ rescue ::NameError
102
+ # If any module parent can't be found, there is no much we can do
100
103
  end
101
104
 
102
105
  # Register a given object, which must be a class where the namespaces and
@@ -144,7 +147,6 @@ module Rails
144
147
  # Unregister all the provided objects by simply assigning nil to their
145
148
  # final value on the index
146
149
  def unregister(*objects)
147
- sub_mod = Type::Creator::NESTED_MODULE
148
150
  objects.each do |object|
149
151
  namespaces = sanitize_namespaces(namespaces: object.namespaces, exclusive: true)
150
152
  namespaces << :base if namespaces.empty?
@@ -155,11 +157,11 @@ module Rails
155
157
  @objects -= 1
156
158
  end
157
159
 
158
- return unless object.const_defined?(sub_mod, false)
160
+ return unless object.const_defined?(NESTED_MODULE, false)
159
161
 
160
- nested_mod = object.const_get(sub_mod)
161
- unregister(*nested_mod.constants.map(&nested_mod.method(:const_get)))
162
- object.send(:remove_const, sub_mod)
162
+ nested_mod = object.const_get(NESTED_MODULE, false)
163
+ nested_mod.constants.each { |name| nested_mod.const_get(name, false).unregister! }
164
+ object.send(:remove_const, NESTED_MODULE)
163
165
  end
164
166
  end
165
167
 
@@ -15,7 +15,7 @@ module Rails
15
15
  MAJOR = 1
16
16
  MINOR = 0
17
17
  TINY = 0
18
- PRE = 'rc1'
18
+ PRE = 'rc2'
19
19
 
20
20
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
21
21
  end
data/lib/rails/graphql.rb CHANGED
@@ -7,6 +7,7 @@ require 'active_support'
7
7
 
8
8
  require 'active_support/core_ext/module/attribute_accessors_per_thread'
9
9
  require 'active_support/core_ext/string/strip'
10
+ require 'active_support/core_ext/enumerable'
10
11
 
11
12
  require 'rails/graphql/version'
12
13
  require 'rails/graphql/uri'
@@ -40,7 +41,7 @@ module Rails
40
41
  # * <tt>Directives:</tt> A directive definition belongs to the introspection
41
42
  # and is handled in the Singleton extent. They are handled as instance
42
43
  # whenever a definition or an execution uses them.
43
- # * <tt>Fields:</tt> Many other types and helper containers holds a serie of
44
+ # * <tt>Fields:</tt> Many other types and helper containers holds a series of
44
45
  # fields, which means that fields with the same name will probably behave
45
46
  # differently.
46
47
  module GraphQL
@@ -22,10 +22,10 @@ scalar Binary @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3548")
22
22
  scalar Boolean
23
23
 
24
24
  "The Date scalar type represents a ISO 8601 string value."
25
- scalar Date @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3339")
25
+ scalar Date @specifiedBy(url: "https://en.wikipedia.org/wiki/ISO_8601")
26
26
 
27
27
  "The DateTime scalar type represents a ISO 8601 string value."
28
- scalar DateTime @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3339")
28
+ scalar DateTime @specifiedBy(url: "https://en.wikipedia.org/wiki/ISO_8601")
29
29
 
30
30
  """
31
31
  The Decimal scalar type represents signed fractional values with extra precision.
@@ -61,7 +61,7 @@ scalar String
61
61
  The Time scalar type that represents a distance in time using hours,
62
62
  minutes, seconds, and milliseconds.
63
63
  """
64
- scalar Time @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3339")
64
+ scalar Time @specifiedBy(url: "https://en.wikipedia.org/wiki/ISO_8601")
65
65
 
66
66
  "The valid locations that a directive may be placed."
67
67
  enum __DirectiveLocation {
@@ -22,10 +22,10 @@ scalar Binary @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3548")
22
22
  scalar Boolean
23
23
 
24
24
  "The Date scalar type represents a ISO 8601 string value."
25
- scalar Date @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3339")
25
+ scalar Date @specifiedBy(url: "https://en.wikipedia.org/wiki/ISO_8601")
26
26
 
27
27
  "The DateTime scalar type represents a ISO 8601 string value."
28
- scalar DateTime @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3339")
28
+ scalar DateTime @specifiedBy(url: "https://en.wikipedia.org/wiki/ISO_8601")
29
29
 
30
30
  """
31
31
  The Decimal scalar type represents signed fractional values with extra precision.
@@ -61,7 +61,7 @@ scalar String
61
61
  The Time scalar type that represents a distance in time using hours,
62
62
  minutes, seconds, and milliseconds.
63
63
  """
64
- scalar Time @specifiedBy(url: "https://www.rfc-editor.org/rfc/rfc3339")
64
+ scalar Time @specifiedBy(url: "https://en.wikipedia.org/wiki/ISO_8601")
65
65
 
66
66
  "The valid locations that a directive may be placed."
67
67
  enum __DirectiveLocation {
@@ -25,7 +25,7 @@ class GraphQL_SourceTest < GraphQL::TestCase
25
25
 
26
26
  def test_base_name
27
27
  described_class.stub(:abstract?, false) do
28
- assert_equal('DESCRIBED', described_class.base_name)
28
+ assert_equal('DESCRIBED_CLASS', described_class.base_name)
29
29
  end
30
30
  end
31
31
 
@@ -35,7 +35,7 @@ class Integration_GlobalIDTest < GraphQL::IntegrationTestCase
35
35
  end
36
36
 
37
37
  def test_create_object_field
38
- obj = SCHEMA::NestedTypes::HumanObject[:name]
38
+ obj = SCHEMA.const_get(:NestedTypes)::HumanObject[:name]
39
39
  assert_gid_value('gql://start-wars-mem/Human/name', obj)
40
40
  end
41
41
 
@@ -85,7 +85,7 @@ class Integration_GlobalIDTest < GraphQL::IntegrationTestCase
85
85
 
86
86
  def test_parse_object_field
87
87
  obj = find_gid('gql://start-wars-mem/Human/name')
88
- assert_equal(SCHEMA::NestedTypes::HumanObject[:name], obj)
88
+ assert_equal(SCHEMA.const_get(:NestedTypes)::HumanObject[:name], obj)
89
89
  end
90
90
 
91
91
  def test_parse_scalar_type
@@ -97,7 +97,7 @@ class Integration_ResolverPrecedenceTest < GraphQL::IntegrationTestCase
97
97
  end
98
98
 
99
99
  def test_simple_object
100
- object = SCHEMA::NestedTypes::Object1Object
100
+ object = SCHEMA.const_get(:NestedTypes)::Object1Object
101
101
  field = object[:field1]
102
102
 
103
103
  # (1) Block has higher precedence than default value
@@ -84,6 +84,6 @@ class Integration_SQLite_StarWarsGlobalIDTest < GraphQL::IntegrationTestCase
84
84
  end
85
85
 
86
86
  def source
87
- StartWarsSqliteSchema::NestedTypes::LiteFactionSource
87
+ StartWarsSqliteSchema.const_get(:NestedTypes)::LiteFactionSource
88
88
  end
89
89
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carlos Silva
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-06 00:00:00.000000000 Z
11
+ date: 2023-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -397,7 +397,7 @@ homepage: https://github.com/virtualshield/rails-graphql
397
397
  licenses:
398
398
  - MIT
399
399
  metadata:
400
- homepage_uri: https://www.rails-graphql.dev/
400
+ homepage_uri: https://rails-graphql.dev/
401
401
  source_code_uri: https://github.com/virtualshield/rails-graphql
402
402
  bug_tracker_uri: https://github.com/virtualshield/rails-graphql/issues
403
403
  changelog_uri: https://github.com/virtualshield/rails-graphql/blob/master/CHANGELOG.md
@@ -418,7 +418,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
418
418
  - !ruby/object:Gem::Version
419
419
  version: 1.3.1
420
420
  requirements: []
421
- rubygems_version: 3.2.33
421
+ rubygems_version: 3.3.26
422
422
  signing_key:
423
423
  specification_version: 4
424
424
  summary: GraphQL meets RoR with the most Ruby-like DSL