0

I'm working on a side project to learn implementation of GraphQL into a Rails 6 app. To do this, I'm using the graphql-ruby gem.

I've got a resolve method to update a Medium model that looks like this:

module Mutations
  module Media
    class UpdateMedia < GraphQL::Schema::Mutation
      include ::GraphqlAuthenticationConcerns
      include ::GraphqlActiveModelConcerns

      description 'Update Media'
      argument :id, Integer, required: true
      argument :title, String, required: false
      argument :preview_url, String, required: false
      argument :preview_image, String, required: false
      argument :watched, Boolean, required: false
      field :success, Boolean, null: false
      field :errors, [Types::ActiveModelError], null: false
      field :media, Types::MediumType, null: false

      def resolve(id:, title:, release_date:, preview_url:, preview_image:, watched:)
        authenticate_user!

        media = Medium.find(id)

        media_params = {
          title: title,
          preview_url: preview_url,
          preview_image: preview_image,
          watched: watched,
        }

        if media.update(media_params)
          success_response(media)
        else
          failed_response(media)
        end
      end

      private

      def success_response(media)
        {
          success: true,
          errors: [],
          media: media
        }
      end

      def failed_response(media)
        {
          success: false,
          errors: errors(media)
        }
      end
    end
  end
end

If I set up the arguments in this way and I want to only update the watched field, I receive a 500 error stating missing keywords: :title, :release_date, :preview_url, :preview_image.

I saw this issue in the graphql-ruby repo from someone with the same problem, however they were told to set default values to nil, and when I tried this it of course sets every column for that model to nil.

I want to be able to change just the fields that are actually being passed as arguments, without affecting others. How do I allow for both a required parameter (id), as well as optional arguments?

J. Jackson
  • 3,326
  • 8
  • 34
  • 74

1 Answers1

1

Finally figured it out. By defining the method like this:

def resolve(id:, **args)
  authenticate_user!

  media = Medium.find(id)

  if media.update(args)
    success_response(media)
  else
    failed_response(media)
  end
end

this keeps the id argument as required, and allows other params to pass through without setting the entire record to nil.

Ended up being more of a general Ruby question rather than specific to graphql-ruby.

J. Jackson
  • 3,326
  • 8
  • 34
  • 74