ember and containers
DESCRIPTION
Please refer to this talk: http://www.slideshare.net/mixonic/containers-di Much more up to date, and discussing detailed use-cases.TRANSCRIPT
![Page 1: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/1.jpg)
Let’s talk about containers.
Matthew Beale -- @mixonic -- madhatted.com
I build Ember apps for spiffy clients in NYC
Friday, July 12, 13
![Page 2: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/2.jpg)
Friday, July 12, 13
![Page 3: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/3.jpg)
Y’all got issues.
Friday, July 12, 13
![Page 4: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/4.jpg)
Convention over configuration.Global namespace! So easy!
new App[controllerName+‘Controller’]()
Friday, July 12, 13
![Page 5: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/5.jpg)
• Namespaces are !ood. Less !lobals, less conflicts.
• Files map to modules. Could be useful!
• Mana!e dependencies in JS. Better/simpler build pipeline and re-usability.
Oh, maybe we should use modules….
Modules for JS
Friday, July 12, 13
![Page 6: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/6.jpg)
THEY’RE COMING
ES6 MODULESFriday, July 12, 13
![Page 7: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/7.jpg)
Memory management.Who cares!
Friday, July 12, 13
![Page 8: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/8.jpg)
Friday, July 12, 13
![Page 9: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/9.jpg)
• When do you declare an object un-used?
• What about nested collections of objects?
• How do you reset sin!letons durin! tests?
Oh, maybe we should use an Inversion of Control Container….
Herding objects is hard.
Friday, July 12, 13
![Page 10: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/10.jpg)
Dependencies between objectsGlobal namespace! So easy!
App.fooController = Ember.Controller.create({
Friday, July 12, 13
![Page 11: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/11.jpg)
• Namespaces are !ood. Less !lobals, less conflicts. App.everythin!IsNotASolution
• Often, it will be useful to attach a dependency based on type.
• Knowin! and possibly stubbin! dependencies in tests would be nice.
Oh, maybe we should use Dependency Injection….
Dependencies between objects
Friday, July 12, 13
![Page 12: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/12.jpg)
Friday, July 12, 13
![Page 13: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/13.jpg)
352 PAGESFriday, July 12, 13
![Page 14: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/14.jpg)
• Factories receive instance variables.
• Resolvers find factories.
• Containers mana!e injections.
Three Components
Friday, July 12, 13
![Page 15: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/15.jpg)
1 var Factory = Ember.Object.extend(); 2 3 // Receives instance variables as a new instance. 4 Factory.create(injections); 5 6 // Can receive injections for future instances. 7 Factory.extend(injections); 8 9 10 // Today in Ember, injections are only sent to instances.11 // Don't worry yourself about this too much, it may change.
Ember Factories
Friday, July 12, 13
![Page 16: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/16.jpg)
Ember Resolvers
1 Ember.DefaultResolver = Ember.Object.extend({ 2 namespace: null, 3 4 resolve: function(fullName) { 5 var parsedName = this.parseName(fullName); 6 7 // Some magic for specific types, but usually getting to: 8 return this.resolveOther(parsedName); 9 },10 11 resolveOther: function(parsedName) {12 var className = classify(parsedName.name) + classify(parsedName.type),13 factory = get(parsedName.root, className);14 if (factory) { return factory; }15 }16 })
Resolves fullNames like controller:application
Must provide `resolve`
Friday, July 12, 13
![Page 17: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/17.jpg)
Ember Containers
1 var container = new Ember.Container(); 2 3 container.register('worker:uploader', MyUploader); 4 container.injection('controller', 'uploader', 'worker:uploader'); 5 6 container.resolve('worker:uploader'); //=> MyUploader 7 container.lookup('worker:uploader'); //=> instance of MyUploader 8 9 container.lookup('controller:application').get('uploader');10 //=> same instance of MyUploader11 12 container.reset();
Friday, July 12, 13
![Page 18: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/18.jpg)
Friday, July 12, 13
![Page 19: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/19.jpg)
In your own app
Thus, `worker` is available on FilePickerController instances
1 var App = Ember.Application.create();2 3 App.register('worker:uploader', MyUploader);4 App.inject('controller:filePicker', 'worker', 'worker:uploader');5 6 // Ah, so simple.
Friday, July 12, 13
![Page 20: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/20.jpg)
In Ember Data
1 Ember.onLoad('Ember.Application', function(Application) { 2 Application.initializer({ 3 name: "store", 4 5 initialize: function(container, application) { 6 application.register('store:main', application.Store); 7 8 // Eagerly generate the store so defaultStore is populated. 9 // TODO: Do this in a finisher hook10 container.lookup('store:main');11 }12 });13 14 Application.initializer({15 name: "injectStore",16 17 initialize: function(container, application) {18 application.inject('controller', 'store', 'store:main');19 application.inject('route', 'store', 'store:main');20 }21 });22 });
Thus, `store` is available on controllers and routes
Friday, July 12, 13
![Page 21: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/21.jpg)
In your tests
1 Ember.Container.prototype.stub = function(fullName, instance) { 2 instance.destroy = instance.destroy || function() {}; 3 this.cache.dict[fullName] = instance; 4 }; 5 6 var container; 7 8 module('UserController saves', { 9 setup: function(){ container = App.__container__ }10 });11 12 test('is saves', function(){13 expect(1);14 container.stub('main:store', function(){15 this.save = function(){ ok(true) };16 });17 controller = container.lookup('controller:user');18 controller.send('submit');19 });
Friday, July 12, 13
![Page 22: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/22.jpg)
THEY’RE COMING
ES6 MODULESFriday, July 12, 13
![Page 23: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/23.jpg)
THEY’RE HERE
ES6 MODULES
EMBER APP KIT
Friday, July 12, 13
![Page 24: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/24.jpg)
In your own app
Thus, `worker` is available on FilePickerController instances
1 var App = Ember.Application.create();2 3 App.register('worker:uploader', MyUploader);4 App.inject('controller:filePicker', 'worker', 'worker:uploader');5 6 // Ah, so simple.
GLOBAL
Flashback to…
Friday, July 12, 13
![Page 25: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/25.jpg)
• Namespaces are !ood. Less !lobals, less conflicts.
• Files map to modules. Could be useful!
• Mana!e dependencies in JS. Better/simpler build pipeline and re-usability.
Oh, maybe we should use modules….
Modules for JS
Flashback to…
Friday, July 12, 13
![Page 26: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/26.jpg)
https://github.com/stefanpenner/ember-app-kit
Grunt pipeline, es6-module-transpiler
Friday, July 12, 13
![Page 27: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/27.jpg)
1 module "appkit/app" { 2 var App = Ember.Application.create(); 3 export default App; 4 // <script type="text/javascript">import App from “appkit/app”;</script> 5 } 6 7 module "appkit/templates/application" { 8 var template = Ember.Handlebars.compile("Howdy Washington!"); 9 export default template;10 }
Real scopes. No globals.
Files become ES6 modules
Friday, July 12, 13
![Page 28: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/28.jpg)
Friday, July 12, 13
![Page 29: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/29.jpg)
Ember Resolvers
1 Ember.DefaultResolver = Ember.Object.extend({ 2 namespace: null, 3 4 resolve: function(fullName) { 5 var parsedName = this.parseName(fullName); 6 7 // Some magic for specific types, but usually getting to: 8 return this.resolveOther(parsedName); 9 },10 11 resolveOther: function(parsedName) {12 var className = classify(parsedName.name) + classify(parsedName.type),13 factory = get(parsedName.root, className);14 if (factory) { return factory; }15 }16 })
Resolves fullNames like controller:application
Must provide `resolve`
Flashback to...
IMPLIES APP.SOMETHING
Friday, July 12, 13
![Page 30: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/30.jpg)
1 module "appkit/app" { 2 var App = Ember.Application.create(); 3 4 import applicationTemplate from "appkit/templates/application"; 5 Em.TEMPLATES['application'] = applicationTemplate; 6 7 export default App; 8 // <script type="text/javascript">import App from “appkit/app”;</script> 9 }10 11 module "appkit/templates/application" {12 var template = Ember.Handlebars.compile("Howdy Washington!");13 export default template;14 }
Quick fix...
But do that for everything? No way.
Friday, July 12, 13
![Page 31: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/31.jpg)
• Factories receive instance variables.
• Resolvers find factories.
• Containers mana!e injections.
Three Components
Flashback to…
OH HAI
Friday, July 12, 13
![Page 32: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/32.jpg)
80 function resolveOther(parsedName) { 81 var prefix = this.namespace.modulePrefix; 82 Ember.assert('module prefix must be defined', prefix); 83 84 var pluralizedType = typeMap[parsedName.type] || parsedName.type; 85 var name = parsedName.fullNameWithoutType; 86 87 var moduleName = prefix + '/' + pluralizedType + '/' + underscore(name); 88 var module; 89 90 if (define.registry[moduleName]) { 91 module = requireModule(moduleName); 92 93 if (typeof module.create !== 'function') { 94 module = classFactory(module); 95 } 96 97 if (Ember.ENV.LOG_MODULE_RESOLVER){ 98 Ember.logger.info('hit', moduleName); 99 }100 101 return module;102 } else {103 if (Ember.ENV.LOG_MODULE_RESOLVER){104 Ember.logger.info('miss', moduleName);105 }106 107 return this._super(parsedName);108 }109 }
/vendor/loader.js
Friday, July 12, 13
![Page 33: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/33.jpg)
1 module "appkit/app" { 2 var App = Ember.Application.create(); 3 export default App; 4 // <script type="text/javascript">import App from “appkit/app”;</script> 5 } 6 7 module "appkit/templates/application" { 8 var template = Ember.Handlebars.compile("Howdy Washington!"); 9 export default template;10 }
Ember & ES6 modules, no hacks
Friday, July 12, 13
![Page 34: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/34.jpg)
• Views
• Controllers
• Templates
• Routes
Today, works with...
Yay, good-guy classes are fetched via containers
Friday, July 12, 13
![Page 35: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/35.jpg)
• Some Views
• Models
• Helpers
Today, busted with...
Boo, Scumbag classes are not referenced via the container
Friday, July 12, 13
![Page 36: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/36.jpg)
• Subcontainers. Flush only part of the app.
• Sin!leton controllers live forever. Problem? Feature?
• Ember.Container could become a micro-lib. Uses no Ember internally.
The future
Friday, July 12, 13
![Page 37: Ember and containers](https://reader034.vdocuments.net/reader034/viewer/2022052410/555194ccb4c905013a8b4713/html5/thumbnails/37.jpg)
Questions? Ideas?
Matthew Beale - @mixonic - madhatted.com
Friday, July 12, 13