LearnBoost/mongoose — Issue #576: Separate accessor for referenced object from foreign key accessor
Author: lackac
Created: 2011-10-24 15:55:14+00:00
State: open

I like the new `populate` functionality. It makes our code so much more readable. Our schema doesn't map well to how it works though.

Consider this schema:

``` javascript
var BrandSchema = new Schema({ name: String });
var ProductSchema = new Schema({
brand_id: { type: Schema.ObjectId, ref: 'Brand' }
, name: String
, description: String
});
```

Now if I use populate with this schema, it starts to look really weird:

``` javascript
Product.findOne().populate('brand_id').run(function(err, product) {

console.log(product.brand_id); // <-- this is now a brand object

var brand = new Brand({_id: 'levis', name: "Levi's"});
product.brand_id = brand; // <-- I'm assigning a brand object to the brand_id property

console.log(product.brand_id); // <-- this is now a brand id

product.save(function() {});
});
```

I've created a monkey patch to resolve this situation. It restores populated references to their 'id state' and creates an accessor for the populated object. It only supports references which end in `_id` (e.g. `brand_id`).

I would be happy to integrate this into core or create a plugin for it. Whichever is more appropriate.

### Some limitations of [my current approach](https://gist.github.com/1309345):

* it only supports references the names of which end in `_id`
* it's not clear how this should handle collections
* probably doesn't handle many cases

### Further ideas for a more complete implementation:

* ref accessors could be declared in the schema definition with something like this: `brand: { refProp: 'brand_id' }`
* if the query wasn't run with `populate` the accessor could do an implicit fetch on first get and return a promise for the object
* alternatively it could return `null` and a separate `fetch` method would be available for populating references on an initialized object