From the docs:
Class actions return empty instance (with additional properties below). Instance actions return promise of the action
The documentations however doesn't clearly differentiate between Class actions and Instance actions. Could you please point out differences with a good example if possible?
When you create a new resource type, you supply it a list of actions that can be performed. By default, these are get
, save
, query
, delete
, and remove
(I think remove is just an alias of delete). You can add your own, as it says in the docs.
The thing about class vs instance is in regard to something it does for convenience of use. "Class actions" refers to calling the action off the resource class that you create itself, kinda like static or shared methods in some other languages. This is useful as an entry point for getting, querying, or saving an instance of your resource when you don't already have the instance. get
and query
are the clearest example of this. If you have a Car
resource, and you need to retrieve it, where do you start? With a class action, of course, such as get
.
Now, when your resource class retrieves an existing instance, or you create a new instance, $resource
will extend your instance with the actions defined for your resource, but prefix them with a $
so they don't collide with fields on your resource. These are your instance actions. The difference between instance and class, is instance is done in the context of the current instance. So if you get
an instance, but then call $save
or $delete
on that instance, it will save or delete that instance specifically. Instance actions are there simply for convenience.
So they are pretty much the same, the difference is the context in which they are being used.
function($resource) {
// first let's define a new resource for car, where all cars have an id field
// calling $resource will create a new resource class that can be used to
// create, retrieve, update, or delete instances
// this is usually done as a service and injected into controllers as needed.
var Car = $resource('/api/car/:id', {id: '@id'});
// the car class we just created has some class actions that can help you query for or get car instances
// let's create a new instance of a car and save it
var newCar = new Car({make: 'Toyota', model: 'Prius'});
// the prototype of Car includes the instance action versions of the actions defined for the resource. below, $save is your instance action
newCar.$save(); // server will respond with the object after it's saved, so we can now access the id. let's say the id it returned is 24, we'll reference this value later.
// now, let's imagine some time later we want to retrieve the car and update it
// Car.get is a class action that requests the resource from the server, parses the JSON into an object, and merges it with the Car instance prototype so you have your instance actions
// let's get the car we created previously.
// remember, this is done asynchronously, so we will do our work in a success handler that we provide to get
Car.get({id: 24}, function(myCar) {
// let's update the car now that we have it. let's set the year of the model and the color
myCar.year = 2004;
myCar.color = 'white';
// now, let's save our changes by calling the instance action $save
myCar.$save();
});
// now, let's query for all cars and get an array back
// query is a class function that expects an array of your resource to be returned
Car.query(function(cars) {
// trivial example, we're just going to enumerate the cars we found and log some info about them
for(var i = 0; i < cars.length; i++)
console.log('Found ' + cars[0].color + ' ' cars[0].year + ' ' + cars[0].make + ' ' + cars[0].model);
});
// ok, let's delete the car we created earlier. use the class action delete
Car.delete({id: 24});
}
You can technically call any actions either as a class or as an instance, but it will become obvious that some are awkward to use as instance actions and vise versa. For example, while you technically can use query
as an instance action, you wouldn't do that in practice because it's extra work and it's awkward (you'd have to do new Car().$query()
. That's silly. Car.query()
is easier and makes more sense). So, the usage in my example above represents your normal usage.
Update:
save
vs $save
$save
is similar to save
, but it assumes the data you want to submit during save is itself, since $save
is an instance action. It is particularly useful because after the response is received, it'll update itself with the object returned by your HTTP endpoint. So if your service saves the object with some additional values populated on the server side, such as an ID, then sends the object back as JSON, $save
will update the instance with the returned JSON object.
var car = new Car({make: 'Toyota', model: 'Prius'});
// at this point there is no id property, only make and model
car.$save(function() {
// angular is async, so we need a success handler to continue the explanation
// assuming your server assigned an ID and sent the resulting object back as JSON, you can now access id off the original object
console.log(car.id); // has a value now
});
You could do something similar with the class method, but it's awkward, particularly if other code in your controller needs to reference the car as you are working on it
Car.save({make: 'Toyota', model: 'Prius'}, function(car) {
// ok, we have an ID now
console.log(car.id);
});
or
var car = new Car({...});
Car.save(car, function(newCar) {
car = newCar; // wut? that's awkward
});
save
could be useful during instances where you are quickly saving a small object, or are performing a sort of "fire and forget". Anyways, I rarely use save
myself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With