Class: GraphQL::Schema::Visibility::Migration
- Defined in:
- lib/graphql/schema/visibility/migration.rb
Overview
You can use this to see how Warden and Profile
handle .visible?
differently in your schema.
It runs the same method on both implementations and raises an error when the results diverge.
To fix the error, modify your schema so that both implementations return the same thing. Or, open an issue on GitHub to discuss the difference.
This plugin adds overhead to runtime and may cause unexpected crashes -- don't use it in production!
This plugin adds two keys to context
when running:
visibility_migration_running: true
- For the Warden which it instantiates, it adds
visibility_migration_warden_running: true
.
Use those keys to modify your visible?
behavior as needed.
Also, in a pinch, you can set skip_visibility_migration_error: true
in context to turn off this behavior per-query.
(In that case, it uses Profile directly.)
Defined Under Namespace
Classes: RuntimeTypesMismatchError
Constant Summary collapse
- PUBLIC_PROFILE_METHODS =
[ :enum_values, :interfaces, :all_types, :all_types_h, :fields, :loadable?, :loadable_possible_types, :type, :arguments, :argument, :directive_exists?, :directives, :field, :query_root, :mutation_root, :possible_types, :subscription_root, :reachable_type?, :visible_enum_value?, ]
Instance Attribute Summary
Attributes inherited from Profile
Instance Method Summary collapse
- #call_method_and_compare(method, args) ⇒ Object
- #equivalent_schema_members?(member1, member2) ⇒ Boolean
-
#initialize(context:, schema:, name: nil) ⇒ Migration
constructor
A new instance of Migration.
- #loaded_types ⇒ Object
Methods inherited from Profile
#all_types, #all_types_h, #argument, #arguments, #directive_exists?, #directives, #enum_values, #field, #field_on_visible_interface?, #fields, from_context, #interfaces, #loadable?, #loadable_possible_types, #mutation_root, null_profile, #possible_types, #query_root, #reachable_type?, #subscription_root, #type, #visible_enum_value?
Constructor Details
#initialize(context:, schema:, name: nil) ⇒ Migration
Returns a new instance of Migration.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/graphql/schema/visibility/migration.rb', line 79 def initialize(context:, schema:, name: nil) @name = name @skip_error = context[:skip_visibility_migration_error] || context.is_a?(Query::NullContext) || context.is_a?(Hash) @profile_types = GraphQL::Schema::Visibility::Profile.new(context: context, schema: schema) if !@skip_error context[:visibility_migration_running] = true warden_ctx_vals = context.to_h.dup warden_ctx_vals[:visibility_migration_warden_running] = true if schema.const_defined?(:WardenCompatSchema, false) # don't use a defn from a superclass warden_schema = schema.const_get(:WardenCompatSchema, false) else warden_schema = Class.new(schema) warden_schema.use_visibility_profile = false # TODO public API warden_schema.send(:add_type_and_traverse, [warden_schema.query, warden_schema.mutation, warden_schema.subscription].compact, root: true) warden_schema.send(:add_type_and_traverse, warden_schema.directives.values + warden_schema.orphan_types, root: false) schema.const_set(:WardenCompatSchema, warden_schema) end warden_ctx = GraphQL::Query::Context.new(query: context.query, values: warden_ctx_vals) warden_ctx.warden = GraphQL::Schema::Warden.new(schema: warden_schema, context: warden_ctx) warden_ctx.warden.skip_warning = true warden_ctx.types = @warden_types = warden_ctx.warden.visibility_profile end end |
Instance Method Details
#call_method_and_compare(method, args) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/graphql/schema/visibility/migration.rb', line 136 def call_method_and_compare(method, args) res_1 = @profile_types.public_send(method, *args) if @skip_error return res_1 end res_2 = @warden_types.public_send(method, *args) normalized_res_1 = res_1.is_a?(Array) ? Set.new(res_1) : res_1 normalized_res_2 = res_2.is_a?(Array) ? Set.new(res_2) : res_2 if !equivalent_schema_members?(normalized_res_1, normalized_res_2) # Raise the errors with the orignally returned values: err = RuntimeTypesMismatchError.new(method, res_2, res_1, args) raise err else res_1 end end |
#equivalent_schema_members?(member1, member2) ⇒ Boolean
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/graphql/schema/visibility/migration.rb', line 154 def equivalent_schema_members?(member1, member2) if member1.class != member2.class return false end case member1 when Set member1_array = member1.to_a.sort_by(&:graphql_name) member2_array = member2.to_a.sort_by(&:graphql_name) member1_array.each_with_index do |inner_member1, idx| inner_member2 = member2_array[idx] equivalent_schema_members?(inner_member1, inner_member2) end when GraphQL::Schema::Field member1.ensure_loaded member2.ensure_loaded if member1.introspection? && member2.introspection? member1.inspect == member2.inspect else member1 == member2 end when Module if member1.introspection? && member2.introspection? member1.graphql_name == member2.graphql_name else member1 == member2 end else member1 == member2 end end |
#loaded_types ⇒ Object
104 105 106 |
# File 'lib/graphql/schema/visibility/migration.rb', line 104 def loaded_types @profile_types.loaded_types end |