Module: Quail::Resource::MutationBuilder
- Defined in:
- lib/quail/resource/mutation_builder.rb,
lib/quail/resource/mutation_builder/context.rb,
lib/quail/resource/mutation_builder/resolvers.rb
Overview
Builds create, update, and delete GraphQL mutations for a resource.
Defined Under Namespace
Modules: Resolvers Classes: MutationContext
Class Method Summary collapse
- .add_result_fields(klass, underscore_name, type_class) ⇒ Object
- .add_writable_arguments(klass, model, writable, required:) ⇒ Object
- .build_create(ctx) ⇒ Object
- .build_delete(ctx) ⇒ Object
- .build_mutation(action, ctx) ⇒ Object
- .build_update(ctx) ⇒ Object
-
.call(resource_class) ⇒ Object
rubocop:disable Metrics/ModuleLength.
- .capture_delete_snapshot(subs, record) ⇒ Object
- .default_writable(model, resource_class = nil) ⇒ Object
- .new_mutation_class(ctx, prefix, model) ⇒ Object
- .polymorphic_columns(resource_class) ⇒ Object
- .resolve_scope(scope_config, record) ⇒ Object
- .trigger_delete_event(gql_context, name, snapshot) ⇒ Object
- .trigger_subscription(gql_context, subs, event, underscore_name, record) ⇒ Object
Class Method Details
.add_result_fields(klass, underscore_name, type_class) ⇒ Object
71 72 73 74 |
# File 'lib/quail/resource/mutation_builder.rb', line 71 def self.add_result_fields(klass, underscore_name, type_class) klass.field underscore_name.to_sym, type_class, null: true klass.field :errors, [GraphQL::Types::String], null: false end |
.add_writable_arguments(klass, model, writable, required:) ⇒ Object
62 63 64 65 66 67 68 69 |
# File 'lib/quail/resource/mutation_builder.rb', line 62 def self.add_writable_arguments(klass, model, writable, required:) writable.each do |attr| col = model.columns_hash[attr.to_s] next unless col klass.argument attr, TypeMap.graphql_types(col), required: required ? !TypeMap.nullable?(col) : false end end |
.build_create(ctx) ⇒ Object
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/quail/resource/mutation_builder.rb', line 96 def self.build_create(ctx) model = ctx.model name = ctx.underscore_name subs = ctx.subscriptions klass = new_mutation_class(ctx, "Create", model) add_writable_arguments(klass, model, ctx.writable, required: true) add_result_fields(klass, name, ctx.type_class) klass.define_method(:resolve) { |**attrs| Resolvers.create(model, name, subs, context, attrs) } klass end |
.build_delete(ctx) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/quail/resource/mutation_builder.rb', line 119 def self.build_delete(ctx) model = ctx.model name = ctx.underscore_name subs = ctx.subscriptions klass = new_mutation_class(ctx, "Delete", model) klass.argument :id, GraphQL::Types::ID, required: true klass.field :success, GraphQL::Types::Boolean, null: false klass.field :errors, [GraphQL::Types::String], null: false klass.define_method(:resolve) { |id:| Resolvers.delete(model, name, subs, context, id) } klass end |
.build_mutation(action, ctx) ⇒ Object
24 25 26 27 28 29 30 |
# File 'lib/quail/resource/mutation_builder.rb', line 24 def self.build_mutation(action, ctx) case action when :create then build_create(ctx) when :update then build_update(ctx) when :delete then build_delete(ctx) end end |
.build_update(ctx) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/quail/resource/mutation_builder.rb', line 107 def self.build_update(ctx) model, name, subs = ctx.model, ctx.underscore_name, ctx.subscriptions klass = new_mutation_class(ctx, "Update", model) klass.argument :id, GraphQL::Types::ID, required: true add_writable_arguments(klass, model, ctx.writable, required: false) add_result_fields(klass, name, ctx.type_class) klass.define_method(:resolve) do |id:, **attrs| Resolvers.update(model, name, subs, context, { id: id, attrs: attrs }) end klass end |
.call(resource_class) ⇒ Object
rubocop:disable Metrics/ModuleLength
10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/quail/resource/mutation_builder.rb', line 10 def self.call(resource_class) skipped = resource_class.skipped_mutations overrides = resource_class.resolved_mutation_overrides ctx = MutationContext.new(resource_class) mutations = {} %i[create update delete].each do |action| next if skipped.include?(action) mutations[action] = overrides[action] || build_mutation(action, ctx) end mutations end |
.capture_delete_snapshot(subs, record) ⇒ Object
84 85 86 87 88 |
# File 'lib/quail/resource/mutation_builder.rb', line 84 def self.capture_delete_snapshot(subs, record) return nil unless subs[:delete] { attributes: record.attributes, scope_args: resolve_scope(subs[:delete][:scope], record) } end |
.default_writable(model, resource_class = nil) ⇒ Object
32 33 34 35 36 |
# File 'lib/quail/resource/mutation_builder.rb', line 32 def self.default_writable(model, resource_class = nil) excluded = %i[id created_at updated_at] excluded += polymorphic_columns(resource_class) if resource_class model.column_names.map(&:to_sym).reject { |c| excluded.include?(c) } end |
.new_mutation_class(ctx, prefix, model) ⇒ Object
131 132 133 134 135 136 |
# File 'lib/quail/resource/mutation_builder.rb', line 131 def self.new_mutation_class(ctx, prefix, model) Class.new(ctx.base) do graphql_name "#{prefix}#{model.name}" description "#{prefix}s a #{model.name}" end end |
.polymorphic_columns(resource_class) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/quail/resource/mutation_builder.rb', line 38 def self.polymorphic_columns(resource_class) return [] unless resource_class resource_class.association_definitions .select { |_, config| config[:polymorphic] } .flat_map do |name, _| [ :"#{name}_type", :"#{name}_id" ] end end |
.resolve_scope(scope_config, record) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/quail/resource/mutation_builder.rb', line 50 def self.resolve_scope(scope_config, record) return {} unless scope_config case scope_config when Symbol then { scope_config => record.public_send(scope_config) } when Hash key, value_proc = scope_config.first { key.to_sym => value_proc.call(record) } else {} end end |
.trigger_delete_event(gql_context, name, snapshot) ⇒ Object
90 91 92 93 94 |
# File 'lib/quail/resource/mutation_builder.rb', line 90 def self.trigger_delete_event(gql_context, name, snapshot) return unless snapshot gql_context.schema.subscriptions&.trigger(:"#{name}_deleted", snapshot[:scope_args], snapshot[:attributes]) end |
.trigger_subscription(gql_context, subs, event, underscore_name, record) ⇒ Object
76 77 78 79 80 81 82 |
# File 'lib/quail/resource/mutation_builder.rb', line 76 def self.trigger_subscription(gql_context, subs, event, underscore_name, record) sub_config = subs[event] return unless sub_config scope_args = resolve_scope(sub_config[:scope], record) gql_context.schema.subscriptions&.trigger(:"#{underscore_name}_#{event}d", scope_args, record) end |