How to PUT only some fields with Restangular? - javascript

Let's say I have a resource with several fields, and some of them are read-only. Or maybe they belong in different use cases that I would like to handle differently on the server.
For instance, my bing resource looks like this:
{id: 1,
foo: "A",
bar: "B",
createdAt: "2013-05-05"}
I would like to get Restangular to PUT only some fields, executing requests like:
PUT /bing/1 {foo: "A"}
PUT /bing/1 {bar: "B"}
PUT /bing/1 {foo: "A", bar: "B"}
What I do not want to do is:
PUT /bing/1 {id: 1, foo: "A", bar: "B", createdAt: "2013-05-05"}
How can I achieve it?

I'm the creator of Restangular.
#Nicholas is absolutely right :). That's a PATCH and not a PUT. And Restangular does support it :).
elem.patch({foo: 2}) would be the way to go if elem is already a restangularized object.
Hope this helps!!

That's a PATCH not a PUT.
See https://www.rfc-editor.org/rfc/rfc5789

One way to do this is to pass the entire object to the patch method, including all the fields that you don't want to send to the backend, and then use a request interceptor to delete any unwanted fields before the request is sent.
For example, to always delete the field createdAt from any patch request you could do something like
app.config(function(RestangularProvider) {
RestangularProvider.setRequestInterceptor(function(element, operation, route, url) {
if (operation === 'patch') {
delete element.createdAt;
return element;
}
});
});
To learn more about request interceptors see the documentation on setRequestInterceptor

Related

Is it considered a bad practice to validate backend's responses in the frontend?

Consider the frontend makes an API call to a backend service.
client.get('/users');
and the response we are expecting is of the form:
{
data: [
{
id: 1,
name: 'John'
},
...,
{
id: 10,
name: 'Mary'
},
]
}
if I were to use Typescript I would do something like:
type User = {
id: number;
name: string;
}
type UsersResp = {
data: User[]
}
const users = (await client.get<UsersResp>('/users')).data;
Now, lets assume the backend makes a change and instead of sending back the aforementioned response, it just sends:
[
{
id: 1,
name: 'John'
},
...,
{
id: 10,
name: 'Mary'
},
]
Now the frontend will crush since there is no .data property.
My question is if there is any point at validating the response of the server in order to take some action in case the validation fails, ex. display a nice message to the user that something has gone terribly wrong.
Is there any point on doing that or it is just a boilerplate code that achieves nothing ?
The need for validation depends on the situation. There is no simple yes/no answer and it depends on whether a breaking change is likely or not. When in doubt, I would always implement validation mechanisms because without error handling there could be unexpected behavior.
To answer your specific question:
lets assume the backend makes a change and instead of sending back the aforementioned response
From my understanding of your problem, you cannot completely rule out a malformed response. Therefore, the validation is not unnecessary boilerplate code. Without a validation, your client might run into an undefined state, resulting in the UI not working as expected and bad user experience.
One way of validating the shape of the response would be by using user-defined type guards.

Most efficient way of extracting values from an array and passing to an ajax Post call

Currently I am calling ajax and posting the following object as data:
var answer = {
checklist: {id: 1},
question: {id: questionId },
answer: "testing1",
notes: checkInNotes
};
On the server side, this updates the answer and notes in the database where a question and checklist with the id of 1 are found.
Now say I have an array of questionId's that I need to pass in to ajax as part of that question property in that object above. What would be the best way to achieve this in ajax?
Currently I can achieve this by sending an ajax call off to the server x amount of times for each value that I need updated in the database, but this is obviously inefficient.
I'm quite new to ajax so please forgive my lack of knowledge.
Thank you for your time.
JSON allows arrays as well as objects.
You can include an array as one of your object properties (if that is what you need) and get it in the server.
var answer = {
checklist: {id: 1},
question: {id: questionId },
answer: "testing1",
notes: checkInNotes,
arrayOfQuestionId: [ 1, 2, 3, 4 ]
};
You could also send an array of objects instead of just one:
var otherAnswer = [ object1, object2, ... ];
tips: generate mix data and post all it to sever side.
1.send all requests from client
2.send all mix data to server and be parsed.
way1: from server
let url='*',ids=[1,2,3];
//generate paramse of array.
function getarams(){
let requests_params=ids.map(i=>{
let data_temp={question:{id:i}}
return data_temp;
}||[];
return resuests_params;
}
//be parsed from server
$.post(url,{data:getParams()},function(data,status){},'json');<br>
way2: send all posts once
let posts=getParams().map(d=>{
return $.post(url,d)
});
$.when(posts[0],posts[1],posts[2]).then(result=>{
console.log(result);
})

Why does angular $resource query and get expect different responses from the same URL?

I'm asking this because it makes me think I mustn't be doing something the 'angular' way, because my code is unnecessarily complicated.
I've defined a resource
Question = $resource("/questions/:id", {id: "#id"});
now if I do
Question.get(1);
It will go to /questions/1 and expect an object as a response
If I do
Question.query({id: 1});
It will go to /questions/1 but expect an array as the response
I get why it does this because of isArray default setting.
I have client side code that I don't know how many id's it will be querying.
I can easily work around this by having my angular code do
if (ids.length == 1)
Question.get(ids);
else
Question.query({id: ids})
and having my server send an object when array length is 1, but this seems overly complicated and makes me think I must be going about this the wrong way.
Is there a cleaner solution?
Not sure if this is the angular way, but the solution I came to which is slightly cleaner was to use different parameters on my query so that it hits the index method on rails instead of show and so can safely always return an array.
Like so:
Question = $resource("/questions/:id", {id: "#id"});
q = Question.get(1);
// Performs GET /questions/1
// q = { id: 1, ...};
q = Question.query({ids: 1});
// Performs GET /questions?ids=1
// q = [{id: 1, ... }];
q = Question.query({ids: [1,2]});
// Performs GET /questions?ids=1&ids=2
// q = [{id: 1, ... }, {id: 2, ...}];

Backbone.js - make POST request without saving a model

I'm wondering is there a possibility to make this.model.save(data, options) in Backbone without writing data to model?
I have a server endpoint where I need to POST json { field1: 'bbb', field2: 'aaa' } - server writes these fields into db like list: [{ field1: 'bbb', field2: 'aaa' }].
The problem is that Backbone adds these fields to model as well. And I have model like { id: '111', field1: 'bbb', field2: 'aaa', list: [{ field1: 'bbb', field2: 'aaa' }] } and that's wrong..
Is there a way to make save without writing send data to model? Or maybe simply use jquery $.post method and set model on success?
I think the easiest way to fix this would be to either change the data returned by the server, or override the parse method in your model and remove the extra attribute.
A second thought would be to give your moel a single attribute of list and set that with the data dict and have the server return the same. This won't be 100% compatible with general Backbone model usage though.
gotta go..
You can define sync function and make ajax there
You can define parse function and write something like this
parse:function(data)
{
return data.list;
}
2 is the better approach. If setting some field will affect another one, server will return it and you will always have actual data in the model.

How to modify a primary key with Restangular?

I've got a very simple object, called "tag" that has only a string primary key. When I go to edit it...
var tag = Restangular.one('tags', 'cat')
.get(function() { // fetches { id: 'cat' } from server
// edit the tag
tag.id = 'dog';
// save changes
tag.post().then(beHappy, beSad);
});
The request that gets sent off is a call to:
POST /tags/cat/dog
with the correct data:
{ id: 'dog' }
I have no doubt that everything work fine if I wasn't trying to modify my primary key, but my server-side REST API isn't expecting the /oldId/newId format, and so I get a 404. Is this a bug in Restangular, or does my REST API need repairing?
Apparently I've been doing CRUD wrong, doing POST for updates and PUT for creates, which is exactly backwards.
Changing it to tag.put() fixed it.

Categories

Resources