GeppettoJS / backbone.geppetto

Bring your Backbone applications to life with an event-driven Command framework.
http://geppettojs.github.com/backbone.geppetto/
MIT License
203 stars 28 forks source link

Passing configuration to lazily instantiated objects #58

Closed creynders closed 10 years ago

creynders commented 10 years ago

I've found need for being able to pass a configuration object to instances that are created by the resolver.

E.g.:

this.context.wireValue( 'account.api.url', this.config.api.root + '/me/account' );
this.context.wireSingleton( 'accountModel', UserModel, {
    url : 'account.api.url'
} );

Here I want the UserModel instance to be injected with a specific url upon instantiation. The above is obviously a solution, but a bit cumbersome. For instance if there are any other config options I'd like to pass, I'll need to wire them as values as well. In this case I use the optional wiring parameter all wire* methods have, but TBH I think this has very little use cases and am starting to think it would be better to turn it into an optional options parameter. So we could do this:

this.context.wireSingleton( 'accountModel', UserModel, {
    url : this.config.api.root + '/me/account' 
} );

Obviously this would be a breaking change. If you don't like this approach how about a separate method, something like:

this.context.wireSingleton( 'accountModel', UserModel);
this.context.configure('accountModel', {
    url : this.config.api.root + '/me/account' 
} );
geekdave commented 10 years ago

Obviously this would be a breaking change

Yeah, I can think of at least one enterprise app that would break as a result of this change.

how about a separate method

I think I like the configure approach. So if I understand correctly, the original API (passing an optional wiring object) would require that each value in that object is, itself, a named dependency. While the configure approach would permit each value in the object to be the actual value to be injected?

creynders commented 10 years ago

So if I understand correctly, the original API (passing an optional wiring object) would require that each value in that object is, itself, a named dependency. While the configure approach would permit each value in the object to be the actual value to be injected?

Yes indeed. The more I think about configure the more I like it, it has some real potential, especially if it accepts functions that return configuration objects as well.

(Caveat: configure cannot be called on view wirings, for obvious reasons.)

I'm thinking of the following

Parameter type

object

.configure('myModel', {
  foo:"bar"
}); 

The object is passed to the constructor function of MyModel.

function

.configure('myModel', function(context){
  return {
    foo: "bar"
  }
});

The result of the function call is passed to the constructor function of MyModel.

Array

If configure receives an array, either directly or as a result of calling a function, each element will be passed as an argument to the constructor function, i.e.

//MyModel
function MyModel( foo, baz ){
}

//config
.configure( 'myModel', ['bar','qux'] );

Results in foo having the value 'bar' and baz 'qux'

creynders commented 10 years ago

Some remarks:

geekdave commented 10 years ago

Sounds great - Let's do it!