Git Product home page Git Product logo

kittencannon's Introduction

KittenCannon™ Challenge

KittenCannon™ is a proprietary, state-of-the-art system for selling and shipping cats to cat enthusiasts worldwide.

Your challenge, should you choose to accept it:

  1. Basic cat breed tagging API

Basic System

Entity (cat breed):
  |
  -- Tags (traits)
Concrete Example
American Bobtail
  |
  -- affectionate
  -- low shedding
  -- playful
  -- intelligent

Cymric
  |
  -- affectionate
  -- has no tail
  -- friendly

Norwegian Forest Cat
  |
  -- low shedding
  -- pet friendly
  -- knows kung fu
  -- climbs trees

The dbz approach

Because this is an open ended exercise, I'd like to take the opportunity to learn something new: graphql This will definitely make the challenge take much longer than it should, but I will get first hand experience to determine how graphql works as a solution to JSON apis.

Graphql implementation details

I have implemented the following methods:

allBreeds
allTags

createBreed(name: String)
createTag(name: String, breed_id: ID)

updateBreed(name: String, id: ID)
updateTag(name: String, id: ID)

deleteBreed(id: ID)
deleteTag(id: ID)

The following fields are accessable from the Breed and Tag type:

  1. id
  2. name
  3. tags / breeds
  4. tag_count / breed_count

Here is an example query to view all of the breeds with their name and tags. Each tag will also contain the name and id.

query {
  allBreeds {
    name
    id
    tags {
      name
      id
    }
  }
}

It would return something that looks like this:

{
  "data": {
    "allBreeds": [
      {
        "name": "turkish van",
        "id": "4",
        "tags": [
          {
            "name": "soft",
            "id": "5"
          },
          {
            "name": "odd eyed (different color eyes)",
            "id": "6"
          },
          {
            "name": "swims",
            "id": "7"
          }
        ]
      },
      {
        "name": "ragdoll",
        "id": "5",
        "tags": [
          {
            "name": "soft",
            "id": "5"
          },
          {
            "name": "lazy",
            "id": "8"
          }
        ]
      }
    ]
  }
}

Exception Handling

I found a neat gem called graphql-errors which allowed me to put all of my exception handling for errors into my schema. Now JSON gives nice pretty errors.

Example mutation:

mutation {
  deleteTag(id: 200) {
    id
  }
}

Will return the following JSON if id = 200 can not be found:

{
  "data": {
    "deleteTag": null
  },
  "errors": [
    {
      "message": "Record not found: Couldn't find Tag with 'id'=200",
      "locations": [
        {
          "line": 46,
          "column": 3
        }
      ],
      "path": [
        "deleteTag"
      ]
    }
  ]
}

Rails backend

There are two main models: Breed and Tag. I originally wanted to experiment with the has_and_belongs_to_many association rather than the more conventional has_many :through association because it's fun to try new things (cough graphql cough). HABTM does not have a join model, and when adding tags through the breeds' tags association, I can not perform model level validations and have to rely on db level constraints. I'm expecting tons and tons of people to use my service, so I'd like to spare the db from doing all of my validations for me, so I switched to a has_many :through association with a validation on the BreedTag model. We still need the db level constraints in case there are concurrent updates to a breed's tags.

Orphaned tags

The Humane Tag Association™ monitored the creation of the tag deletion api. No tags are orphaned (even for a second) during the deletion of a breed.

Testing

I am a big fan of RSpec, Shoulda-Matchers, Capybara, FactoryGirl, Fuubar, and Database-Cleaner for helping me test. I found a helpful gem called rspec-graphql_matchers which provided a little bit of syntactic sugar when testing my graphql api.

I followed bits of advice from graphql-ruby.org, how to graphql, and rspec-graphql_matcher on proper ways to test the graphql API. However, there is not a lot of documentation and guides on this in the wild, and a good blog post would do the rails community a great service.

kittencannon's People

Contributors

dbz avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.