<commit_before><commit_msg>Even better: a general way to manage relations between two polyclay model classes.<commit_after>var
	_          = require('lodash'),
	assert     = require('assert'),
	levelgraph = require('levelgraph'),
	models     = require('./models'),
	P          = require('p-promise'),
	util       = require('util')
	;

var GraphRelation = module.exports = function GraphRelation(opts)
{
	assert(opts && _.isObject(opts), 'you must pass an options object');
	assert(opts.dbpath || opts.db, 'you must pass either a db option or a dbpath string');
	assert(opts.relation && _.isString(opts.relation, 'you must pass a relation string'));
	assert(opts.subject && _.isFunction(opts.subject, 'you must pass a subject constructor function'));
	assert(opts.object && _.isFunction(opts.object, 'you must pass an object constructor function'));

	this.options  = opts;

	if (opts.dbpath)
		this.db = levelgraph(opts.dbpath);
	else
		this.db = opts.db;

	this.relation = opts.relation;
	this.subject  = opts.subject;
	this.object   = opts.object;
};

GraphRelation.prototype.db       = null;
GraphRelation.prototype.relation = null;
GraphRelation.prototype.subject  = null;
GraphRelation.prototype.object   = null;

GraphRelation.prototype.add = function add(subject, object)
{
	var self = this,
		deferred = P.defer();

	var triple = { subject: subject.key, predicate: this.relation, object: object.key };
	this.db.put(triple, function(err)
	{
		if (err)
			deferred.reject(err);
		else
			deferred.resolve();
	});

	return deferred.promise;
};

GraphRelation.prototype.remove = function add(subject, object)
{
	var self = this,
		deferred = P.defer();

	var triple = { subject: subject.key, predicate: this.relation, object: object.key };
	this.db.del(triple, function(err)
	{
		if (err)
			deferred.reject(err);
		else
			deferred.resolve();
	});

	return deferred.promise;
};

GraphRelation.prototype.relationsFor = function favorites(subject)
{
	var self = this,
		deferred = P.defer();

	this.db.get({ subject: subject.key, predicate: this.relation }, function(err, list)
	{
		if (err)
			return deferred.reject(err);

		var keys = _.map(list, function(i)
		{
			return i.object;
		});

		self.object.get(keys)
		.then(function(posts)
		{
			deferred.resolve(posts);
		})
		.fail(function(err)
		{
			deferred.reject(err);
		}).done();
	});

	return deferred.promise;
};

GraphRelation.prototype.hasAsRelation = function favorites(object)
{
	var self = this,
		deferred = P.defer();

	this.db.get({ object: object.key, predicate: this.relation }, function(err, list)
	{
		if (err)
			return deferred.reject(err);

		var keys = _.map(list, function(i)
		{
			return i.subject;
		});

		self.subject.get(keys)
		.then(function(people)
		{
			deferred.resolve(people);
		})
		.fail(function(err)
		{
			deferred.reject(err);
		}).done();
	});

	return deferred.promise;
};
{'fraction_non_alphanumeric': 0.14767199444058374, 'fraction_numerical': 0.0, 'mean_word_length': 3.8549747048903877, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6737268', 'n_tokens_mistral': 1033, 'n_tokens_neox': 949, 'n_words': 217}