Sproutcore RC.Record primary keys, guids and ids

Every Sproutcore record needs a primary key.

By default, the primary key is named guid.

TableSample.User = SC.Record.extend(
/** @scope TableSample.User.prototype */ {
  firstName: SC.Record.attr(String),
  lastName: SC.Record.attr(String)
}) ;

TableSample.User.FIXTURES = [
   { guid: 1,
     firstName: "Michael",
     lastName: "Scott" },

   { guid: 2,
     firstName: "Dwight",
     lastName: "Schrute" },

   { guid: 3,
     firstName: "Jim",
     lastName: "Halpert" },
];

You can change the name of your primary key by using the primaryKey attribute. For example, below we’ve changed the name of our primary key to userID.

TableSample.User = SC.Record.extend(
/** @scope TableSample.User.prototype */ {
  primaryKey: 'userID',
  userID: SC.Record.attr(Number),
  firstName: SC.Record.attr(String),
  lastName: SC.Record.attr(String)
}) ;

TableSample.User.FIXTURES = [
   { userID: 1,
     firstName: "Michael",
     lastName: "Scott" },

   { userID: 2,
     firstName: "Dwight",
     lastName: "Schrute" },

   { userID: 3,
     firstName: "Jim",
     lastName: "Halpert" },
];

Here’s the catch. If you need to retrieve the value of your primaryKey, always retrieve it using the id attribute no matter if you are using the default ‘guid’ primary key property name or not.

  var userRecord = TableSample.store.find(TableSample.User, 1);

  // Correct way of getting the primary key
  var pk = userRecord.get('id');

  // This is incorrect
  var wrongWayToGetPrimaryKey = userRecord.get('userID');

Getting the value of the primary key using the primary key attribute will only work for existing records retrieved from a data source or instanced in a fixture.

I found that it does NOT work for records created in sproutcore and then pushed for saving on your server (i.e. new records that a user may have added).

This is because sproutcore keeps the primary key in an array called SC.Store.idsByStoreKey. When the primary key is updated after a SC.Store.commitRecords(), the array is updated but the primary key property of the record is not.

    var userRecord = { userID: null,
     firstName: "Sponge",
     lastName: "Bob"
    };

    store.createRecord(TableSample.User, userRecord) ;
    store.commitRecords();

    // Correct way of getting the primary key.
    // pk will equals the newly allocated primary key.
    // If you are using fixtures data source, it will be something like "@id4".
    var pk = userRecord.get('id');

    // This is incorrect
    // wrongWayToGetPrimaryKey will be null.
    // It is unchanged from the userRecord declaration.
    var wrongWayToGetPrimaryKey = userRecord.get('userID');

In the above example, userID is left unchanged as null. I think this is because doing so would change the record status from READ_CLEAN to READ_DIRTY which is not what we want after a commitRecords().

So, the lesson for newbies, always read your record’s primary key using the id attribute. Also, never change your primary key except after saving a newly created record in your data source.

Leave a comment

1 Comments.

Leave a Reply


[ Ctrl + Enter ]

Trackbacks and Pingbacks: