Canjs - Extending can.Model with additional Methods

496 views Asked by At

I'm not the first person to ask this... the answers basically say "Well you're doing REST wrong." Fair enough, but development is filled with tradeoffs and I often find myself not in a position to rewrite the API.

Moving on to the problem at hand, what's the most elegant way to add a method for some resource to a model?

var Issue = can.Model.extend({
  findAll: 'GET Issues',
  findOne: 'GET Issues/{id}',
  findRelated: can.Model.makeFindAll(function(params) {
    return can.ajax({
      type: 'GET',
      url: 'Issues/'+params.id+'/'
    });
  })
},{});

jsfiddle

2

There are 2 answers

0
Alfredo Delgado On BEST ANSWER

If I understand the question correctly, you want to get an Issue.List from findRelated.

var Issue = can.Model.extend({
  findAll: 'GET Issues',
  findOne: 'GET Issues/{id}',

  findRelated: function(params) {
    var deferred = new can.Deferred();

    can.ajax({
      type: 'GET',
      url: 'Issue/'+params.id+'/Related'
    }).then(function(response) {
      // success
      deferred.resolve(Issue.models(response || []));
    }, function(xhr, textStatus, err) {
      // failure
      deferred.reject(err);
    });

    return deferred;
  }

},{});

jsfiddle

0
mehiel On

Another option, similar to the accepted answer, is to return can.ajax instead of creating a new deferred. It's a bit less verbose.

Also, as of v2.1, passing the response directly to .models is deprecated and converting it first with .parseModels is preferred.


    var Issue = can.Model.extend({
      findAll: 'GET Issues',
      findOne: 'GET Issues/{id}',

      findRelated: function(issue) {
        return can.ajax({
          type: 'GET',
          url: 'Issue/'+issue.id+'/Related'
        }).then(function(response) {
          return this.models(this.parseModels(response));
        }.bind(this));
      }

    },{
      findRelated: function() {
        return this.constructor.findRelated(this);
      }
    });

    // usage examples
    // 1. Issue.findRelated({id: 1});
    // 2. new Issue({id: 1}).findRelated();

jsfiddle