Skip to the content.

Home

Previous: Chapter 10 - The Selection


📝 As an app user, I want to delete a selection, so that I can make the user available again.

So far we’ve only created. Now it’s time to destroy. Lucky for us this should be pretty simple, but let’s think about possible issues. There might be a few things you need to consider when destroying an object and removing its row from the database. One thing might be asynchronous jobs. If you enqueue a job to send an email to a user and then that user is deleted soon after, you might have an issue when the job goes looking. Another major thing to think about is foreign keys. We’ve used foreign keys in our application already. Databases will not let you delete a record if it is referenced by a foreign key. Luckily, we can delete records just fine if they’re referencing another record. For us, we wouldn’t be able to delete rounds or users without removing matching selections first. Of course, we can delete selection records at any time because they only point to rounds and users. In general, we perform true deletion sparingly. When records contain important historical data or are referenced by many foreign keys, I would look for an alternative. For example, instead of deleting users I would go with either a state or archived_at column instead. Here we really want to undo, so let’s cause some destruction.

Generate a new mutation.

Terminal

bin/rails g graphql:mutation_delete Selection

Sort the mutations.

app/graphql/types/mutation_type.rb

module Types
  class MutationType < Types::BaseObject
    field :round_create, mutation: Mutations::RoundCreate
    field :selection_create, mutation: Mutations::SelectionCreate
    field :selection_delete, mutation: Mutations::SelectionDelete
    field :user_create, mutation: Mutations::UserCreate
  end
end

Clean up the new mutation.

app/graphql/mutations/selection_delete.rb

module Mutations
  class SelectionDelete < BaseMutation
    description "Deletes a selection by ID"

    field :selection, Types::SelectionType, null: false

    argument :id, ID, required: true

    def resolve(id:)
      selection = Selection.find(id)
      selection.destroy!
      { selection: selection }
    end
  end
end

Generate a test for the mutation.

Terminal

bin/rails g integration_test types/mutation_type/selection_delete

Fill in the generated tests.

test/integration/types/mutation_type/selection_delete_test.rb

require "test_helper"

class Types::MutationType::SelectionDeleteTest < ActionDispatch::IntegrationTest
  setup do
    @query = <<~GRAPHQL
      mutation SelectionDelete($id: ID!) {
        selectionDelete(input: {
          id: $id
        }) {
          selection {
            id
            createdAt
            updatedAt
            user {
              id
              name
              email
              createdAt
              updatedAt
            }
          }
        }
      }
    GRAPHQL
  end

  test "selection_delete" do
    selection = selections(:full_daniel)
    variables = { id: selection.id }

    assert_difference -> { Selection.count }, -1 do
      post graphql_path, params: { query: @query, variables: variables }

      assert_equal(
        {
          "data" => {
            "selectionDelete" => {
              "selection" => {
                "id" => selection.id.to_s,
                "createdAt" => selection.created_at.iso8601,
                "updatedAt" => selection.updated_at.iso8601,
                "user" => {
                  "id" => selection.user.id.to_s,
                  "name" => selection.user.name,
                  "email" => selection.user.email,
                  "createdAt" => selection.user.created_at.iso8601,
                  "updatedAt" => selection.user.updated_at.iso8601,
                },
              },
            },
          },
        },
        @response.parsed_body
      )

      assert_nil Selection.find_by(id: selection.id)
    end
  end
end

Run the new test.

Terminal

bin/rails t test/integration/types/mutation_type/selection_delete_test.rb

Check for regressions by running all tests.

Terminal

bin/rails t

Success!

âś… Make a commit

âś… As an app user, I want to delete a selection, so that I can make the user available again.


Next: Chapter 12 - The Archive