0

I have been playing with the TypeScript MVC framework TypeFramework and am trying to figure out how to create relationships between models. I know it uses the Waterline ORM. An example of a Waterline model with a relationship is:

// A user may have many pet
var User = Waterline.Collection.extend({
  attributes: {
    firstName: 'string',
    lastName: 'string',

    // Add a reference to Pets
    pets: {
      collection: 'pet',
      via: 'owner'
    }
  }
});

// A pet may only belong to a single user
var Pet = Waterline.Collection.extend({
  attributes: {
    breed: 'string',
    type: 'string',
    name: 'string',

    // Add a reference to User
    owner: {
      model: 'user'
    }
  }
});

An example of a TypeFramework model looks like:

class User extends TF.Model{
    firstName: string,
    lastName: string
}

The code for TF.Model is:

class Model {
    public id: number;
    public createdAt: Date;
    public updatedAt: Date;
    static collectionName: string;
    static schema: boolean;
    static adapter: string;
    static attributes: any;
    private static collection;
    public save: <T>(callback: ISingleResultCallback<T>) => void;
    public destroy: <T>(callback: INoResultCallback<T>) => void;
    static save<T>(model: T, callback: ISingleResultCallback<T>): void;
    static destroy<T>(model: T, callback: INoResultCallback<T>): void;
    static all<T>(): DbQueryEnd<T>;
    static where(query: {}): WL.IQuery;
    static get(id: number): DbQueryUnique<any>;
    static first<T>(query: {}): DbQueryUnique<T>;
    static find<T>(): DbQuery<T>;
    static query<T>(query: string): DbQueryRaw<T>;
    static validate(attr: string, options: ModelValidation): any;
    static validate(attrs: string[], definition: ModelValidation): any;
    private static extend(from, to);
}

I'm not sure how to integrate a relationship into a strongly-typed TypeFramework model. Any suggestions or help would be greatly appreciated.

BSmith
  • 123
  • 8

1 Answers1

1

So, let me preface this without knowing all the inner workings of either framework. However, I think I know how to get what you want here.

First, if you are OK with having your models be in Typescript, and your waterline code be in Javascript, that will make this much easier.

However, if you want to use Waterline in Typescript, you will likely need to create .d.ts files. I currently do not see anything available on DefinitelyTyped for it, unfortunately. It's not particularly easy, but with some willpower you could probably get the concept enough to make it work. The official guide is pretty good.

That said, on to code!

You will need to instantiate your class with everything you need in it. If you don't put in content into your class properties, you have a good chance of missing them. You need to call the constructor on your base object with super(); as well.

class User extends Model
{
    firstName: string;
    lastName: string;
    pets: IPet[];

    constructor(firstname: string, lastname: string, pets: IPet[])
    {
        super();
        this.firstName = firstname;
        this.lastName = lastname;
        this.pets = pets;
    }
}

interface IPet
{
    breed: string;
    petType: string;
    name: string;
}

You may want to make Pet and actual class, but for the moment, we'll assume it isn't.

So then, all you should have to do to create a Waterline User the way you have described above would be like this:

var User = Waterline.Collection.extend(
    new User("Jim", "Bob", [{"breed": "tabby", "petType": "small", "name": "Mittens"}])
);

You may have a static method that could get a "prebuilt" kind of user, or fetch one out by an ID.

static GetJimAndPets() : User
{
    return new User("Jim", "Bob", [{"breed": "tabby", "petType": "small", "name": "Mittens"}])
}

static GetUserById(id: number) : User
{
    //Logic here
    return null;
}

Then you could call your method even easier:

var User = Waterline.Collection.extend(User.GetJimAndPets());

That should work, but as I mentioned before, I don't know how to test it and YMMV.

Zachary Dow
  • 1,897
  • 21
  • 36
  • That was my first thought, but was hoping I wouldn't have to resort to that. It looks like there may be a way to do create these relationships based on the "collections" referenced in the code, but I'm not sure how to use them. – BSmith Aug 19 '15 at 12:23