Skip to content

Instantly share code, notes, and snippets.

@parris
Created April 28, 2014 09:52
Show Gist options
  • Save parris/11367257 to your computer and use it in GitHub Desktop.
Save parris/11367257 to your computer and use it in GitHub Desktop.
(We now have a repo/npm package: https://github.com/parris/mixablejs) Mixin class for coffeescript. Based on Angus Croll style mixins and backbone.advice.
_ = require('lodash')
class Mixable
constructor: ->
@initialize()
initialize: ->
@addToObj: (objectName, dictionary) ->
if _.isUndefined(@prototype[objectName])
@prototype[objectName] = {}
if _.isObject(@prototype[objectName])
@prototype[objectName] = _.extend dictionary, @prototype[objectName]
@after: (target, after) ->
previous = @prototype[target] or ->
@prototype[target] = ->
previous.apply @, arguments
after.apply @, arguments
@around: (target, wrapper) ->
@prototype[target] = _.wrap @prototype[target], wrapper
@before: (target, before) ->
previous = @prototype[target] or ->
@prototype[target] = ->
before.apply @, arguments
previous.apply @, arguments
@clobber: (name, thing) ->
@before 'initialize', ->
@[name] = thing
@hasMixin: (mixin) ->
_.indexOf @constructor.mixins, mixin
hasMixin: (mixin) ->
_.indexOf @mixins, mixin
@mixin: (mixin, options) ->
@mixins = @mixins or []
mixin.call @, options
module.exports = Mixable
_ = require('lodash')
Mixable = require('./mixable.coffee')
newName = 'Parris'
order = []
objectCounterMixin = ->
@numberAfterCreated = 0
@numberBeforeCreated = 0
@after 'initialize', ->
order.push 2
@constructor.numberAfterCreated += 1
@before 'initialize', ->
order.push 0
@constructor.numberBeforeCreated += 1
@around 'add', (fn, x, y) ->
fn(x, y) + 1
moreMixin = ->
@clobber 'name', newName
@addToObj 'events', {
'click .js-hi': 'moreMixin'
'click .js-hi2': 'moreMixin'
}
@addToObj 'ninjas', {}
describe 'Mixable', ->
beforeEach ->
order = []
class @Mixed extends Mixable
name: 'Default'
events:
'click .js-hi': 'default'
'click .js-hi3': 'default'
initialize: ->
super
order.push 1
add: (x, y)->
1 + x + y
@Mixed.mixin objectCounterMixin
@Mixed.mixin moreMixin, {}
describe 'before creation', ->
it 'can add mixins', ->
expect(@Mixed.numberAfterCreated).toBe 0
it 'detects if a mixin is mixed', ->
expect(@Mixed.hasMixin objectCounterMixin).toBeTruthy
describe 'after creation', ->
beforeEach ->
@mixInstance1 = new @Mixed
@mixInstance2 = new @Mixed
describe 'hasMixin', ->
it 'detects if a mixin is mixed', ->
expect(@mixInstance1.hasMixin moreMixin).toBeTruthy
describe 'clobber', ->
it 'allows clobbering of instance variables', ->
expect(@mixInstance1.name).toEqual newName
describe 'before and after', ->
it 'allows for running method after another method', ->
expect(@Mixed.numberAfterCreated).toEqual 2
it 'allows for running method before another method', ->
expect(@Mixed.numberAfterCreated).toEqual 2
it 'calls before and after for initialize in the correct order', ->
expect(order[0]).toEqual 0
expect(order[1]).toEqual 1
expect(order[2]).toEqual 2
describe 'addToObj', ->
it 'does not clobber', ->
expect(@mixInstance1.events['click .js-hi']).toEqual('default')
expect(@mixInstance1.events['click .js-hi3']).toEqual('default')
it 'adds keys to an object', ->
expect(@mixInstance1.events['click .js-hi2']).toEqual('moreMixin')
it 'creates an object if it does not exist', ->
expect(@mixInstance1.ninjas).toBeTruthy()
describe 'around', ->
it 'returns the result of the first function to the second', ->
expect(@mixInstance1.add(1, 1)).toEqual 4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment