<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Nation Building]]></title><description><![CDATA[Dustin Nation talks about building stuff]]></description><link>http://blog.dustinnation.com/</link><generator>Ghost v0.4.2</generator><lastBuildDate>Fri, 03 Apr 2026 23:04:17 GMT</lastBuildDate><atom:link href="http://blog.dustinnation.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Angular 1 - Custom Compare in $watch]]></title><description><![CDATA[<p>Sometimes you run into a situation where you need to define a custom compare function for $watch to use in Angular 1 change detection.</p>

<p>This was the case for me when I needed to check for changes on a rather deeply nested class.</p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p>Angular 1 uses <code>$scope.$watch</code> to actively check for changes.</p>

<script src='https://gist.github.com/d-nation/ef3068bcd50fab1c5f1c59c51456bd23.js?file=simple_watch.controller.js' ></script>

<p>In my scenario, the built in equality checker had a really hard time with my class. So much so, that it would cause a <code>Max call size exceeded</code> error every time it tried to run <code>$watch</code>.</p>

<p>We already had a function that would compare only the attributes on the class that mattered, but <code>$watch</code> doesn't support custom comparators.</p>

<hr />

<h2 id="thesolution">The Solution</h2>

<p>You'll need to keep a copy of the previous state somewhere. We have a service that has the original copy of the class, so we used that to determine if the local copy changed.</p>

<p>Here's what it looks like:</p>

<script src='https://gist.github.com/d-nation/ef3068bcd50fab1c5f1c59c51456bd23.js?file=custom_compare.controller.js' ></script>

<p><em>Warning - your equals function will run on every digest cycle, so perf matters. Return early!</em></p>

<p>Here, we provide <code>$watch</code> with a function that returns a value. Angular will keep track of that value for you. We are going to take advantage of that and simply return a boolean that changes when our custom compare function says that the object has changed.</p>

<p>After you determine that a change has happened, don't forget to update your previous version</p>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>This is a simple trick that can get you out of a bind, but again, be very mindful of how your build your custom comparator logic.</p>]]></description><link>http://blog.dustinnation.com/angular-1-custom-compare-in-watch/</link><guid isPermaLink="false">3b843209-6bd6-4d8f-a231-a76c81726530</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Fri, 10 Feb 2017 04:14:34 GMT</pubDate></item><item><title><![CDATA[Sharing Broadcast Messages between Angular 1 & 2]]></title><description><![CDATA[<p>I'm in the middle of migrating a project from Angular 1 to Angular 2. Every now and then I hit a bump in the road where architecture/design decisions in the Angular 1 version don't always have a clear path into the best practices of Angular 2.</p>

<p>I ran into one of those instances recently when implementing an HTTP Interceptor.</p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p>The Angular 1 code relied on <code>$rootScope.$broadcast</code> in order to tell other parts of the app when an HTTP call responded with a server error. (<em>This mechanism will be changed once all of its players are migrated to Angular 2</em>)</p>

<p>Unfortunately, there is no built in way to send a broadcast from an Angular 2 service to the Angular 1 <code>$rootScope.$broadcast</code> mechanism.</p>

<hr />

<h2 id="thesolution">The Solution</h2>

<p>At this point, it is either refactor the Angular 1 code to decouple the broadcast handlers from the components they live in (not a bad idea, since it'll have to happen during the migration anyways), or figure out a way to pass broadcasts between the two versions.</p>

<p>I opted for the latter since there are other places in the app that will need broadcasts all the way up until I'm fully migrated.</p>

<p><a href='https://twitter.com/calebwilliams12' >Caleb Williams</a> and I were chewing on this challenge in the breakroom one day and this is the result!</p>

<p>First, we create a service that Angular 1 and 2 can both use to send each other broadcast messages.</p>

<script src='https://gist.github.com/d-nation/4e40d16c877b803c2d669a32fcc95b31.js?file=broadcast-interface.service.ts' ></script>

<p>This service has two public Subjects. One is for broadcasts coming from Angular 2 ( <code>ng2Broadcasts</code> ), and the other is for broadcasts coming from Angular 1 ( <code>ng1Broadcasts</code> ). It also has two convenience functions for updating each Subject.</p>

<p>The intent here is that each version's interested parties can subscribe to the broadcasts coming from the other version.</p>

<p>In my case, I want to just relay all broadcasts coming from Angular 2 straight onto <code>$rootScope.$broadcast</code>.</p>

<p>So we downgrade the <code>BroadcastInterfaceService</code> and do just that.</p>

<script src='https://gist.github.com/d-nation/4e40d16c877b803c2d669a32fcc95b31.js?file=upgrades.ts' ></script>

<script src='https://gist.github.com/d-nation/4e40d16c877b803c2d669a32fcc95b31.js?file=core.run.js' ></script>

<p>Then, in Angular 2 when you need to send a broadcast to Angular 1, you import <code>BroadcastInterfaceService</code> and call <code>.sendToNg1()</code>.</p>

<p>Likewise, in Angular 1 code, we'd inject <code>broadcastInterface</code> and call <code>.sendToNg2()</code>. Unfortunately, there is no way to listen to all Angular 1 <code>$broadcasts</code> and relay them. Any interested party in Angular 2 needs to subscribe to the <code>ng1Broadcasts</code> Subject and listen for a specific message.</p>

<script src='https://gist.github.com/d-nation/4e40d16c877b803c2d669a32fcc95b31.js?file=random.component.ts' ></script>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>Broadcasts aren't really "a thing" in Angular 2 since everything is moving towards RxJs Observables, but during a migration it may not be possible to completely discard them. This is one way to bridge the gap in the interim.</p>]]></description><link>http://blog.dustinnation.com/sharing-broadcast-messages-between-angular-1-2/</link><guid isPermaLink="false">2db9faaa-e508-4c58-b9c0-868f1140bb78</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Wed, 30 Nov 2016 16:27:21 GMT</pubDate></item><item><title><![CDATA[Ditch Your Angular 1.x Watchers! (Follow Up)]]></title><description><![CDATA[<p><em>Note:</em> <br />
<em>This is a follow up to <a href='http://blog.dustinnation.com/ditch-your-angular-1-x-watchers-quick-swap-them-for-observables/' >Ditch Your Angular 1.x Watchers! Quick-Swap Them for Observables</a></em></p>

<p>It's been 2 months since I wrote about swapping <code>$watch</code> for <code>observeOnScope</code>, so I thought I'd post a follow up! In that 2 months we have finally found the time to educate the team on Observables and actually implement these swaps in our production application!</p>

<p>In doing so, we ran across a scenario that I hadn't covered in the "Quick-Swap" article.</p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p><code>$watchGroup</code>.</p>

<p>We had a couple of places where we had the need to detect changes on several objects, then run one function if any of them changed (think auto-sorting across multiple list of different types of objects).</p>

<p>It looks something like this:  </p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope'];  
function Controller1($scope) {  
    $scope.property1 = {};
    $scope.property2 = {};
    $scope.property3 = {};

    $scope.$watchGroup(['property1', 'property2', 'property3'], function(newValue, oldValue) {

        if (newValue &amp;&amp; oldValue) {
            //Do Something        
        }
    }, true);
}
</code></pre>

<p>Since <code>observeOnScope</code> only takes one attribute (or function), we have a problem. </p>

<p>If you don't need to know which value actually changed, you <em>could</em> combine the object properties with a function and pass it into <code>observeOnScope</code>. However, in our case, our "on-change" function requires the most up-to-date data from all of the objects. With this method, we would have had to do change detection on our change detection in order to figure out which one of the objects actually triggered the change.</p>

<p>You also run into this same problem if you try to use <code>Observable.merge</code> which creates a single Observable out of multiple.</p>

<p>You <em>could</em> also break the "on-change" function up and split each object into its own Observable and Subscription. However, in our case, that would result in a lot of repeated code, which we didn't want to do.</p>

<hr />

<h2 id="thesolution">The Solution</h2>

<p>Enter <code>Observable.combineLatest</code>! This function accepts any number of Observables. Then when something changes, it emits a list of the most recent values for each Observable in the order that it was given to the <code>combineLatest</code> function.</p>

<p>It looks like this:</p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope', 'rx', 'observeOnScope'];  
function Controller1($scope, rx, observeOnScope) {  
    $scope.property1 = {};
    $scope.property2 = {};
    $scope.property3 = {};

    rx.Observable.combineLatest(
            observeOnScope($scope, 'property1', true),
            observeOnScope($scope, 'property2', true),
            observeOnScope($scope, 'property3', true)
        )
        .subscribe(function(changes) {

          /*  changes will look like this:
             [
                  {newValue: {...}, oldValue:{...}},
                  {newValue: {...}, oldValue:{...}},
                  {newValue: {...}, oldValue:{...}}
             ]
         */
        });
}
</code></pre>

<p>As you can see, we now have a predictable object that gives us the new value for each "watched" property every time any of them change. </p>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>If you're wondering if there's a thing that rxjs can do, the answer is most likely "yes". There are a TON of helper functions and built in functionality. The hard part is finding it.</p>

<p>Thankfully, the documentation is continually getting better. Things like RxMarbles are also attempting to help with this.</p>

<p>In fact, here is the <a href='http://rxmarbles.com/' #combineLatest">RxMarble for combineLatest</a>!</p>]]></description><link>http://blog.dustinnation.com/ditch-your-angular-1-x-watchers-follow-up/</link><guid isPermaLink="false">5faa04de-0490-447d-8305-94155f894eac</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Tue, 06 Sep 2016 15:29:59 GMT</pubDate></item><item><title><![CDATA[Ditch Your Angular 1.x Watchers! Quick-Swap Them for Observables]]></title><description><![CDATA[<h5 id="convertingdwatchtoobserveonscope"><em>Converting $watch to observeOnScope</em></h5>

<p><em>Note: I wrote this article to help my teammates understand my quest to eradicate  $watch in our application. I hope it helps someone else, too!</em></p>

<p>Observables are very powerful and have a lot of different functionality, but they can also be very simple to use. Here, we will convert a few <code>$watch</code>'s to <code>observeOnScope</code>.</p>

<p><code>observeOnScope</code> uses <code>$watch</code> in the background, but switching will gain you access to the wide world of Observers and will start to move you down the future path where Angular 2 has switched to exclusively using Observables for change detection.</p>

<hr />

<h2 id="therxangularjslibrary">The rx.angular.js Library</h2>

<p>RXJS provides a helper library to use Observables on Angular 1.x projects. </p>

<p>Here is the <a href='https://github.com/Reactive-Extensions/rx.angular.js/tree/master/docs' #rx">documentation</a>.</p>

<p>For this discussion, we'll only be using the <code>observeOnScope</code> function. You give it a $scope and an attribute and it creates an Observable with them.</p>

<p>Begin by adding rx.angular to your bower files.</p>

<pre><code class="`language-bash">bower install angular-rx --save  
</code></pre>

<p>Then add the files to your html.</p>

<pre><code class="`language-markup">&lt;script src='http://blog.dustinnation.com/bower_components/rxjs/modules/rx-lite/rx.lite.js' &gt;&lt;/script&gt;  
&lt;script src='http://blog.dustinnation.com/bower_components/rx-angular/modules/rx.lite.angular/rx.lite.angular.js' &gt;&lt;/script&gt;  
&lt;script src='http://blog.dustinnation.com/bower_components/angular/angular.js' &gt;&lt;/script&gt;  
</code></pre>

<p><em>Tip: Make sure you import rx.angular.js before angular.js or it gets mad.</em></p>

<p><em>Note: The documentation doesn't say you need to import rxjs, but I had to.</em></p>

<p>Lastly, we need to declare RXJS as a dependency to our app.</p>

<pre><code class="`language-javascript">angular.module('app', [  
  ...
  'rx',
  ...
]);
</code></pre>

<hr />

<h2 id="convertingbasicwatchers">Converting Basic Watchers</h2>

<p><br></p>

<h3 id="noncontrollerascontroller">Non-"controllerAs" controller</h3>

<p>We'll start by looking at a controller that's directly using the $scope object. Here's its <code>$watch</code>:</p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope'];  
function Controller1($scope) {  
    $scope.property1 = false;

    $scope.$watch('property1', function(newValue, oldValue) {

        if (newValue &amp;&amp; oldValue) {
            //Do Something        
        }
    });
}
</code></pre>

<p><code>$watch</code> expects the property name and the function that is to be run when the property changes.</p>

<p>Similarly, you'll need both when converting to <code>observeOnScope</code>. </p>

<p>It expects the following arguments: </p>

<ul>
<li>scope - the scope we're working on</li>
<li>propertyName or function - the property name, or a function that returns the value to be checked. (The function will be called with the provided scope as its parameter.)</li>
</ul>

<p>First, you'll need to declare <code>observeOnScope</code> as a dependency of the controller.</p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope', 'observeOnScope'];  
function Controller1($scope, observeOnScope) {  
    ...
}
</code></pre>

<p>Then we define an Observable on the thing we were <code>$watch</code>ing. That definition would look like this:</p>

<pre><code class="`language-javascript">observeOnScope($scope, 'property1');  
</code></pre>

<p>But you still need to tell the application what to do when the Observable changes. That is accomplished with a "subscription."</p>

<p>Subscriptions are functions that are called when the Observable changes. When fired, they are given an object that has the attributes <code>newValue</code> and <code>oldValue</code>.</p>

<pre><code class="`language-javascript">observeOnScope($scope, 'property1')  
    .subscribe(function(change) {

        if (change.newValue &amp;&amp; change.oldValue) {
            //Do Something        
        }
    });
</code></pre>

<p>That's it! You're done!</p>

<p>Here's what the controller looks like now:</p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope', 'observeOnScope'];  
function Controller1($scope, observeOnScope) {  
    $scope.property1 = false;

    observeOnScope($scope, 'property1')
        .subscribe(function(change) {

            if (change.newValue &amp;&amp; change.oldValue) {
                //Do Something        
            }
        });
}
</code></pre>

<p><br></p>

<h3 id="convertingacontrollerascontroller">Converting a controllerAs Controller</h3>

<p>This conversion follows the same formula as described above, but you need to be careful to provide the right attribute name (just like you have to be careful with a <code>$watch</code>)</p>

<pre><code class="`language-javascript">// controllerAs: 'ctrlAs'
ControllerAs1.$inject = ['$scope'];  
function ControllerAs1($scope) {  
    var vm = this;

    vm.property1 = false;

    $scope.$watch('ctrlAs.property1', function(newValue, oldValue) {

        if (newValue &amp;&amp; oldValue) {
            //Do Something        
        }
    });
}
</code></pre>

<p>Becomes...</p>

<pre><code class="`language-javascript">// controllerAs: 'ctrlAs'
ControllerAs1.$inject = ['$scope', 'observeOnScope'];  
function ControllerAs1($scope, observeOnScope) {  
    var vm = this;

    vm.property1 = false;

    observeOnScope($scope, 'ctrlAs.property1')
        .subscribe(function(change) {

            if (change.newValue &amp;&amp; change.oldValue) {
                //Do Something        
            }
        });
}
</code></pre>

<hr />

<h2 id="observinganobjectsattributes">Observing an Object's Attributes</h2>

<p>Sometimes we need to detect changes on attributes of an Object. With <code>$watch</code> we could pass in the optional "deep" <em>boolean</em> parameter, like this:</p>

<pre><code class="`language-javascript">$scope.object1 = {...};

$scope.$watch('object1', function(){}, true);
</code></pre>

<p>Similarly, you can tell <code>observeOnScope</code> to detect "deep" attributes changes. Like this:</p>

<pre><code class="`language-javascript">$scope.object1 = {...};

observeOnScope($scope, 'object1', true)  
    .subscribe(function(){});
</code></pre>

<hr />

<h2 id="unsubscribingfromanobservable">Unsubscribing from an Observable</h2>

<p>Sometimes you need to cancel a <code>$watch</code>. </p>

<p>The <code>$watch</code> function returns a function that cancels itself. So you'd cancel it like this:</p>

<pre><code class="`language-javascript">// controllerAs: 'ctrlAs'
ControllerAs1.$inject = ['$scope'];  
function ControllerAs1($scope) {  
    var vm = this;

    vm.property1 = false;

    vm.cancelWatcher = $scope.$watch('ctrlAs.property1', function(newValue, oldValue) {

        if (newValue &amp;&amp; oldValue) {
            //Do Something        
        }
    });

    vm.cancelWatcher();
}
</code></pre>

<p><code>observeOnScope</code> provides a similar feature, but it is a bit more nuanced. </p>

<p>Here's the code, followed by a bit of a technical discussion on what is happening (and why it's useful).</p>

<pre><code class="`language-javascript">// controllerAs: 'ctrlAs'
ControllerAs1.$inject = ['$scope', 'observeOnScope'];  
function ControllerAs1($scope, observeOnScope) {  
    var vm = this;

    vm.property1 = false;

    vm.propertySubscription = observeOnScope($scope, 'ctrlAs.property1')
        .subscribe(function(change) {

            if (change.newValue &amp;&amp; change.oldValue) {
                //Do Something        
            }
        });

    vm.propertySubscription.dispose();
}
</code></pre>

<p>This has the same effect as canceling a <code>$watch</code>, in that the function you provide to the subscription will cease to be called when the property changes. However, it has some subtle differences.</p>

<p>The result of calling <code>.subscribe()</code> is what is called a Disposable. This simply means that it's an object that can control whether or not it is active or stopped. </p>

<p>With rx.angular.js when a $scope is destroyed, all subscriptions to it are disposed of by default.</p>

<p>It's important to remember that there are two parts to the change detection now: the Observable and the subscriptions to it. </p>

<p>This allows you to provide an observable from a service, and let different parts of the application control their own subscriptions. So, disposing of a subscription in one controller will not affect the Observable or any other subscriptions to it.</p>

<hr />

<h2 id="usingafunctiontoprovidesubjectofobservable">Using a Function to Provide Subject of Observable</h2>

<p><code>$watch</code> can accept a function that returns the value you want to watch. For example:</p>

<pre><code class="`language-javascript">// controllerAs: 'ctrlAs'
Controller1.$inject = ['$scope'];  
function Controller1($scope) {  
    $scope.property1 = 1;
    $scope.property2 = 2;

    $scope.$watch(function() {
            return $scope.property1 + $scope.property2;
        }, function(newValue, oldValue) {

            if (newValue &amp;&amp; oldValue) {
                //Do Something        
            }
        });
}
</code></pre>

<p><code>observeOnScope</code> allows you to pass in a function as well.  It will even pass in the scope you provided in the first parameter to this function.</p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope', 'observeOnScope'];  
function Controller1($scope, observeOnScope) {  
    $scope.property1 = 1;
    $scope.property2 = 2;

    observeOnScope($scope, function(scope) {
            return scope.property1 + scope.property2;
        })
        .subscribe(function(change) {

            if (change.newValue &amp;&amp; change.oldValue) {
                //Do Something        
            }
        });
}
</code></pre>

<p>Notice we're using <code>scope.property1</code> instead of <code>$scope.property1</code> inside the "subject" function. While not always necessary, this can be really helpful if, for some reason, you need to pass in a different <code>scope</code> than the <code>$scope</code> that you're defining your Observable in. It is "best practice" to limit the scope of this "subject" function to its own closure.</p>

<hr />

<h2 id="cleanitallupwithnamedfunctions">Clean It All Up With Named Functions</h2>

<p>If you're feeling feisty...</p>

<pre><code class="`language-javascript">Controller1.$inject = ['$scope', 'observeOnScope'];  
function Controller1($scope, observeOnScope) {  
    $scope.property1 = 1;
    $scope.property2 = 2;

    observeOnScope($scope, getAdditionResult)
        .subscribe(onValueChange);

    ////////////////

    function getAdditionResult(scope) {
        return scope.property1 + scope.property2;
    }

    function onValueChange(change) {

        if (change.newValue &amp;&amp; change.oldValue) {
            //Do Something        
        }
    }
}
</code></pre>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>This article barely scratches the surface of how you can use Observables, but it should give you the gist of how to do a quick 1-for-1 swap with <code>$watch</code>. Enjoy.</p>]]></description><link>http://blog.dustinnation.com/ditch-your-angular-1-x-watchers-quick-swap-them-for-observables/</link><guid isPermaLink="false">8f31fdf1-6d6c-467e-baa7-1472ce61f884</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Thu, 14 Jul 2016 16:22:24 GMT</pubDate></item><item><title><![CDATA[Ignoring SASS Partials in the Angular-CLI Build]]></title><description><![CDATA[<p>In my last post, I talked about how I'm attempting to port my current Angular 1 project to Angular2. I decided to use the CLI since it forces you to use the current "best practices." </p>

<p>After setting up my first route, I decided to pull over the HTML template and the existing styles.</p>

<p><em>This post is basically a duplicate of the <a href='http://stackoverflow.com/questions/37581613/angular2-sass-unable-to-build-on-angular-cli/37600065' #37600065">Stack Overflow question</a> that I asked, and then answered myself.</em></p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p>Here is the basic format of the pre-existing SASS:</p>

<p><strong>src/app/styles/master.scss</strong></p>

<pre><code class="`language-css">@import 'folder/variables';
@import 'folder/headers';
</code></pre>

<p><strong>src/app/styles/folder/_variables.scss</strong></p>

<pre><code class="`language-css">$header-bg: #ababab;
</code></pre>

<p><strong>src/app/styles/folder/_headers.scss</strong></p>

<pre><code class="`language-css">h1 {  
  background-color: $header-bg;
}
</code></pre>

<p>Unfortunately, after following the instructions on the <a href='https://github.com/angular/angular-cli' #css-preprocessor-integration">Github readme</a>, I was getting build errors.</p>

<p>In short, it was complaining that it couldn't find the declarations for variables in one of the SASS partials.</p>

<p>Here was the error:</p>

<pre><code class="`language-bash">Build failed.  
File: /my-app/tmp/sassplugin-input_base_pathjFTXlfed.tmp/0/  
src/app/styles/folder/_more.scss (2)  
The Broccoli Plugin: [SASSPlugin] failed with:  
Error: Undefined variable: "$header-bg".  
</code></pre>

<hr />

<h2 id="thesolution">The Solution</h2>

<p>After spending way too much time Googling and searching Stack Overflow, I decided to go line-by-line in the Angular-CLI source to better understand the build process.</p>

<p>As I read, I noticed that there were many "<em>.scss", but none for "_</em>.scss".  Just about that time the most recent commit message caught my eye. <br />
<code>feat(SASSPlugin): Allow regexes to be passed to include/exclude certa…</code></p>

<p>I clicked on the commit, and boom! There was the answer.</p>

<p><strong>angular-cli-build.js</strong></p>

<pre><code class="`language-javascript">sassCompiler: {  
  cacheExclude: [/\/_[^\/]+$/]
}
</code></pre>

<p>You can read the actual commit, <a href='https://github.com/angular/angular-cli/commit/6b45099b6a277ecd7a57f2d2e632bf40af774879' >here</a></p>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>Such a simple solution that took up so much of my time. I have a feeling that as I move forward, I'll find a few more "gotchas" along the way. However, I'm sure the documentation will get better over time, too.</p>]]></description><link>http://blog.dustinnation.com/ignoring-sass-partials-in-the-angular-cli-build/</link><guid isPermaLink="false">dd303d2c-49e0-483c-80d9-a786fdbe16a3</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Thu, 02 Jun 2016 19:37:24 GMT</pubDate></item><item><title><![CDATA[Getting Generated Routes to Work in Angular-CLI]]></title><description><![CDATA[<p><em>UPDATE</em> <br />
<em>The "new-new" router has dropped, and the Angular CLI has turned off the router generator until it has integrated it.</em></p>

<p><em>In the interim, I've just been generating a component, renaming all of the files with a "+" if I want that route lazy loaded, then manually inserting the router config.</em></p>

<p>Lately I've been trying to teach myself Angular 2. Having watched ng-conf talks, I figured that since the angular-cli was more-or-less "blessed" by the Angular team, it might be a good way to spin up some example projects. However, I soon hit a snag.</p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p>As of the time of writing this, generating routes with the angular-cli does not work out of the box.</p>

<p>Running <code>ng new my-app</code> creates the structure and you start with the following:</p>

<p><strong>my-app.component.ts</strong></p>

<pre><code class="`language-javascript">import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'my-app-app',
  templateUrl: 'my-app.component.html',
  styleUrls: ['my-app.component.css']
})
export class MyAppAppComponent {  
  title = 'my-app works!';
}
</code></pre>

<p>Adding your first route with <code>ng generate route my-route</code> leaves you with:</p>

<p><strong>my-app.component.ts</strong></p>

<pre><code class="`language-javascript">import { Component } from '@angular/core';  
import { MyRouteComponent } from './+my-route';  
import { Routes , ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from '@angular/router';

@Component({
  moduleId: module.id,
  selector: 'my-app-app',
  templateUrl: 'my-app.component.html',
  styleUrls: ['my-app.component.css'],
  directives: [ROUTER_DIRECTIVES],
  providers: [ROUTER_PROVIDERS]
})
@Routes([
  {path: '/my-route', component: MyRouteComponent}
])
export class MyAppAppComponent {  
  title = 'my-app works!';
}
</code></pre>

<p><em>Note: I recently tried this on my work laptop and none of the ROUTE_PROVIDERS business was included.</em></p>

<p>All good, right? Unfortunately, if you navigate to <em>/my-route</em> nothing happens. Bummer.</p>

<hr />

<h2 id="thesolution">The Solution</h2>

<p>Fear not! All it takes to get the router to work is to wire up a few more things.</p>

<p><em>Credit: <a href='https://github.com/angular/angular-cli/issues/708' >https://github.com/angular/angular-cli/issues/708</a></em></p>

<p>First, you need to add "Router" to the other router imports. Then all you need to do is add a constructor in my-app.component.ts. Its as simple as <code>constructor(private router:Router) { }</code></p>

<p>Without further ado, here's the final result:</p>

<p><strong>my-app.component.ts</strong></p>

<pre><code class="`language-javascript">import { Component } from '@angular/core';  
import { MyRouteComponent } from './+my-route';  
import { Router, Routes , ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from '@angular/router';

@Component({
  moduleId: module.id,
  selector: 'my-app-app',
  templateUrl: 'my-app.component.html',
  styleUrls: ['my-app.component.css'],
  directives: [ROUTER_DIRECTIVES],
  providers: [ROUTER_PROVIDERS]
})
@Routes([
  {path: '/my-route', component: MyRouteComponent}
])
export class MyAppAppComponent {

  constructor(private router:Router) { }

  title = 'my-app works!';
}
</code></pre>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>There is also one more way to make the routes work. If you add a routerLink to my-app.component.html the router will get instantiated behind the scenes. But that's not always the way you need to go about things.</p>

<p>Now that routing's out of the way...maybe I can get SASS working in the build process.</p>

<p>Happy cli-ing and routing!</p>]]></description><link>http://blog.dustinnation.com/getting-generated-routes-to-work-in-angular-cli/</link><guid isPermaLink="false">b875e2b4-c123-49df-8bea-298a0c3563d5</guid><category><![CDATA[Angular2]]></category><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Wed, 01 Jun 2016 03:19:36 GMT</pubDate></item><item><title><![CDATA[Developers Die. Projects Must Live On. (Intro + Version Control)]]></title><description><![CDATA[<p>I'm the only front end engineer on my team and like most of us, I've got a crushing feature backlog.</p>

<p>Earlier this year I had the realization that if I left the project, it would either die or be completely re-written by the next guy. It wouldn't suffer this fate  because I've written bad code, but because I'd been using the large feature backlog as an excuse to neglect all of the non-code parts of the project that enable developers to be effective.</p>

<p>The project in question is an application I helped conceive and something that has the potential to make the lives of our internal business customers much easier. Needless to say, I've got an emotional attachment to it and want to see it survive whether I'm working on it or not.</p>

<p>So, I set out to fix the situation. I did some research to try and figure out what best practices and tools I could use. After some time I was able to put together a list of things I needed to do in order to harden my project against turnover (or make on-boarding new teammates much easier).</p>

<h4 id="disclaimer">Disclaimer</h4>

<p><em>These articles are written to serve as a jumping off point for someone in a similar situation. They are intended as an entry level discussion. I give some tips on how I implemented the discussed concepts as I produced features, but those who are an on a mature team probably won't gain much from this series.</em></p>

<h2 id="thelist">The List</h2>

<ol>
<li><strong>Git the most out of version control (see what I did there?)</strong>  </li>
<li>More better documentation  </li>
<li>Implement a coding style guide  </li>
<li>Easily reproducible environments  </li>
<li>Testing...ugh  </li>
<li>Utilize build tools  </li>
<li>Setup continuous integration</li>
</ol>

<h2 id="versioncontrol">Version Control</h2>

<blockquote>
  <p>“Any kind of practice that tracks and provides control over changes to source code” - Wikipedia</p>
</blockquote>

<p>Most of us use or have at least heard of version control before. But for those that are new to the subject, its just a system of keeping track of the changes you've made to your code. </p>

<h3 id="versioncontrolsystems">Version Control Systems</h3>

<p>Software that helps track these changes are called Version Control Systems (VCS). </p>

<p>There are 3 major VCSs to be aware of. They share many of the same major features but have some significant implementation differences. I encourage you to try them all out and choose one that fits your way of thinking and meets your needs.</p>

<ol>
<li>Git  </li>
<li>Mercurial  </li>
<li>Team Foundation Server VCS</li>
</ol>

<h4 id="git">Git</h4>

<p>Git is currently the most popular of the 3 due largely to its widespread adoption in the open source world. Most open source tooling around VCSs assumes that you're using Git. It has been described as the "MacGyver" of VCSs because it has lots of utility functions and there seem to be multiple ways of accomplishing the same thing.</p>

<p>Most of the online repository services support Git, including <a href='http://github.com/' >Github</a>, <a href='http://bitbucket.org/' >Bitbucket</a>, and <a href='http://msdn.microsoft.com/en-us/vstudio/ff637362.aspx' >Team Foundation Server</a>.</p>

<h4 id="mercurial">Mercurial</h4>

<p>Mercurial debuted around the same time as Git in 2005. It was a strong competitor to Git until around 2010 when Git seemed to gain critical mass. It has been described as the "James Bond" of VCSs because many people believe usage of it to be more elegant than Git.</p>

<p>The main online repository service that supports Mercurial is Bitbucket.</p>

<h4 id="teamfoundationservervcs">Team Foundation Server VCS</h4>

<p>This is Microsoft's VCS. If your company is mainly a Microsoft shop, there's a good likelihood that you'll want to use TFS as it integrates nicely with all of the Visual Studio environments and tooling.</p>

<p>As you might expect, its only supported by TFS.</p>

<h3 id="vcstools">VCS Tools</h3>

<p>There are many tools out there focused on providing a GUI for VCSs.</p>

<p>Some Git standouts are <a href='http://www.git-tower.com/' >Tower</a>, <a href='https://windows.github.com/' >Github's Windows client</a> &amp; <a href='http://mac.github.com/' >Github's Mac Client</a>, and <a href='http://www.sourcetreeapp.com/' >SourceTree</a>.</p>

<p>Some Mercurial standouts are <a href='http://www.sourcetreeapp.com/' >SourceTree</a> and <a href='http://tortoisehg.bitbucket.org/' >TortoiseHg</a>.</p>

<p>TFS is tightly integrated into Visual Studio IDE.</p>

<p>My favorite is SourceTree because I can use it for my Git and Mercurial projects, but you should check them all out and choose the one that best fits you and your needs.</p>

<h3 id="issuetracking">Issue Tracking</h3>

<p>Many of the VCS services provide a way for developers and users to submit issues and discuss them. I won't get into issue tracking much here besides to say that many developers, even solo developers, find issue tracking to be a fantastic way of keeping track of required maintenance for their applications.</p>

<h3 id="commitmessages">Commit Messages</h3>

<p>Once you're using version control, one of the most important things you can do to help your team understand the changes happening on the project is to write good commit messages.</p>

<p>Good commit messages describe 3 things.</p>

<ol>
<li>The issue being fixed or feature being added  </li>
<li>The changes made and the rationale behind them  </li>
<li>Any side-effects the changes bring</li>
</ol>

<h4 id="examples">Examples</h4>

<p><strong>Bad Commit Message</strong></p>

<pre><code>commit -m "Fixed a spinner bug."  
</code></pre>

<p>Notice 2 things here. </p>

<p>Firstly, the message is incredibly vague. What spinner bug? Where is it? How'd you fix it?</p>

<p>Secondly, its written in the command line. Executing VCS commands from the command line is not necessarily a bad thing, however, committing from the command line makes it very hard to craft good messages.</p>

<p><strong>Good Commit Message</strong></p>

<p><em>From a VCS tool</em></p>

<pre><code>Stops the spinner from showing on form A's "ok" button hover (#123)

Removes the event trigger that caused the spinner to show when the user hovers over the "ok" button.  
</code></pre>

<p>As you can see, this message was written in a VCS tool. This allows you to format the message in a way that's conducive to writing good, informative commit messages. Some of the tools even allow you to write commit messages in markdown. Fancy!</p>

<p>You'll also notice how specific the first line is. It explains the issue being addressed and also where in the application you'd find the issue (Form A's "ok" button). It even has a reference to an issue number (the VCS you use may have a more integrated way of linking commits with issues).</p>

<p>The second paragraph explains what was done to address the issue. This is where you can get a bit more technical and where you'd go into rationale if necessary.</p>

<h3 id="branching">Branching</h3>

<p>Branching is a feature of VCSs that allows you to make as many changes to your code as you want while still maintaining a version that is ready for your users. When you're done making changes, the VCS will assist you in "merging" all of your changes back into the main version.</p>

<h4 id="thetheory">The Theory</h4>

<p>Take the following example: <br />
<img src='http://www.gamasutra.com/db_area/images/feature/5900/image001.png'  alt="branching diagram" />
<em><a href='http://www.gamasutra.com/db_area/images/feature/5900/image001.png' >http://www.gamasutra.com/db_area/images/feature/5900/image001.png</a></em></p>

<p>In this example there is a main development branch. A branch for Feature A is started, but before it is finished Feature B is started in its own branch. Likewise, before Feature B is finished, Feature C is started in its own branch. After that Feature B is finished and merged back into the main development branch, then Feature C, then finally Feature A.</p>

<p>The theory here is that at any point in developing Feature's A, B, or C the main development line could be put into production.</p>

<h4 id="mybranchingscheme">My Branching Scheme</h4>

<p>The branching scheme I use is based off of a Mercurial plugin called Hg Flow which is also a built in feature in SourceTree. There exists a "Git Flow" as well, but I have little experience with it. </p>

<p>It looks a little something like this: <br />
<img src='https://docs.google.com/drawings/d/1SW5k9oFSXchWm8cxPiMfvLJhOFfGluMr2pJovI_WJBQ/pub?w=888&amp;h=334'  alt="my branch flow" /></p>

<p>The heart of the repo is the development branch. It is the branch from which features are started and the branch that completed features join the herd. When a substantial feature set is finished, the development branch merges into the production branch.</p>

<p>Hg Flow and Git Flow have convenience functions to facilitate this including a "Start Feature" button that opens a new branch and even namespaces the feature with "feature/".</p>

<h3 id="conclusion">Conclusion</h3>

<p>Version control is the most basic, yet most powerful thing you can do to start working in a team-friendly environment. Its easy to take shortcuts in branching workflow and in writing commit messages, and we all do it from time to time. However, creating and following VCS guidelines will enable your team and save you from unexpected headaches.</p>]]></description><link>http://blog.dustinnation.com/developers-die-projects-must-live-on-intro-version-control/</link><guid isPermaLink="false">c4484708-1ec8-4fb0-8885-df559e419a08</guid><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Fri, 26 Sep 2014 16:10:01 GMT</pubDate></item><item><title><![CDATA[Update - Fantasy Soccer Engine]]></title><description><![CDATA[<hr />

<h2 id="update">Update</h2>

<p>Due to low interest and homeownership keeping me from having as much free time as expected, I have suspended work on this project. I fully intend to pick it back up later in the year. In the mean time, the code is up (as promised) at <a href='https://github.com/d-nation/soccer-sim-engine' >https://github.com/d-nation/soccer-sim-engine</a></p>

<p>I've documented it as much as possible. Feel free to use it, improve it, or show me how I'm doing NodeJS wrong! Its my first go at making a Node project, so any feedback is welcome.</p>]]></description><link>http://blog.dustinnation.com/update-fantasy-soccer-engine/</link><guid isPermaLink="false">8b296b44-2e0c-4b71-b03f-71622330c5bf</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Tue, 29 Jul 2014 16:08:23 GMT</pubDate></item><item><title><![CDATA[3Deke - Fantasy Sports Simulation Engine]]></title><description><![CDATA[<p>I know there are 2 or 3 posts that I've billed as "1 of 2" that are still awaiting their "2 of 2", but I've been a bit busy of late working on a project that combines two of my passions (sports and software development).</p>

<h1 id="introducing3deke">Introducing: 3Deke</h1>

<p><a href='https://github.com/d-nation/soccer-sim-engine' >https://github.com/d-nation/soccer-sim-engine</a></p>

<p>I've begun creating a service that I'm describing as a <em>"Fantasy Sports Simulation as a Service"</em>.</p>

<p>There are a lot of people out there who participate in fantasy sports "sim leagues." However, the means of actually simulating a league's games can be a clunky, time consuming, and tedious task for league operators. Some are forced to manually sync their league's rosters with a video game while others are left to use ancient csv-driven desktop software.</p>

<h2 id="isthisafantasysportsleague">Is this a fantasy sports league?</h2>

<p>No. This is simply a simulation engine to be used by "sim league" operators and developers.</p>

<p>I will be standardizing on a player ability ranking scheme (most likely it will align with the EA Sports player abilities), but 3Deke will not be maintaining any type of player, team, or league database. This will allow users to use the game engine in any way they wish and not be beholden to any arbitrary league constraints.</p>

<p>Your league, your way.</p>

<h2 id="howwill3dekehelpsimleagueoperatorsdevelopers">How will 3Deke help "sim league" operators/developers?</h2>

<p>With 3Deke I aim to make life better for league operators/developers by creating an API driven simulation engine. This opens the possibility for a league to automate simulation straight from league data already saved in the user's own site.</p>

<p>The game engine API will accept basic league information such as team rosters and player ability rankings to start a simulation. When the simulation is finished, the game details can be sent to a callback URL or retrieved upon request. It will even save a play-by-play so that a league's participants can see exactly how a game unfolded.</p>

<h2 id="whatsportswillbeavailable">What sports will be available?</h2>

<p>I'm starting with soccer (futbol). The idea for this whole service was sparked by an iPhone "Footy Manager" game, so I decided to start there.</p>

<p>My two main sports passions are the English Premier League and the NHL, so as soon as the soccer engine reaches a viable state, I'll be expanding to a hockey simulation engine.</p>

<p>If there's demand for a different sport following the completion of these two, I'll work on them then.</p>

<h2 id="howdetailedwillgameoutputbe">How detailed will game output be?</h2>

<p>Very. Eventually. </p>

<p>I'm creating this in such a way that almost everything about the game can be tracked and reported. However, detail takes time. </p>

<p>Starting out, there will be very basic game statistics such as score and discipline. Over time, new game information will be added such as injuries and substitutions.</p>

<h2 id="canitrustthegameengine">Can I trust the game engine?</h2>

<p>Yup. It's my plan to open source the engine portion of the service. This provides transparency as well as opens up the engine for peer review and community contributions.</p>

<p>If you're ambitious, you could even use the open source code to implement your own engine service.</p>

<h2 id="whatsthetimeline">What's the timeline?</h2>

<p>This is a side project for me, so it'll inevitably take longer to create than I'd like.  </p>

<p>That having been said, its my goal to get a very basic version of the engine completed prior to the World Cup finals in order to "predict" a winner. After that minimally viable product (MVP to those in the biz) is ready, things will start rocking. That's the point in which I'll open source the engine and open up the API to beta testers.</p>

<h2 id="whatswiththename">What's with the name?</h2>

<p>3Deke is a play on the gamer tag I've had since I started playing Eve Online years and years ago (Triple Deke). A "deke" is the hockey equivalent to a "juke" in American football. Remember The Mighty Ducks?</p>

<h2 id="update72914">Update (7-29-14)</h2>

<p>Due to low interest and homeownership keeping me from having as much free time as expected I have suspended work on this project. I fully intend to pick it back up later in the year. In the mean time, the code is up (as promised) at <a href='https://github.com/d-nation/soccer-sim-engine' >https://github.com/d-nation/soccer-sim-engine</a></p>]]></description><link>http://blog.dustinnation.com/3deke-fantasy-sports-simulation-engine/</link><guid isPermaLink="false">a19fc022-f93c-42a5-b1d3-c4594cdc91ba</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Thu, 12 Jun 2014 02:26:09 GMT</pubDate></item><item><title><![CDATA[Maintainable Backbone Micro-Templates with RequireJS and Underscore]]></title><description><![CDATA[<p>For me, MarionetteJS was love at first site. Everything just made sense and worked the way I expected it to...everything but the templating. Its template processing and the usage syntax around it is great, but all of the documentation shows the templates being created from HTML-snippets wrapped in <code>&lt;script&gt;</code> tags on the app's main HTML page.</p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p>This is all well and good, except that I am building a very large single page app that will have a multitude of modules and views. Do I even need to say how non-maintanable having all of your templates for all of your modules and views on your app's single HTML page is?</p>

<p>So then how does one supply templates to views in a way that's maintainable?</p>

<hr />

<h2 id="myfirstsolution">My First Solution</h2>

<p>Under a time crunch, and with Google-foo failing me, I came up with a solution that got me part of the way there. I created a requireJS module for each Marionette module that exported a big object of template strings.</p>

<p>The file structure went something like this:</p>

<pre><code class="`language-bash">App/  
    -module/
        -models/
        -views/
            -mainView.js
        -module.js
        -templates.js
</code></pre>

<p>And the <strong>templates.js</strong> file looked something like this:</p>

<pre><code class="`language-javascript">define(function(require){  
    "use strict";

    var template1 =
            "&lt;h1&gt;Hey there!&lt;/h1&gt;\
            &lt;p&gt;How goes, &lt;%= name %&gt;&lt;/p&gt;,

        template2 =
            "...";

    return {
        template1: template1,
        template2: template2
    };
});
</code></pre>

<p>This solved a lot of my problems, but still left me with some maintainability nightmares. Here's a pro-con list:</p>

<h4 id="pros">Pros</h4>

<ul>
<li>No templates in the main HTML file</li>
<li>Templates live under their modules, keeping modules more modular</li>
<li>Only one requirement import per view</li>
</ul>

<h4 id="cons">Cons</h4>

<ul>
<li>Writing HTML in Javascript (barf)</li>
<li>A module with lots of templates will have a bloated templates.js file</li>
</ul>

<hr />

<h2 id="abettersolution">A Better Solution</h2>

<p>This worked for getting me started, so I rolled with it. However, over time the con's listed above really, really bothered me. My IDE's syntax highlighting hated me for it, I had to constantly fight the <code>'</code> vs <code>"</code> battle in writing HTML strings, keeping track of <code>\</code>'s at end of the lines was hard, and once my views started to use conditional templating and micro-templating, these files got to be hundreds of lines long.  Not good.</p>

<p>So, once I'd had enough, I started asking around on Twitter. A lovely user named Boris (<a href='https://twitter.com/zbzzn' >@zbzzn</a>) enlightened me to a part of requireJS I'd overlooked...the <a href='https://github.com/requirejs/text' >text plugin</a>. It allows you to declare HTML files (or other text files) as dependencies.</p>

<p>Great! I dropped the text.js file in my app's main folder and got cracking. Now I could separate each template into its own file and pull them in like this:</p>

<p><strong>module/templates/main.html</strong></p>

<pre><code class="`language-markup">&lt;dir&gt;Main Template&lt;/dir&gt;  
</code></pre>

<p><strong>view.js</strong></p>

<pre><code class="`language-javascript">define(["marionette", "text!module/templates/main.html"],  
    function (Marionette, mainTemplate) {
        "use strict";

    return Marionette.ItemView.extend({
        template: _.template(mainTemplate);
    });    
});
</code></pre>

<h4 id="pros">Pros</h4>

<ul>
<li>No templates in the main HTML file</li>
<li>Templates live under their modules, keeping modules more modular</li>
<li>HTML written in HTML</li>
</ul>

<h4 id="cons">Cons</h4>

<ul>
<li>Views with multiple templates will need to import multiple files (can get overwhelming)</li>
</ul>

<p>This alone takes a huge stride towards better maintainability, and for many (most?) this is perfect. However, if you're doing conditional templating and/or micro-templating this method also means that many of your views will need to import multiple templates (I have a few views with 10+ templates). Keeping track of that many imports in the require syntax is a nightmare and creates a ton of unique variable names inside the require module that you have to then remember and not use again.</p>

<hr />

<h2 id="mysolution">My Solution</h2>

<p>Ok, here's where I get crazy. The con of the previous method of handling templates is actually a pro of the first method I used. "Why not combine them?" I thought. So I did. </p>

<p>I ended up with the following:</p>

<pre><code class="`language-bash">App/  
    -module/
        -models/
        -views/
            -mainView.js
        -templates/
            -main.html
            -main-alt.html
            -templates.js
        -module.js
</code></pre>

<p><strong>templates.js</strong></p>

<pre><code class="`language-javascript">define(["text!module/templates/main.html",  
        "text!module/templates/main-alt.html"],
        function (main, mainAlt) {
    "use strict";

    return {
        "main": main,
        "mainAlt": mainAlt
    }
});
</code></pre>

<p><strong>mainView.js</strong></p>

<pre><code class="`language-javascript">define(["marionette", "module/templates/templates"],  
    function (Marionette, templates) {
        "use strict";

    return Marionette.ItemView.extend({
        template: function(serializedModel){
            if (someCondition){
                return _.template(templates.mainAlt);
            } 

            return _.template(templates.main);            
        }
    });    
});
</code></pre>

<p>In essence, I moved the multiple template imports into a require module whose only responsibility is templates. Each view now only imports one file for templates, giving the view logic the clear focus. If you need to add, remove, or change the name of a template, it is done in one place. Make your changes in templates.js then in your view, simply change the attribute you're looking at without needing to also change your require import paths.</p>

<hr />

<h2 id="finalthoughts">Final Thoughts</h2>

<p>Creating a separate template require module for each Marionette module may seem like I'm adding an unneccessary layer. Maybe. But it gives me a much cleaner view as well as one central access point for templates across all of the module's views. What's more, is that in addition to all of the pro's on both of my lists, after I type the <code>.</code> in <code>templates.</code> I get IDE code completion! No more needing to remember the exact variable name I gave them all when importing. Bonus!</p>

<p>Hate it? Love it? Let me know on Twitter (<a href='https://twitter.com/D_Naish' >@D_Naish</a>)</p>]]></description><link>http://blog.dustinnation.com/maintainable-backbone-micro-templates-with-requirejs-and-underscore/</link><guid isPermaLink="false">7e8b421c-0562-46d8-b907-20bf13cabd7f</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Thu, 15 May 2014 18:37:59 GMT</pubDate></item><item><title><![CDATA[JSDoc3 with Backbone and RequireJS (Models and Collections)]]></title><description><![CDATA[<p>Recently I've been on a mission. I call this mission "The 'What happens to my project if I get hit by a bus?' Mission."  </p>

<p>You see, I am the only front-end engineer, developer, and designer on my team. We spent the bulk of last year feverishly releasing feature after feature just to ensure the project didn't lose funding. However, in order to do this I all but neglected documenting anything about my browser-side code.</p>

<hr />

<h2 id="theproblem">The Problem</h2>

<p>While I've been very diligent in creating a maintainable code base and most of it is pretty straight-forward, I had no documentation around the event-driven parts of my application. To anyone else, it would be very hard to follow the flow of how and what happens when events are triggered.</p>

<p>I decided that I would start with a good code documentation tool. In the past I'd used JSDoc-Toolkit and was pleasantly surprised to see that it had been ported to NodeJS and continued on as <a href='http://usejsdoc.org/' >JSDoc3</a>. </p>

<p>The awesome part is that it includes several tags for documenting event driven code. The not-so-awesome part is that the tool's usage with Require and Backbone/Marionette is...well...it's less than intuitive at best.  This is compounded by spotty documentation and seemingly contradictory advice on Stack Overflow and their Google Group.</p>

<hr />

<h2 id="themysolution">The (My) Solution</h2>

<p>What I quickly learned is that using JSDoc3 on your RequireJS + Backbone project is less of a science and more of an art. Depending on the coding style, you may be forced to override the functionality of many of the tags.  Doing so gives you a lot of flexibility but also requires more work to be done by hand. You can also use this flexibility to tweek how the documentation looks in the generated documentation webpages.</p>

<p>The following is a brief overview of how I chose to implement JSDoc on my project. I'd encourage readers to experiment and explore if this isn't exactly what you're looking for.</p>

<p>The example project structure I'm going to use is as follows:</p>

<pre><code class="`language-bash">App  
 -Module1
    -models
        -model1.js
    -collections
        -collection1.js
        -collection2.js
    -views
        -view1.js
    -module1.js
    -vent.js
    -reqres.js    
</code></pre>

<h3 id="modelsandcollectionsbasic">Models and Collections (Basic)</h3>

<p>Lets start with the most basic documentation, a require definition that defines only one model or collection.</p>

<h4 id="basicmodel">Basic Model</h4>

<p>The first thing you have to do is to tell JSDoc what this require definition is defining. This is done by placing an <code>@exports</code> tag prior to your define block.</p>

<pre><code class="`language-javascript">/**
 * @exports module:Module1.Module1/Models/Model1
 */
define(['backbone'], function (Backbone) {  
    "use strict";
    ...
});
</code></pre>

<p>You'll notice the <code>module:Module1.</code> prefixing the model's path. If you're using a module or otherwise subdividing your code, you'll want to use this to ensure that the documentation webpage reflects this subdivision.</p>

<p>Also of note is that I'm using capitals for the path. This is partly due to the convention of capitalizing class names, but for me it is mainly stylistic for the webdocs.</p>

<p>Next, we need to define the model as a class. We do that using the <code>@constructor</code> tag.  </p>

<pre><code class="`language-javascript">/**
 * @name module:Module1.Module1/Models/Model1
 * @constructor
 * @augments Backbone.Model
 */
return Backbone.Model.extend({  
    ...
});
</code></pre>

<p>Here also use the <code>@name</code> tag to make sure that the class's name matches up with the name we told JSDoc that we're exporting and the <code>@augments</code> tag to specify that we're just adding onto the Backbone.Model object.</p>

<p>Lastly, we need to tell JSDoc that the object being added to Backbone.Model via <code>.extend()</code> is actually the same thing as the class we just told it about.  This is done using some tag placement trickery and the <code>@lends</code> tag. It looks like this...  </p>

<pre><code class="`language-javascript">return Backbone.Model.extend(  
  /** @lends module:Module1.Module1/Models/Model1.prototype **/
  {
      ...
  });
</code></pre>

<p>Be careful to place the tag comment inside the <code>extend</code> openning parenthesis and the object definition's opening curly-bracket.</p>

<p>Once all of this is taken care of, JSDoc can figure out all of the attributes and functions you add in the model's definition using basic JSDoc techniques. </p>

<p>For example, adding a URLRoot function to the model would look like this...</p>

<pre><code class="`language-javascript">return Backbone.Model.extend(  
    /** @lends module:Module1.Module1/Models/Model1.prototype **/
    {       
        /**
         * Specify the URL root to fetch from
         * @returns {string}
         */
        urlRoot: function(){
            if(this.get("isCool")){
                return "../cool/"
            }
            else{
                return "../not-cool/";
            }
        }
    });
</code></pre>

<p>Putting it all together...</p>

<p><strong>model1.js</strong></p>

<pre><code class="`language-javascript">/**
 * @exports module:Module1.Module1/Models/Model1
 */
define(['backbone'], function (Backbone) {  
    "use strict";
    /**
     * @name module:Module1.Module1/Models/Model1
     * @constructor
     * @augments Backbone.Model
     */
    return Backbone.Model.extend(
        /** @lends module:Module1.Module1/Models/Model1.prototype **/
        {
            /**
             * Specify the URL root to fetch from
             * @returns {string}
             */
            urlRoot: function(){
                if(this.get("isCool")){
                     return "../cool/"
                }
                else{
                     return "../not-cool/";
                }
            }
        });
});
</code></pre>

<h4 id="basiccollection">Basic Collection</h4>

<p>Basic collections are documented very similarly to basic model definitions.  However, there is one concept that is added: linking in your model in the documentation.</p>

<p>Documenting the link between the collection's model and the already documented model definition also links them on the generated documentation website, which is very convenient.</p>

<p>The linking is done via the <code>@type</code> tag.</p>

<p><strong>collection1.js</strong></p>

<pre><code class="`language-javascript">/**
 * @exports module:Module1.Module1/Collections/Collection1
 */
define(['backbone', 'models/model1'], function (Backbone, Model1) {  
    "use strict";
    /**
     * @name module:Module1.Module1/Collections/Collection1
     * @constructor
     * @augments Backbone.Collection
     */
    return Backbone.Collection.extend(
    /** @lends module:Module1.Module1/Collections/Collection1.prototype */
    {
        /**
         * This collection contains model1s
         * @type {module:Module1.Module1/Models/Model1}
         */
        model: Model1,

        /** URL to item list */
        url: "/collection1/"
    });
});
</code></pre>

<p><br>  </p>

<h3 id="modelsandcollectionsadvanced">Models and Collections (Advanced)</h3>

<p>Sometimes you need/want to create multiple models, collections, or both in the same require definition. This can be a bit tricky to document in JSDoc. </p>

<p>My most common use case for this is with ItemViews and CollectionViews, which I'll cover in part II. Another common use case for me - and the one I'm going to use here for an example - is when I have a model that is tightly coupled to a collection (meaning that the model only exists for the purpose of filling this one particular collection). </p>

<p>In this scenario the file define's and returns a collection but also creates an internal model to be used by the collection. This seems to confuse JSDoc, so we have to give it a little extra help.</p>

<p>First, document the definition just as we did before. With the exception that we no longer need to reference an external model.</p>

<p><strong>collection2.js</strong></p>

<pre><code class="`language-javascript">/**
 * @exports module:Module1.Module1/Collections/Collection2
 */
define(['backbone'], function (Backbone) {  
    "use strict";
    ...
});
</code></pre>

<p>Then, we create the model.  </p>

<pre><code class="`language-javascript">/**
 * @exports module:Module1.Module1/Collections/Collection2
 */
define(['backbone'], function (Backbone) {  
    "use strict";

    /**
     * @name module:Module1.Module1/Models/Model2
     * @constructor
     * @augments Backbone.Model
     */
     var Model2 = Backbone.Model.extend(
        /** @lends module:Module1.Module1/Models/Model2.prototype **/
        {
            /**
             * Specify the URL root to fetch from
             * @returns {string}
             */
            urlRoot: function(){
                if(this.get("isAdvanced")){
                     return "../cool/"
                }
                else{
                     return "../not-cool/";
                }
            }
        });
    ...
});
</code></pre>

<p>You'll notice that Model2 is tagged in the same way that the stand alone Model1 is above.</p>

<p>Now comes the trickery. After this point, JSDoc really gets confused. We document the collection just like we did above with a "basic" collection, but unfortunately, we have to help it by adding in a <code>@memberof!</code> tag to each of its attributes.  The <code>!</code> at the end of the tag serves to tell JSDoc that it needs to listen to this tag and not try to figure things out on its own.</p>

<p>Here's what the whole thing looks like:</p>

<p><strong>collection2.js</strong></p>

<pre><code class="`language-javascript">/**
 * @exports module:Module1.Module1/Collections/Collection2
 */
define(['backbone'], function (Backbone) {  
    "use strict";

    /**
     * @name module:Module1.Module1/Models/Model2
     * @constructor
     * @augments Backbone.Model
     */
     var Model2 = Backbone.Model.extend(
        /** @lends module:Module1.Module1/Models/Model2.prototype **/
        {
            /**
             * Specify the URL root to fetch from
             * @returns {string}
             */
            urlRoot: function(){
                if(this.get("isAdvanced")){
                     return "../cool/"
                }
                else{
                     return "../not-cool/";
                }
            }
        });

    /**
     * @name module:Module1.Module1/Collections/Collection2
     * @constructor
     * @augments Backbone.Collection
     */
     return Backbone.Collection.extend(
     /** @lends module:Module1.Module1/Collections/Collection2.prototype */
     {
         /**
          * This collection contains model1s
          * @memberof! module:Module1.Module1/Collections/Collection2
          * @type {module:Module1.Module1/Models/Model2}
          */
          model: Model2,

         /** 
          * URL to item list 
          * @memberof! module:Module1.Module1/Collections/Collection2
          */
         url: "/collection2/"
     });
});
</code></pre>

<h2 id="finalthoughts">Final Thoughts</h2>

<p>Documenting this flavor of Marionette code with JSDoc can present some challenges and can be a downright hassle at times. However, the generated documentation webpage and in-code documentation provide clarity of intent and make it well worth it.</p>

<p>In part 2 I will cover the documentation of Views and Event-Driven code.</p>

<h4 id="oncomments">On Comments</h4>

<p>I grew tired of the 1000's of spam bot comments on my previous blog engine so feel free to contact me on Twitter ( <a href='http://twitter.com/d_naish' >@d_naish</a> ) if you like this article, hate it, agree with me, or think I've got it all wrong...or just want to say hi.</p>]]></description><link>http://blog.dustinnation.com/jsdoc3-with-backbone-and-requirejs/</link><guid isPermaLink="false">6564ddaa-0fe7-4822-b004-03308f4d1ed0</guid><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Thu, 27 Mar 2014 15:41:19 GMT</pubDate></item><item><title><![CDATA[Lightning Talk on Firebase and Marionette]]></title><description><![CDATA[<p>Thursday 3/6/14 I'll be giving a lightning talk at the DallasJS meetup.</p>  

<p><strong>Meetup Details</strong>:&nbsp;<a href='http://www.meetup.com/DallasJS/events/165754952/' >http://www.meetup.com/DallasJS/events/165754952/</a></p>  

<p><strong>Topic</strong>: Real Time Puppetry with Marionette and Firebase</p>  

<p><strong>Description</strong>:</p>  

<p>A brief overview of&nbsp;<a href='http://firebase.io/' >Firebase.io</a>, Marionette, and how to connect them for painless real time updates of your views.</p>  

<p></p>  

<p>I'll post the slides and example code here aftwerwards.</p>]]></description><link>http://blog.dustinnation.com/lightning-talk-on-firebase-and-marionette/</link><guid isPermaLink="false">49d124f7-bb80-42b3-b72c-cf57768a6b7c</guid><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Mon, 03 Mar 2014 07:52:00 GMT</pubDate></item><item><title><![CDATA[Highcharts Beyond-Extremes Plugin]]></title><description><![CDATA[<p>Its been awhile since I've posted anything here. I'll spare you the excuses. I'm still working on the Firebase-Marionette tutorial, and its coming along nicely...but slowly.</p>  

<p>As I've alluded to previously, the main project I'm currently working on is an energy/building performance application. One of the requirements is a dynamically populated, interactive chart for historical values of different building parameters (ie room temperatures, heating/cooling modes, etc). The charting library we chose to use for this is called <a href='http://www.highcharts.com/products/highstock'  target="_blank">Highstock</a>. It is a specialized version of the <a href='http://www.highcharts.com/products/highcharts'  target="_blank">Highcharts</a> library that provides a "preview" slider below the actual data, allowing a user to change the date range by sliding some handles around.</p>  

<hr />

<h2>The Problem</h2>  

<p><span>Out of the box Highstock does much of what I need it to extremely well and very easily, but it feels like its still trying to make the transition from a static "generated once" chart to something that can easily handle interactions such as adding and removing series on the fly and adding data to series that are currently charted. &nbsp;They have some helper functions that approach these things, but they don't quite address my requirements, so as I encounter needs like these, I end up writing work-arounds.</span></p>  

<p>I currently default all of my charts to start with 30 days of data. However, users frequently need much larger time ranges. I wanted to set up a system where the user puts in a different date and the app determines if it needs to go get more data. Unfortunately Highstock's date-range input validates the user input against the range extremes in the data to make sure the input isn't outside of the current data's date range. This means that if if my chart currently starts on and has data starting on October 10th, inputting October 1st would not pass validation and nothing would happen. Bummer.</p>  

<p>So I asked around in their forums and on <a href='http://stackoverflow.com/questions/19694258/highstock-change-range-input-beyond-the-data-max'  target="_blank">Stack Overflow</a> and was basically told to edit the Highstock source code. It wasn't hard to find the part that needed to be changed and only 2 lines needed 6 words commented out, but if I edit their source it puts me in charge of maintaining that source going forward.</p>  

<hr />

<h2>The Solution</h2>  

<p>Luckily Highcharts has some fairly decent documentation on how to make a plugin! So that's what I went about doing.</p>  

<p>It was pretty straight-forward, but I did have to do a lot of learning about the context that the plugin code runs in. I basically copied the original code that I'd have had to modify out of the source and into the plugin. I made my changes (commenting out like 10 words) and set about figuring out how to get all of the variables in that code defined by the variables accessible to code in the plugin.</p>  

<p>Here's the result!<br />Highstock plugin repo:&nbsp;<a href='http://www.highcharts.com/plugin-registry/single/12/Beyond-Extremes' >http://www.highcharts.com/plugin-registry/single/12/Beyond-Extremes</a><br />Github page:&nbsp;<a href='https://github.com/d-nation/highstock-beyond-extremes' >https://github.com/d-nation/highstock-beyond-extremes</a></p>  

<hr />

<h2>Final Thoughts</h2>  

<p>I'm not a Highcharts expert, nor am I a plugin guy, but I was presented with the option of taking on a maintainer role for our own version of Highstock, or to write a plugin to augment the original source. With just that criteria it was an easy choice, but when I added in the fact that I could publish it and help out other developers...no brainer.</p>]]></description><link>http://blog.dustinnation.com/highcharts-beyond-extremes-plugin/</link><guid isPermaLink="false">98455f2c-1dab-4fb6-aac1-49a5dcbf9194</guid><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Thu, 07 Nov 2013 04:08:00 GMT</pubDate></item><item><title><![CDATA[Real-Time Web App Notifications via Firebase and MarionetteJS]]></title><description><![CDATA[<hr />

<h2>The Problem</h2>  

<p>Recently at work we had the need for a real-time notification system. When an event in our system fires, our users need to be alerted live and be able to clear the notifications when they'be been addressed. The problem is&nbsp;that we're a small shop under a time crunch. The other two developers on the team were busy, leaving me to worry about both the back-end and the browser.</p>  

<hr />

<h2>The Solution</h2>  

<p>Enter <a href='https://www.firebase.com/'  target="_blank">Firebase</a>. I'm probably going to butcher this and/or sell them short, but... Firebase is a No-SQL database as a service. They offer both REST and websocket interfaces along with full blown security features. Best of all...they maintain a Backbone extension called <a href='https://github.com/firebase/backfire'  target="_blank">Backfire</a>!</p>  

<p>Backfire is basically a drop in replacement for Backbone Collection that establishes and maintains a connection to the Firebase database of your choosing. Any changes to the database are automatically reflected in the collection and vice-versa.</p>  

<p>That sounded like a pretty good match for the Marionette Collection View. Turns out...it is the perfect marriage! &nbsp;I was able to implement a solution in about 5 hours, even though I'd never used Firebase/Backfire before!</p>  

<p><em>Note: It would've been much quicker, but I had some trouble dynamically specifiying the Firebase I wanted Backfire to point to. &nbsp;I'll cover it in the tutorial so fear not!</em></p>  

<h3>Nitty Gritty</h3>  

<p>I'm also preparing a tutorial with a sample app, so I won't get into much code detail in this post. I will however, go over the system architecture I used to implement the real-time notification system.</p>  

<h4>Environment</h4>  

<ul>  
<li>Backend: Python running in AWS</li>  
<li>Web-framework: MarionetteJS</li>  
</ul>  

<h4>Flow</h4>  

<ol>  
<li>A notification is sent from the system to my firebase processing code (Documentation)</li>  
<li>My Firebase processing code sends a REST call to Firebase</li>  
<li>Firebase adds the data from the REST call to the database</li>  
<li>Firebase syncs the new data with any listeners (any connected Backfire collections)</li>  
<li>Marionette's Collection View knows that there's a change and renders the added notification</li>  
<li>A user clicks on the "clear button" which removes the model from the Backfire collection</li>  
<li>Backfire syncs the deletion with Firebase</li>  
</ol>  

<h4>Diagram</h4>  

<p>I felt like drawing, so here's the above flow in picture form...</p>  

<p><img src='http://blog.dustinnation.com/content/images/2014/Mar/Notification_Firebase_MarionetteJS.png'  alt="" /></p>

<hr />

<h2>Final Thoughts</h2>  

<p>This combination was a real time-saver. The amount of total code required to make real-time changes show in your web app is ridiculously low.</p>  

<p>Stay tuned later this week for a tutorial...</p>  

<p><strong>3/3/14 Update:</strong> this tutorial is still in the works...sorry. But I'm giving a talk on it on 3/6/14 at the DallasJS meetup.</p>]]></description><link>http://blog.dustinnation.com/real-time-web-app-notifications-via-firebase-and-marionettejs/</link><guid isPermaLink="false">4b00ad38-2604-4a59-8770-87d4545f7409</guid><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Tue, 01 Oct 2013 02:07:00 GMT</pubDate></item><item><title><![CDATA[Modification to my Marionette Module Minions]]></title><description><![CDATA[<hr />

<h2>The Background</h2>  

<p>In a <a href='http://blog.dustinnation.com/making-marionette-modules-into-my-minions/'  target="_blank">previous post</a> I talked about how to make MarionetteJS modules into little reusable apps for use within your big app. However, whilst using this at work I realized that there was something missing.</p>  

<hr />

<h2>The Problem</h2>  

<p>One of the ways I'm using modules like this is with a configuration modal. The configuration can be a new configuration, or it can be an edit to an existing one. The module that is starting up the configuration module already has all of the information that will be needed to edit a particular configuration, it just needs to get it into the freshly started module.</p>  

<p>Following? I'm not sure even I am.</p>  

<p>Let me try again.</p>  

<p>Sometimes I need to pass info to a module when its starting up that may change by the next time the module is started up again.</p>  

<hr />

<h2>The Solution...or so I thought</h2>  

<p>Well, here's where I admit to a mistake. The <a href='https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.application.module.md' #module-definitions" target="_blank">documentation</a> says you can pass in "any custom arguments" so I tried to do this:</p>  

<p dir="ltr"><strong>module1.js</strong></p>

<pre><code class="`language-javascript">define(['marionette', 'mainLayout'], function (Marionette, MainLayout) {  
    "use strict";

    return function(Module1, App, Backbone, Marionette, $, _, options ){
        ...
        this.addInitializer(function(){
            //Do something with the options here, like send them to the layout
            Module1.regions.main.show(new MainLayout({options: options));
        });
        ...
    };

});
</code></pre>

<p>And then start it up like this (in <strong>App.js</strong> or in another module)</p>

<pre><code class="`language-javascript">var options = {config: some_pre_determined_configuration};  
App.module(name, functionDef, options);  
</code></pre>

<p>Technically this works, but not the way I thought. I was thinking that I could pass in arguments every time I started it back up. Turns out that the module only gets the options the first time the "App.module" method is called on the definition function.</p>  

<p>Maybe I should've read the docs a bit more closely, because I couldn't figure out why the options I was sending in on the 2nd and 3rd times weren't there.</p>  

<hr />

<h2>The (real)Solution</h2>  

<p>To get around this, I turned to a new old friend: RequestResponse.<br />I created a "moduleOptions" object in the parent who's doing the starting up the modules. &nbsp;It will hold any information that any of my modules may need for the next time they start up.</p>  

<p>In <strong>App.js</strong> or in another module that is calling a minion</p>

<pre><code class="`language-javascript">App.moduleOptions = {};  
</code></pre>

<p>Then I setup request handlers as a "getter" and a "setter" for moduleOptions</p>  

<p>In <strong>App.js</strong> or in another module that is calling a minion</p>

<pre><code class="`language-javascript">reqres.setHandlers({  
    setModuleOptions: function(moduleName, options){
        App.moduleOptions[moduleName] = options;
    },
    getModuleOptions: function(moduleName){
        return App.moduleOptions[moduleName];
    }
});
</code></pre>

<p>As you can see, both handlers require a module name. &nbsp;This is in case you have multiple modules that need options. &nbsp;It prevents you from having to explicitly define a new variable under App every time you add a new module type. &nbsp;Instead they just get thrown under App.moduleOptions, keeping your App code nice and clean.</p>  

<p>Ok, so now that I've got a way to set the module's start up options and tell it about those options, I just have to make the module ask for them when he/she starts up.</p>  

<p><b>Module1.js</b></p>

<pre><code class="`language-javascript">this.addInitializer(function(){  
    ...
    Module1.startOptions = reqres.request('getModuleOptions', "Module1");
    ...
});
</code></pre>

<p>I typically don't like to manually put in "Module1" as the argument in case I decide to change the name of the module. &nbsp;So I pass in Module1.moduleName instead of "Module1". &nbsp;The less I have to change when I make a change, the better.</p>  

<h4>Full Examples</h4>  

<p><strong>App.js</strong></p>

<pre><code class="`language-javascript">define( ["marionette", "module1”, “app_reqres”], function (Marionette, Module1, reqres) {  
 "use strict";

    var App = new Marionette.Application();
    App.moduleOptions = {};

    //These could be called directly in App.js, but I'm using the reqres
    //to show how one might start another minion from a module.
    reqres.request("setModuleOptions", "Module1", {
        version: "version#",
        regionContainer: ".module1-##" //substitute ## for a unique identifier. I just use an auto-incremented counter
    });
    reqres.request("startModule", null, "someName", Module1);

    App.infoToShare = “Share Me”;

    reqres.setHandlers({
        startModule: function(parent, name, functionDef){
            //Handle sub-modules
            if(parent != null){
                App[parent.moduleName].module(name, functionDef);
            }
            //Handle top-level modules
            else{
                App.module(name, functionDef);
            }
        },
        getInfo: function(){
            return App.infoToShare;
        },
        setModuleOptions: function(moduleName, options){
            App.moduleOptions[moduleName] = options;
        },
        getModuleOptions: function(moduleName){
            return App.moduleOptions[moduleName];
        }
    });
});
</code></pre>

<p><strong>Module1.js</strong></p>

<pre><code class="`language-javascript">define(['marionette', 'app_reqres', 'mainLayout'], function (Marionette, app_reqres, MainLayout) {  
    "use strict";

    return function(Module1, App, Backbone, Marionette, $, _){
        this.addInitializer(function(){
            var rm = new Marionette.RegionManager();

            Module1.startOptions = app_reqres.request('getModuleOptions', Module1.moduleName);

            this.regions  = rm.addRegions({
                main: Module1.startOptions.regionConainer
            });

            Module1.regions.main.show(new MainLayout());
        });

        this.addFinalizer(function(){
            Module1.regions.main.close();
        });
    };

});
</code></pre>

<hr />

<h2>Final Thoughts</h2>  

<ul>  
<li>I totally get now why it didn't work the way I thought it would.</li>  
<li>Wreqr makes me happy.</li>  
<li>When all else fails, read the docs a little closer.</li>  
</ul>]]></description><link>http://blog.dustinnation.com/modification-to-my-marionette-module-minions/</link><guid isPermaLink="false">f5404e3e-0236-425e-9a9a-07480c676e3a</guid><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Dustin Nation]]></dc:creator><pubDate>Mon, 23 Sep 2013 10:07:00 GMT</pubDate></item></channel></rss>