The ability to reply to discussions is limited to PRO members. Want to join in the discussion? Click here to subscribe now.

Add Caching to the Model Base Class

Add Caching to the Model Base Class

6:58
In the previous lessons we created a base class and looked at a caching mechanism for our models. In this lesson we will expand on that concept by test driving the addition of caching to our model base class, as well as some initial core functionality. *This is advanced subject matter, and will require study of the code as well as watching the video.*
Watch this lesson now
Avatar
egghead.io

In the previous lessons we created a base class and looked at a caching mechanism for our models. In this lesson we will expand on that concept by test driving the addition of caching to our model base class, as well as some initial core functionality. This is advanced subject matter, and will require study of the code as well as watching the video.

Avatar
Loy

Very good post but was wondering if we can take advantage of caching in resource object like

return {
Things: $resource('api/person/:id', {}, {
GetPerson : {
method : 'GET',
cache : true
}
})
};

And also why is cache factory not used for caching?

In reply to egghead.io
Avatar
Joel

You can definitely use $resource as you describe, but this is building an alternative to $resource from scratch. It will serve a similar purpose, as such will share features.

To that same end, cache factory is not used.

In reply to Loy
Avatar
Brett Shollenberger

Ditto what Joel said. While we could use $resource and $cacheFactory we're taking a theoretical look at caching in Javascript, why it's important, and how we can replicate the functionality of Angular (to some degree). I like the idea of understanding how your tools works so you can use them with confidence :)

In reply to Loy
Avatar
Thomas

Hi Brett

I tried to build my own resource manager around $resource and $cacheFactory, but have decided to give your ActiveResource a try instead, and so far it is looking very great.

However, I have a little problem as I'm working with an api, that structures its levels of associations so the endpoint of comments related to posts is like this:

/posts/:id/comments

so when Post.find(1) tries to fetch /comments?post_id=1 -- because posts hasMany('comments') -- it returns nothing.

A can't figure out, if there is some way to configure ActiveResource to work with this api design, do you have any suggestions?

In reply to Brett Shollenberger
Avatar
Wayne

In the previous lessons we created a base class and looked at a caching mechanism for our models. In this lesson we will expand on that concept by test driving the addition of caching to our model base class, as well as some initial core functionality. This is advanced subject matter, and will require study of the code as well as watching the video.

This is really advanced! ...and I like it!

Also, I really enjoy vi/vim myself, but have never seen anyone use it quite this way...I'm so jealous!!! :)

In reply to egghead.io
Avatar
Magnus

I've really enjoyed this series. One thing regarding the use of models that I haven't seen talked much about is how to validate that the model I send to the server and the server sends back to the UI is what the UI expects.

If I send the object
User
{
contactid: "123",
foo: "abc"
};

I do a post to the server to update the User object
$http.post('http://localhost/contact/update', JSON.stringify(user)).success(function( data, status) {

}

If the server sends me back the User object

User
{
contactid: "123",
bar "abc"
};

How would I be able to detect that in a nice way? Seems like there should be a nice way of handling it without having to just compare the object I sent and the object I recieved and having to know what data I may expect to be changed.

In reply to Wayne
Avatar
Kevin

I'm having a hard time following the definition of the privateVariable, particularly how it's setting up accessors.

The use of val variable throughout the function confuses me; I'm confused why value isn't used for get and set instead. The get seems like it'll throw undefined if it wasn't for the if statement at the end of the function (if (value !== undefined) object[name] = value;)

The existence of that particular if statement actually also confuses me because it seems like it should be a conditional statement inside of get instead of being outside the function.

For additional educational purposes, why wouldn't a data property attribute definition wouldn't work?

Within the privateVariable function, the following code snippet probably would work seemingly:

Object.defineProperty(object, name, {
  enumerable: true,
  configurable: false,
  value: value,
  writable: true
}

// value could also take a function that can return value after conditional statements, like checking if it's undefined to perhaps throw an exception or something...
Avatar

Love this series! It's a great introduction to some of the more complex (for me) Angular topics.

I'm following along, and have run into two issues I'm confused by. Not sure if they're bugs or misunderstandings on my part or what.

The first issue has to do with the previous video in the series, in which you define a base-class spec which stubs out a SomeBaseClass and tests that Post can inherit it:

describe('BaseClass', function(){
  describe('Inheritance', function(){
    beforeEach( function() {

      Post.inherits(SomeBaseClass);

      function SomeBaseClass(attributes) {
        var _constructor = this;
        var _prototype   = _constructor.prototype;

        _constructor.new = function(attributes) {
          var instance = new _constructor(attributes)
          return instance;
        };

        _prototype.$save = angular.noop;
    });

    it 'adds methods to the child class', function(){
      expect(Post.new).toBeDefined();
    )};

    it 'adds methods to the instances', function(){
      post = Post.new({});
      expect(post.$save).toBeDefined();
    )};
  });
});

The issue (for me) is that, because you do Post.inherits(SomeBaseClass) before defining SomeBaseClass, I run into this error:

TypeError: 'undefined' is not an object (evaluating 'baseclass.apply')`

I was able to fix the issue by moving Post.inherits(SomeBaseClass) after the definition of SomeBaseClass, but I don't know if that's right, given that it disagrees with your video/code, nor do I get how it could work in your video/code.

Second question has to do with your caching spec in this video.

You write:

expect(Post.cached).toEqual({});`

But when I do that I run into this error:

PhantomJS 1.9.7 (Mac OS X) BCCache adds a cache to the model FAILED
    Expected {  } to equal {  }.
    Error: Expected {  } to equal {  }.

It seems to have something to do with this, but isEqual is supposed to calculate object-equality on the basis of key-value similarity, not reference. Maybe it has to do with the {} object's not having a constructor with Cache?

Am I doing something wrong? Can you think of a way to get around this imperfect equality issue in the spec?

Thanks,

Sasha

In reply to egghead.io
Avatar
Brett Shollenberger

With the first problem--

The code you've posted will work (albeit it's missing a bracket that closes SomeBaseClass); I'm guessing you're using something similar but not exactly this code? The way this works is through function hoisting (http://designpepper.com/blog/drips/variable-and-function-hoisting).

If you're assigning the function to a variable, like below, it won't work:

X.inherits(MyFunction)
var MyFunction = function() {
}

But this will:

X.inherits(MyFunction)
function MyFunction() {
}

With the second problem--
I think this may be a bug on my part; you are correct about the way object equality is tested in Jasmine (https://github.com/pivotal/jasmine/blob/33641578e6f7d90be6155ea6dcb262b11a326fea/src/core/matchers/matchersUtil.js#L143).

The different constructor makes this untrue. You should get the correct results out of:

expect(Post.cached).toEqual(new Cache())
In reply to
Avatar

Thanks! Yeah. I'm using Coffeescript, which may be causing other problems (including why I missed a bracket in translating it back). Maybe Coffeescript automatically assigns the function to a variable?

Thanks for the prompt reply!

In reply to Brett Shollenberger
Avatar
Brett Shollenberger

Yes, you're correct about that as well. Coffeescript removes this behavior because of the ambiguities you're noticing.

You can read more in The Little Book on Coffeescript's chapter "The Bad Parts" under Function Definition (https://arcturo.github.io/library/coffeescript/07_the_bad_parts.html).

In reply to
Avatar
Grégory

The videos "full resource" do not open here. Codec?
All others are normal.

Avatar
Grégory

Sorry, my download manager converted the extension .zip for mp4

In reply to Grégory
Avatar
valery

Hi Guys,

First of all, thank you for your hard work.
Could you help me, I can't download source code for this and other lessons from this playlist.
When I click "available for download" link the browser starts downloading of related video instead of source code.

Thanks.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?