advice.js
function(mixins, options) {
        // used to saved applied mixins
        this.mixedIn = _.clone(this.mixedIn) || [];
        if (!this.__super__
            || this.mixedOptions == this.__super__.constructor.mixedOptions) {
            this.mixedOptions = _.clone(this.mixedOptions) || {};
        }
        _.extend(this.mixedOptions, options);
        // if only one passed in make it an array
        if (!_.isArray(mixins))
            mixins = [mixins];

        // if an array then run each mixin and save to mixedIn array
        mixins = _(mixins).map(function(mixin) {
            if(!Boolean(mixin)) console.error('Missing mixin at ', this.prototype.className, this.prototype);
            if (!_.isFunction(mixin)) return mixin;
            if (!_.contains(this.mixedIn, mixin)) {
                this.mixedIn.push(mixin);
                if(mixin) return mixin.call(this, this.mixedOptions);
            }
        }, this);

        // if we have an object (can be returned by functions) - use them
        _(mixins).each(function(mixin) {

            if (!mixin) return;

            mixin = _.clone(mixin);

            // call the reserved keywords
            _([
                'mixin',
                'around',
                'after',
                'before',
                'clobber',
                'addToObj',
                'setDefaults'
            ]).each(function(key) {
                if (mixin[key]) {
                    if (key == 'mixin')
                        this[key](mixin[key], this.mixedOptions);
                    else
                        this[key](mixin[key]);
                    delete mixin[key];
                }
            }, this);

            // on the remaining keywords, guess how to add them in
            _.each(_.keys(mixin), function(key) {

                // if it's a function then put it after
                if (_.isFunction(mixin[key])) {
                    this.after(key, mixin[key]);

                    // if it's an object then add it to any existing one
                } else if (_.isObject(mixin[key]) && !_.isArray(mixin[key])) {
                    var obj = {};
                    obj[key] = mixin[key];
                    this.addToObj(obj);

                    //else change the value
                } else {
                    this.clobber(key, mixin[key]);
                }
            }, this);
        }, this);

        // chaining
        return this;
    }
function(mixins, options) {
        // used to saved applied mixins
        this.mixedIn = _.clone(this.mixedIn) || [];
        if (!this.__super__
            || this.mixedOptions == this.__super__.constructor.mixedOptions) {
            this.mixedOptions = _.clone(this.mixedOptions) || {};
        }
        _.extend(this.mixedOptions, options);
        // if only one passed in make it an array
        if (!_.isArray(mixins))
            mixins = [mixins];

        // if an array then run each mixin and save to mixedIn array
        mixins = _(mixins).map(function(mixin) {
            if(!Boolean(mixin)) console.error('Missing mixin at ', this.prototype.className, this.prototype);
            if (!_.isFunction(mixin)) return mixin;
            if (!_.contains(this.mixedIn, mixin)) {
                this.mixedIn.push(mixin);
                if(mixin) return mixin.call(this, this.mixedOptions);
            }
        }, this);

        // if we have an object (can be returned by functions) - use them
        _(mixins).each(function(mixin) {

            if (!mixin) return;

            mixin = _.clone(mixin);

            // call the reserved keywords
            _([
                'mixin',
                'around',
                'after',
                'before',
                'clobber',
                'addToObj',
                'setDefaults'
            ]).each(function(key) {
                if (mixin[key]) {
                    if (key == 'mixin')
                        this[key](mixin[key], this.mixedOptions);
                    else
                        this[key](mixin[key]);
                    delete mixin[key];
                }
            }, this);

            // on the remaining keywords, guess how to add them in
            _.each(_.keys(mixin), function(key) {

                // if it's a function then put it after
                if (_.isFunction(mixin[key])) {
                    this.after(key, mixin[key]);

                    // if it's an object then add it to any existing one
                } else if (_.isObject(mixin[key]) && !_.isArray(mixin[key])) {
                    var obj = {};
                    obj[key] = mixin[key];
                    this.addToObj(obj);

                    //else change the value
                } else {
                    this.clobber(key, mixin[key]);
                }
            }, this);
        }, this);

        // chaining
        return this;
    }
#### mixin
This is the 'mixin' function available
on an object with advice added to it.
Takes a mixin or array of mixins and options
Adds the given mixins to the to
on the target object.
@param mixins {function|array} Mixins to be added
@param options {object} (Optional) Options to the mixins
@returns {function}