I'm documenting an API and I have 2 responses very similar.
One of them is the call /resource/{id}.
This response returns a resource model.
The other call is /resource/search{?name,category} which returns a list of resources so I need to return an array of the resource model.
I can't find if I can do this. On the blueprint documentation there is something similar about Gists. But there are two models Gist and Gist Collection.
I hope I explained my self.
Unfortunately at this moment you cannot reference one payload from another. The reason for this is that a payload (model, request or response) is opaque to the API Blueprint parser (and therefore you do not have to escape anything within).
There are plans to address this need and make blueprints more DRY in the future - See the Embedded Assets and Traits milestones.
Related
As a newcomer to spring I would like to know the actual difference between:-
#PostMapping
#PutMapping
#PatchMapping
My understanding is PUT is for update but then we have to get the element by its id and then save() it. Similarly the save() method is again used by Post which automatically replaces by its identifier(PRIMARY). In my application I am able to use three of these methods interchangeably.
What is the point of having PATCH, POST, PUT types when we use repository save methods for all?
HTTP method tokens are used to define request semantics in such a way that general purpose components (browsers, reverse proxies, etc) can exploit the information to do intelligent things.
The easiest of these is that PUT has idempotent semantics; if an http response is lost, a general purpose component knows that it may autonomously retry sending the request. This in turn gives you a bit of extra reliability over an unreliable network, "for free".
The fact that your origin server uses the same persistence mechanism for each is an implementation detail, something deliberately hidden behind the "uniform interface".
The difference between PATCH and POST is subtle; PATCH gives you an unambiguous way to designate that the enclosed entity is a patch document, and offers a mechanism for discovering which patch document formats are understood by the origin server, neither of which you get from POST alone.
What's less clear, at least to me, is whether PATCH semantics allow an intermediate component to do something intelligent with a request - in other words, do the additional constraints (relative to POST) allow intermediaries to do anything interesting?
As best I can tell, the semantics of a PATCH request are more specific, but not actionably more specific -- certainly not as obviously as we have in the case of safe or idempotent request semantics.
POST is for creating a brand new object.
PUT will replace all of an objects properties in one go.
Leaving a property empty will empty the value in the datastore.
PATCH does a partial update of an object.
You can send it just the properties which should be updated.
A PATCH request with all object properties included will have the same effect as a POST request. But they are not the same.
The HTTP method is a convention not specific to Spring but is a main pillar of the REST API specification.
They make sure the intent of a request is clear and both the provider and consumer are in agreement of the end result.
Kind of like the pedals or gear shift in our cars. It's a lot easier when they all work the same.
Switching them up could lead to a lot of accidents.
For us as developers, it means we can expect most REST APIs to behave in a similar way, assuming an API is implemented according to or reasonably close to the specification.
POST/PUT/PATCH may look alike but there are subtle differences.
As you mention the PUT and PATCH methods require some kind of ID of the object to be updated.
In an example of a combined POST/PUT/PATCH endpoint, sending a request with an object, omitting some of its properties. How does the API react?
Update only the received properties.
Update the entire object, emptying the omitted properties.
Attempt to create a new object.
How is the consumer of the endpoint to know which of the three actions the server took?
This is where the HTTP method and specification/convention help determine the appropriate course of action.
Spring may facilitate the save method which can handle both creation, updates and partial updates. But this is not necessarily the case for other frameworks in Java or other languages.
Also, your application may be simple enough to handle POST/PUT/PATCH in the same controller method right now.
But over time as your application grows more complex, the separation of concerns makes your code a lot cleaner, more readable and maintainable.
Not sure this is specific to Laravel but what is the proper RESTFUL way to handle creating a child of a parent with Laravel. For example I have a Car that can have many Drivers (hasMany) and Drivers belong to one Car (belongsTo). If I want to create a Driver whose parent is Car #1 does the CarController.php have the responsibility to create the driver: /car/1/driver/create or do I use /driver/create/car/1 and keep the responsibility within DriverController.php?
Right now I'm doing /driver/create/1 (where #1 represents the Car) which feels wrong but I'm not clear about what the RESTFUL way should be. TIA.
There really isn't a proper way of implementing nested resources in REST as it doesn't really care. There are arguments for and against nested resources, however, there are some generally accepted implementations and the agreement that whatever you decide on, be consistent.
I utilise nested resources, but only a single level of nesting and no more. So for example:
GET /cars/{carId}/drivers/{driverId}
However, I would avoid the following:
GET /cars/{carId}/drivers/{driverId}/incidents
If you have multiple nested resources, consider obtaining the nested resource through the parent resource:
GET /cars/{carId}/drivers/ // Get all drivers for the car
GET /drivers/{driverId}/incidents // Get all incidents for the driver
Arguably nested resource URLs can convey more meaning than a single resource URL at a glance. e.g.
GET /cars/{carId}/drivers/{driverId} // more meaningful
GET /drivers/{driverId} // less meaningful
With the second URL above, I do not know which car the requested driver is associated with until the resource is returned. That being said /drivers/{driverId} can still be applicable and useful to have depending on your use case.
A use case for a /drivers endpoint would be if you can create new drivers that are not yet associated with a car.
In response to your question of how to create a driver, I would consider the following use cases;
Create a driver without an association to a car
POST /drivers
Create a driver with an association to a car
POST /cars/{carId}/drivers
POST /drivers
For the POST /drivers endpoint you would use a DriverController and pass your Driver information to the store method. The validation rules in the store method would allow for an optional car_id parameter as part of the request. This would allow you to either associate a driver with a car at creation, or not.
For the POST /cars/{carId}/drivers endpoint, you would use a CarDriverController (or a DriverController in a Cars subfolder if often seen) and pass your Driver information to the store method. A car_id paramter would not be required in the request as the associated car would be obtained from the {carId} passed in the URL.
For updating your driver resources, you can follow the same principle just amending your HTTP verbs and creating the appropriate routes.
PUT /drivers/{driverId}
DriverController#update
PUT /cars/{carId}/drivers/{driverId}
CarDriverController#update
If you decided to implement both methods for creating drivers and you find duplicate code, consider refactoring it to a service.
Update 1
For #2 POST /cars/{carId}/drivers is the store endpoint does that make GET /cars/{carId}/drivers/create the create endpoint? And similarly for POST /drivers creation endpoint GET /drivers/cars/{carId}?
If you're working with blade views and following the Laravel conventions then your form to create a new driver for a given car would be found at GET /cars/{carId}/drivers/create or GET /drivers/create.
And it sounds like relationships should always get a separate controller.
Ideally yes as most applications are nothing more than CRUD and so everything can be mapped to one of the 7 controller actions. This keeps things clean and simple and responsibilities separate.
Take a look at this video by Adam Wathan which explains how to map what you think are custom actions to one of the 7 basic Laravel actions. Bit lengthy at 40 minutes but well worth a watch.
POST /cars/1/driver.
no interest in specifying the action (create). the method (post) already does it.
We're providing a public API that we use internally but also provide to our SaaS users as a feature. I have a Model, a ModelSerializer and a ModelViewSet. Everything is functional but it's blurting out the Model help_text for the description in the API documentation.
While this works for some fields, we would like to be a lot more explicit for API users, providing examples, not just explanations of guidance.
I realise I can redefine each field in a Serializer (with the same name, then just add a new help_text argument, but this is pretty boring work.
Can I provide (eg) a dictionary of field names and their text?
If not, how can I intercede in the documentation process to make something like that work?
Also, related, is there a way to provide a full example for each Viewset endpoint? Eg showing what is submitted and returned, like a lot of popular APIs do (Stripe as an example). Or am I asking too much from DRF's documentation generation? Should I handle this all externally?
To override help_text values coming from the models, you'll need to use your own schema generator subclass and override get_path_fields. There you'd be able to prioritize a mapping on the viewset (as you envision) over the model fields help_text values.
On adjusting the example generation - you could define a JSON language which just deals with raw JSON and illustrate the request side of things pretty easily, however, illustrating responses is difficult without really getting deep into the plumbing, as the default schema generated does not contain response structure data.
Dumb question but I have some lingering confusion of what, exactly, a "resource" is in Rails. The term is used everywhere but I get a funny feeling it might be being used rather loosely. It's referenced in the model, the controller and, quite literally, in routes.rb.
Is it the specific route? For example, map.resources maps the 7 RESTful "resources". So an example of one resource would be the call to, say, the index action of a particular class's controller?!?
Is it a reference to the whole page/object being retrieved? or perhaps, more narrowly, a database table? or the row being retreived?
Is it something else?
Anyway, hopefully someone can set me straight...
Any object that you want users to be able to access via URI and perform CRUD (or some subset thereof) operations on can be thought of as a resource. In the Rails sense, it is generally a database table which is represented by a model, and acted on through a controller.
For example, you might have a User resource (with a users table in your DB). This is represented by a User model, is mapped to users_controller with map.resources :users (which then generates routes like /users (a collection of User resources) and /users/1 (a specific User resource).
You act upon those resources by using the appropriate HTTP method when making calls to those resources. POST to the resource collection (/users) creates a new record; GET retrieves a list of resources (/users) or a specific user (/users/1). PUT updates a specific user (/users/1/), and DELETE destroys that user. The URLs are the same, but the result (and controller action) may be different based on the HTTP verb. The idea, though is that /users/1 always means "I'm interacting with the User that has ID #1", regardless of the action.
Here's a good article discussing how most developers think that "Resource" is synonomous with the database table, the argument, I guess, being that mapping to the resource is mapping the controller to that database table (or, with ActiveResource, to another REST url).
Basically, I think a "resource" is "persisted data." map.resources maps the 7 RESTful actions to a particular suite of persisted data.
But I haven't thought about it too much in depth. Good question!
I think they probably mean it in the general web sense, i.e., Resource (Web):
the referent of any Uniform Resource Identifier
I don't think it has anything to do with database tables.
open your model folder, that is a hint of what resources you have!
example: users, pictures, comments...
A lot of people here say that resources refer to the database tables you have. It might be true sometimes but not necessarily true always. I could give you a lot of examples where you don't have a corresponding table in your database for a particular resource. Hence asssociating it with tables is rather wrong.
I would define a resource as a route which maps to related requests. So instead of declaring separate routes for the actions you want to do you can simply declare them using a resourceful route.In Rails, a resourceful route provides a mapping between HTTP requests and URLs to controller actions.
So say you define resources :users in config/routes.rb. You can now use a number of helpers to the controllers in your application like edit_user_path which returns users/edit .
Here's a good link: https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/Routing/Mapper/Resources.html
Which basically says: Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, new, edit, create, update and destroy actions, a resourceful route declares them in a single line of code:
resources :photos
Right now I can't get the concept behind Spring Data REST if it comes to complex aggregate roots. If I understand Domain Driven Design correctly (which is AFAIK the base principle for spring data?), you only expose aggregate roots through repositories.
Let's say I have two classes Post and Comment. Both are entities and Post has a #OneToMany List<Comment> comments.
Since Post is obviously the aggregate root I'd like to access it through a PostRepository. If I create #RepositoryRestResource public interface PostRepository extends CrudRepository<Post, Long> REST access to Post works fine.
Now comments is renderd inline and is not exposed as a sub resource like /posts/{post}/comments. This happens only if I introduce a CommentRepository (which I shouldn't do if I want to stick to DDD).
So how do you use Spring Data REST properly with complex domain objects? Let's say you have to check that all comments does not contain more than X characters alltogether. This would clearly be some invariant handled by the Post aggregate root. Where would you place the logic for Post.addComment()? How do you expose other classes as sub resources so I can access /posts/{post}/comments/{comment} without introducing unnecessary repositories?
For starters, if there is some constraint on Comment, then I would put that constraint in the constructor call. That way, you don't depend on any external validation frameworks or mechanisms to enforce your requirements. If you are driven to setter-based solutions (such as via Jackson), then you can ALSO put those constraints in the setter.
This way, Post doesn't have to worry about enforcing constraints on Comment.
Additionally, if you use Spring Data REST and only define a PostRepository, since the lifecycle of the comments are jointly linked to the aggregate root Post, the flow should be:
Get a Post and its collection of Comment objects.
Append your new Comment to the collection.
PUT the new Post and its updated collection of Comment objects to that resource.
Worried about collisions? That's what conditional operations are for, using standard HTTP headers. If you add a #Version based attribute to your Post domain object, then every time a given Post is updated with a new Comment, the version will increase.
When you GET the resource, Spring Data REST will include an E-Tag header.
That way, your PUT can be conditionalized with an HTTP If-Match: <etag> header. If someone else has updated the entity, you'll get back a 412 Status code, indicating you should refresh and try again.
NOTE: These conditional operations work for PUT, PATCH, and DELETE calls.