loadRelations (relations, opts) {
    let op
    const mapper = this._mapper()

    // Default values for arguments
    relations || (relations = [])
    if (utils.isString(relations)) {
      relations = [relations]
    }
    opts || (opts = {})
    opts.with = relations

    // Fill in "opts" with the Model's configuration
    utils._(opts, mapper)
    opts.adapter = mapper.getAdapterName(opts)

    // beforeLoadRelations lifecycle hook
    op = opts.op = 'beforeLoadRelations'
    return utils.resolve(this[op](relations, opts)).then(() => {
      // Now delegate to the adapter
      op = opts.op = 'loadRelations'
      mapper.dbg(op, this, relations, opts)
      const tasks = []
      let task
      utils.forEachRelation(mapper, opts, (def, optsCopy) => {
        const relatedMapper = def.getRelation()
        optsCopy.raw = false
        if (utils.isFunction(def.load)) {
          task = def.load(mapper, def, this, opts)
        } else if (def.type === 'hasMany' || def.type === 'hasOne') {
          if (def.foreignKey) {
            task = superMethod(relatedMapper, 'findAll')({
              [def.foreignKey]: utils.get(this, mapper.idAttribute)
            }, optsCopy).then(function (relatedData) {
              if (def.type === 'hasOne') {
                return relatedData.length ? relatedData[0] : undefined
              }
              return relatedData
            })
          } else if (def.localKeys) {
            task = superMethod(relatedMapper, 'findAll')({
              where: {
                [relatedMapper.idAttribute]: {
                  in: utils.get(this, def.localKeys)
                }
              }
            })
          } else if (def.foreignKeys) {
            task = superMethod(relatedMapper, 'findAll')({
              where: {
                [def.foreignKeys]: {
                  contains: utils.get(this, mapper.idAttribute)
                }
              }
            }, opts)
          }
        } else if (def.type === 'belongsTo') {
          const key = utils.get(this, def.foreignKey)
          if (utils.isSorN(key)) {
            task = superMethod(relatedMapper, 'find')(key, optsCopy)
          }
        }
        if (task) {
          task = task.then((relatedData) => {
            def.setLocalField(this, relatedData)
          })
          tasks.push(task)
        }
      })
      return Promise.all(tasks)
    }).then(() => {
      // afterLoadRelations lifecycle hook
      op = opts.op = 'afterLoadRelations'
      return utils.resolve(this[op](relations, opts)).then(() => this)
    })
  }
Lazy load relations of this record, to be attached to the record once their
loaded.

@example
import { Container } from 'js-data';
import { RethinkDBAdapter } from 'js-data-rethinkdb';

const store = new Container();
store.registerAdapter('rethink', new RethinkDBAdapter(), { default: true });
store.defineMapper('user', {
  relations: {
    hasMany: {
      post: {
        localField: 'posts',
        foreignKey: 'user_id'
      }
    }
  }
});
store.defineMapper('post', {
  relations: {
    belongsTo: {
      user: {
        localField: 'user',
        foreignKey: 'user_id'
      }
    }
  }
});
store.find('user', 1234).then((user) => {
  console.log(user.id); // 1234

  // Load the user's post relations
  return user.loadRelations(['post']);
}).then((user) => {
  console.log(user.posts); // [{...}, {...}, ...]
});

@method Record#loadRelations
@param {string[]} [relations] List of relations to load. Can use localField
names or Mapper names to pick relations.
@param {object} [opts] Configuration options.
@returns {Promise} Resolves with the record, with the loaded relations now
attached.
@since 3.0.0