Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rebuilding in Ember

Rebuilding in Ember

My Toronto Ember.js Meetup talk on my work to date in iteratively rebuilding Jugnoo's social media dashboard as an Ember app.

Joshua Gorner

May 01, 2014
Tweet

Other Decks in Programming

Transcript

  1. Outline • Background – project and rebuild • Problems 1.

    Disjoint views (not a SPA) 2. Rewriting modals 3. Shared classes • Other challenges and future steps
  2. What is Jugnoo? • We make a solution for social

    media presence management • SoMeAnalyzer used to track, visualize, and analyze social media data across major social networks • I mainly work on the dashboard and social feeds
  3. Pre-Ember • Ruby on Rails backend + custom object-oriented JavaScript

    frontend • AJAX responses: Combination of ERb rendering, JSON, and plaintext responses • Code becoming increasingly messy, repetitive, difficult to maintain • Ember = most complete solution to help us get code into a more organized state
  4. Reality Sets In • Full rebuild would be ideal, but

    impractical for now • Existing app to maintain • Limited resources • Meanwhile: new backend data collection • Decide to “phase in” Ember as new backend becomes available
  5. Starting off… • Only the feeds themselves (and only some

    of them) initially rebuilt with Ember / Handlebars • Everything surrounding them remains in ERb • Not a standard single-page app • Multiple apps on the same page? – Possible but not realistic
  6. Solution • Single Ember application, but no routes and no

    {{outlet}} • Have to create our feed views manually
  7. jugnoo.JSocialFeedPanel = function(someArgs) {
 // ... generic setup code ...


    if(this.isLegacy){
 // setup with existing custom JS classes
 this.feed = new jugnoo.JSocialFeed(this, ...);
 }
 else {
 // setup with Ember
 var store = JFeeds.__container__.lookup('store:main');
 var panel = this;
 Ember.run(function() {
 var c = JFeeds.SocialFeedController.create();
 var platformFeedId = panel.$div.attr('platform-id');
 
 store.find("socialFeed", platformFeedId).then(function(feed) {
 c.set("content", feed);
 }).catch(function(jqXHR) {
 // some error handling code
 });
 
 panel._emberView = JFeeds.SocialFeedView.create();
 panel._emberView.set('controller', c);
 
 var loc = panel.$div.find('.dashboard-panel-content').empty().first();
 panel._emberView.appendTo(loc);
 
 panel.feed = c;
 });
 }
 } Getting the store:
 a bit sketchy Manually create 
 controller + view
  8. At this point: • Application: Yes • Models, views, controllers,

    templates: Yes • Routes: No • ApplicationRoute / Controller / .hbs: No • <body> still being used as root element • Router: Yes… but doing nothing App.Router.reopen({
 location: 'none'
 });
  9. What’s next? • Can’t (yet) build out the rest of

    the tab in Ember • But there are things outside of that we can replace: modal popups • The Ember tutorial for using modals works for our app just like for a “regular” Ember app • But now need to add ApplicationRoute + application.hbs
  10. # application_route.coffee
 JEmberPlatform.ApplicationRoute = Ember.Route.extend
 actions:
 openModal: (modalName, properties =

    {}) ->
 modalController = @controllerFor(modalName)
 modalController.setProperties properties
 @render modalName,
 into: 'application'
 outlet: 'modal'
 Ember.run.next ->
 modalController.show()
 
 closeModal: ->
 @disconnectOutlet
 outlet: 'modal'
 parentView: 'application'
 
 # application.hbs - yes just one line
 {{outlet modal}}" # some_other_template.hbs
 <button {{action "openModal" "someModal"}}>Click Me!</button>
  11. Caveats re Modals • Legacy code: Using Bootstrap-based modals •

    CSS is fine but JS does not interact well with Ember out of the box • Used Bootstrap for Ember (e.g. {{bs-modal}} components)
  12. Sharing Classes • Our other Ember apps use many of

    same (or similar) models, views, etc. • Needed to extract a portion of our Ember codebase to make available in other projects • ES6 modules weren’t really on our radar at the time • Ember’s solution (of sorts) for this: Ember.Namespace
  13. # CoffeeScript
 window.JEmberPlatform = Ember.Namespace.create
 VERSION: ‘0.1.0'" # define common

    classes, templates, etc. like…" JEmberPlatform.SocialFeed = DS.Model.extend
 # core attributes, properties, etc." JFeeds = Ember.Application.create({…})" JFeeds.SocialFeed = JEmberPlatform.SocialFeed.extend
 # additional attributes, properties, etc.
  14. Namespace ≠ Mixin MyNamespace = Ember.Namespace.create();
 MyNamespace.SomeView = Ember.View.extend({…});" #

    won’t work!
 MyApp = Ember.Application.createWithMixins(MyNamespace);" # so this won’t work out of the box either
 MyApp.SomeView.create();" # we could use the namespace class directly in some cases…
 MyNamespace.SomeView.create();
 # but the app resolver won’t pick them up" # or we could add each and every class to the app’s namespace
 MyApp.SomeView = MyNamespace.SomeView
 # …
 MyApp.SomeView.create();
  15. Our Solution # CoffeeScript
 JEmberPlatform.ApplicationResolver = 
 Ember.DefaultResolver.extend
 resolveModel: (parsedName)

    ->
 unless @_super(parsedName)
 parsedName.root = JEmberPlatform
 @_super(parsedName)
 
 resolveOther: # basically the same
 
 JEmberPlatform.BaseApplication = Ember.Application.extend
 Resolver: JEmberPlatform.ApplicationResolver
 
 # meanwhile, in our main app code…
 JFeeds = JEmberPlatform.BaseApplication.extend({…})
  16. Our Solution • Custom resolver does not directly add namespace

    classes to the app namespace • But: Can use lookup / lookupFactory to access classes via resolver • Don’t have to worry about updating references if we move or extend classes • Still need to get the container – sketchy MyApp.__container__.lookupFactory(“view:someNamespace”).create()
  17. Other Challenges • Communication between legacy and Ember code •

    Legacy codebase: lots of `Ember.run` calls • Ember codebase: references to legacy Dashboard object singleton
  18. Other Challenges • Performance • Interference with existing jQuery (click

    handlers) • Rendering: a bit slower sometimes vs ERb • Occasional issues with re-rendering • Styling / Maintenance • New DOM structure + styling for Ember-based feeds
  19. Where to Go From Here? • Our eventual goal is

    still to convert the entire Dashboard into a “regular” Ember app • Not yet able to process some data sources into a format our Ember app can support, and other parts of backend not yet fully RESTful • After that we can proceed to rewrite panels, tabs etc. in Handlebars and start making full use of router • ES6 modules to replace namespacing?