0

I have three resource types - character, word, and write (these are three separate database tables, with word and write having a foreign key dependency on character).

When character is created (upon a user save process), word and write also must be created. Character has a few values, but one of the most important is "active" - which is a boolean flag.

However, I don't necessarily care that the client knows the state of character in the database. I want a user be able to click something, and send a PUT request and the end result should be an "active" character in the database - whether or not that character entry existed beforehand.

Ultimately what should happen for every PUT is that character is created or set to active status (which it will have by default if created - so basically, character will exist in its default state after a PUT)

However, if the two children are created, I obviously don't need to create them again, nor do I want to reset them (they must track their state separately from their parent).

I have a few different ideas on how I could do this, but I'm not sure which is the most "REST"ful.

I could:

1) Create the records in the word and write tables on the initial PUT request, and check for their existence and do nothing on subsequent requests. This is probably the easiest way/cheapest way, but it is not idempotent.

2) Create three PUT requests (with upsert functionality on the backend) on a client side action, with the end result being that a record exists in all three tables. Downsides of this are that I have to send three separate PUT requests (which is expensive), and they'd have to be timed correctly - very messy.

Do a GET call on any relevant character a user tries to save first, and if it already exists, issue a PATCH updating its status to the opposite of its current active status. This is a bit cleaner than #2, but also requires quite a bit of back and forth between client and server.

I'm not really sure exactly the best way to design the REST API in this context - can anyone give me advice on how they'd probably think it should be done?

2
  • I may be missing something, but how is 1) not idempotent? If you send the exact same request twice, and do nothing on the second one (no state is changed) due to performing checks, then the operation is idempotent. May 10, 2020 at 11:25
  • @FilipMilovanović The first ever request will create three records. All subsequent requests will do nothing, EXCEPT if the first record (the parent record) has "active" set to false, it will be set to true. My understanding is that that is not idempotent May 10, 2020 at 17:59

1 Answer 1

1

How do I stay RESTful

By thinking about how you would model your interactions on the world wide web.

I have three resource types - character, word, and write (these are three separate database tables, with word and write having a foreign key dependency on character).

This is a description of a data model. In REST, the thing that we care about is the resource model - think "web pages". You might have one resource that surfaces the data from all three of these tables, you might have many many resources that share data from those three tables.

I want a user be able to click something, and send a PUT request and the end result should be an "active" character in the database - whether or not that character entry existed beforehand.

In HTTP, "PUT" means something very specific: it's a method designed for editing resources. For instance, if you wanted to change the title of your home page, the interaction would look something like

GET /home.html
(change the title in your local copy)
PUT /home.html

Think "save document". Just like save, the document doesn't have to exist first

PUT /new.html

It's up to the server to figure out how to express the semantics of the request in its own data model. In the simple case, you just compare the two representations, compute the commands required to update your data model, and then apply those commands.

With complex data models, that can be challenging to implement.

There are lots of trade offs you can make. It is okay to use POST, if you are willing to relax the idempotent constraint. A resource can have more than one representation, and maybe you encourage PUT to use a specific representation, like text/csv. You can have different resources specifically to support remote authoring, with links to help the client navigate through the resource model. You can decide that a relational data model isn't the right fit for your interface.

1
  • Ok, so it seems using POST is ok here. There's not really a way this can be "standardized", as my use-cases on creation and update are different. Thanks. It seems I'm being perhaps a bit too dogmatic to my idea of what REST "is". Thanks May 9, 2020 at 20:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.