Ready to get started?

Join Adocasts Plus for $8/mo, or sign into an existing Adocasts Plus account, to get access to all of our lessons.

robot mascot smiling

Creating, Updating, and Deleting Courses

In This Lesson

We'll add endpoints to allow creating, updating, and deleting courses from our API. We'll then use this to stub a number of test courses to give us wiggle room to play with our pagination.

Created by
@tomgobich
Published

Join the Discussion 2 comments

Create a free account to join in on the discussion
  1. @aaron-ford

    Rather than have someone have to know the ids relations, how would it be best to implement using a string? Like for status ID. I can give the user a list of valid statuses. They want to make an API call with a status of 'Planned'. I can have my validator verify that planned exists in the statues table, that's fine, but I want to call the parameter in the API call status, not statusId, since it isn't an ID. That means the validator needs to validate the status 'Planned' exists in the statuses table, and then when we pass the results of the validation to the store course method, it expects a type of courseValidator, which now has status instead of statusId, which doesn't exist on the table. So I'm not sure if I should transform API parameter names before passing the data to the validator, so when the data gets to the validator and the store action the parameters match the DB, or if I should validate and then transform? Transforming before validating kind of seems to reduce the usefulness of the validator, but transforming after validation means we're changing the type expected by the store action to some new transformed object. What would be the best way to do something like this? I hope that makes sense. Essentially I want to use human readable data in the API which requires a parameter name different than the validator/table, but validate it against DB values so the action can use the validated data to create the data in the DB.

    1
    1. Responding to aaron-ford
      @tomgobich

      The way I would recommend to do this is to implement slugs/aliases for those string values so that you have an extra step to ensure they're unique within the database via:

      • A unique constraint directly on the column in the database

      • A unique rule via the validator (if you allow it to be user-defined). You can also generate a unique slug for the user from the name.

      Without that unique constraint, by just using the name, you open up the possibility of Planned matching multiple id values within your database. You can also ensure slugs are all normalized and URL safe, lowercased_with_underscores for example, whereas your names might "Be A Lil' Complex" and need encoded for URL usage.

      Likelihood of that actually happening might be slim, but think of the use-case where someone might use color to differentiate between two equally named statuses. Planned with a red color could mean its planned with issues while Planned green means it's all done.

      Your route parameter, validator, and logic can then access it as slug and safely do a database lookup directly from it since the column would have a unique constraint on it. No need to worry about transforming it!

      Though, if you do need to get an id from the slug for any reason, I wouldn't worry about doing so in the validator. I would instead create a separate service/action method to perform that conversion and call that method from the controller. For example:

      async store({ response, params }: HttpContext) {
        const slug = params.slug
        const id = await GetStatusIdFromSlug.handle({ slug })
        const status = await StoreStatus.handle({ /* ... */ })
      }
      Copied!

      If we're talking accepting slugs in place of all id's needed to create a course, then you could create a separate action/method specifically for that, like StoreCourseFromSlugs or even StoreCourse.fromSlugs(). That could perform the conversion to the id then kick it along to the original store method.

      Hope that helps, Aaron!!

      0