Skip to content

Instantly share code, notes, and snippets.

@mullr
Created February 17, 2012 15:36
Show Gist options
  • Save mullr/1854059 to your computer and use it in GitHub Desktop.
Save mullr/1854059 to your computer and use it in GitHub Desktop.
jinja.coffee: a minuscule DI container for javascript/coffeescript
# jinja.coffee: a minuscule DI container for javascript/coffeescript
#
# Put your class dependencies under meta.needs and needs_modules, and
# you'll get a hash of whan you asked for as a constructor parameter. A
# useful idiom is to stash the whole thing in a property named 'd',
# for dependencies.
#
# class A
# @meta:
# needs: ["someParam"]
# needsModules: ["request", "fs"]
#
# constructor: (@d) ->
#
# doSomething: ->
# @d.fs.readFile ...
#
# c = new jinja.Container
# c.register "someParam", "foo"
# c.register "a", A
#
# a = c.resolve "a"
module.exports.Container = class Container
registry = {}
register: (key, impl) ->
registry[key] = impl
registerModule: (key, module) ->
registry[key] = require(module)
resolve: (key) ->
throw "nothing registered for key: #{key}" unless registry.hasOwnProperty(key)
impl = registry[key]
# any objects or strings or numbers just get returned
return impl unless typeof(impl) is 'function'
# With a function, see if we have an metadata about it
args = {}
if impl.meta?.needs?
args[k] = @resolve(k) for k in impl.meta.needs
if impl.meta?.needsModules?
args[k] = require(k) for k in impl.meta.needsModules
return new impl(args)
jinja = require("./jinja.coffee")
class A
@meta: { needs: ["param"] }
constructor: (@d) ->
getParam: -> @d.param
class B
@meta: { needs: ["param", "a"] }
constructor: (@d) ->
getParam: -> @d.param
getA: -> @d.a
class NeedsModule
@meta: { needsModules: ["http"] }
constructor: (@d) ->
getHttp: -> @d.http
describe "jinja:", ->
describe "Container:", ->
c = new jinja.Container()
it "can register value types", ->
c.register("param", "foo")
c.register("a", A)
a = c.resolve("a")
expect(a.getParam()).toBe("foo")
it "can register class", ->
c.register "param", "foo"
c.register "a", A
c.register "b", B
b = c.resolve("b")
expect(b.getA()).not.toBeNull()
expect(b.getA().getParam()).toBe("foo")
expect(b.getParam()).toBe("foo")
it "can provide module references", ->
c.register "nm", NeedsModule
nm = c.resolve "nm"
expect(nm.getHttp()).toBeDefined()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment