Generating Menus in OSX Apps - the Ruby way!

A few months ago I made the decision to convert my Mac app from Objective-C to RubyMotion. It's a status-bar app, which means that the primary user interface is a menu, not a window. I quickly ran into issues with the generating menus in code and got quite fed up.

I've now solved most of my problems with my new gem Drink Menu; today I want to explain my motivations and show you a working code example. Finally, I'd like to ask for your help making it even better.

Motivation

Menus were made to be built in Interface Builder. If you've ever tried to code one, you'll understand that. But I was made to work at the command-line in Vim. For me visual tools like IB are for rapid prototyping, but when I'm ready to commit I want to manage the UI in code, provided I can do it in a reasonably sane way.

For window-based UIs we have Teacup, a RubyMotion library that enables separating window creation from styling/layout. If you haven't seen it, I highly recommend taking a look, it's great for extracting those properties you have to set over and over again (ever tried to create a basic label?)

For menu-based UIs, we have this. That's the code RubyMotion generates for you when you create a new Mac app. It's exactly the same menu that you get in a new Cocoa app with Xcode. This is a nice wrapper around the Cocoa APIs for generating menus, and since it uses blocks it looks very Rubyish.

But the first time I needed to generate items from a collection (and update the menu when new items are added), or use an NSStatusItem it became more complicated. I really needed something a little more powerful.

Also, I've never liked the Cocoa pattern of passing a selector to execute when an action occurs. It leads to what I like to "entry-point hell"; you know, that special situation where your classes a bunch of entry-point methods, and you have to find where it's being used as a selector to find out what happens. These methods are difficult to test and makes the code a little harder to understand on a quick read (those who geek out about this stuff should read about connascence).

And there's another problem with this code. One of the things I like about teacup is that it separates the layout/style of a view from the creation of its controls, along with a DSL for specifying all of that. So I can create a generic "stylesheet" to cover different style/layout use cases, and then relate controls to those styles. This ultimately leads to much easier to maintain view code. How can we get a similar separation for our menus?

Today I'm proud to show you my initial stab at solving these problems with menu code. It's a gem called Drink Menu. It provides methods to create menu items and then gives you a nice DSL for laying out the menu items in an actual menu. Then in your AppDelegate you can subscribe to menu item clicks with a block, rather than relying on selector matching to figure out what's going on. It also generates menus from collections, and keeps them up-to-date as you add items.

Basic Example

Here is the code to generate a basic main menu for an app. You can run this code by cloning the Drink Menu repo from Github and running example=basic_main_menu platform=osx rake.

You create items using a few different factory methods, and then you refer to those items by their label when you create the menu. The block for creating a menu is a visual representation of the actual menu. To reorder items, just move them up and down in the block. To create a separator use the ___ (that's 3 underscores) method.

I'll let that sink in and follow up soon with examples for how to do status menus and bind to collections.

Call to Action

The ideas here are still young. It's ready to use in any Mac app, but I know there are use cases I'm not covering. Do you feel the same pains I do? Would you use this in your OSX RubyMotion apps today? If not, what would you change to make it more useful? Please feel free to hit me up on Twitter or via email if you have questions or feedback.

Permalink

Published on by Joe Fiorini.

Implementing a Functional-Reactive Search UI with Bacon.js

Most event handling code exists to do some work based the state of the system at that time. Usually we call out to other objects to make Ajax requests, UI updates, etc.

The problem is that these event handlers usually take some time to understand what each line is doing. Responding to an event usually involves at least two or three actions, yet we do it all in one function.

What if our code could make this clear by saying "when E happens, do X, then do Y and then Z"? This is the problem that Functional Reactive Programming (FRP) solves.

Event Streams

An Event Stream is a wrapper around an event with a similar publish/subscribe mechanism. Every event that happens in your system has some sort of value associated with it: DOM events have the Event object and Ajax events have a response. Event streams allow you to subscribe to different events and respond to them all in a uniform way.

Bacon.js provides a great JavaScript implementation of FRP and Event Streams, and (bonus!) it plays nicely with jQuery.

Binding to click/keyboard events

Our search is kicked off by a button click. We bind to the button's click event by using Bacon's built-in $.asEventStream. This will convert any jQuery event binding to an event stream. So we can bind to click using

    var clickStream = $("button").asEventStream("click");
    clickStream.onValue(function(){
        // onValue is the actual event binding
    });

But we also want the user to be able to press enter. Typically this would require something ugly like:

    $("input:text").bind("keyup", function(e){
        if(e.keycode == 13){
          doStuff();
        }
    });

Instead with Bacon, we can combine multiple streams and subscribe to all of them at once with:

    Bacon.mergeAll(clickStream, enterKeyStream).onValue(function(value){
        doStuff(value);
    });

Making an Ajax Request

If you need to do an extremely simple Ajax request and do nothing with the return value, you can do something like this:

    $("button").asEventStream("click").map(function(){
        return $("input:text").val();
    }).onValue(function(searchTerm){
        return $.getJSON("/search?q=" + searchTerm);
    });

Of course, this isn't extremely useful. Bacon.js has a few utility functions for creating Event Streams from asynchronous calls. In this case we can use the lovely Bacon.fromPromise, which takes a function that returns a promise and calls its subscribers every time that promise resolves. Since all of jQuery's ajax helpers return promises we can wrap our ajax call in a special function like:

    function ajax(query){
        return Bacon.fromPromise($.getJSON("/search?q=" + value));
    }

Then subscribe to it just like any other event stream:

    ajax("blah").onValue(function(data){
        renderResults(data); // do something with the response now
    });

Event Streams allow us to compose anything asynchronous; be it DOM events, custom events or Ajax requests. They are the great equalizer. How do we go from a stream of user interactions to an ajax request though? So far we've been combining mostly with .map, let's try it with our ajax function:

    clickStream.map(extractSearchTerm).map(ajax).onValue(function(value){
        // what is value?
    });

It turns out if we do it this way, value is just our ajax event stream, which means our subscriber would look like:

    clickStream.map(extractSearchTerm).map(ajax).onValue(function(value){
        value.onValue(function(value){
            renderResults(value);
        });
    });

This works, but YUCK! We're trying to get away from nested callbacks, right? If only there was a way to take the stream that gets returned from ajax() and automatically subscribe to it within the current stream. This is exactly what the flatMapLatest helper does. Using flatMapLatest we'd have:

    clickStream.map(extractSearchTerm).flatMapLatest(ajax).onValue(function(value){
        renderResults(value);
    });

Adding a Spinner

Usually adding an Ajax spinner means inserting something into the DOM at the start of an Ajax request, and removing it when the request completes. The simplest way to do that would be to show the spinner at the start of the stream and hide it at the end.

So far we've used map to combine our streams, but showing/hiding a spinner doesn't give us a value to pass on. Instead, we can use Bacon's doAction helper that takes a function, subscribes it to the current stream and then returns that stream. When the ajax call complets, it passes the response to the next subscriber in the chain. It looks something like:

stream.doAction(showSpinner).
    flatMapLatest(ajax).
    doAction(hideSpinner).
    onValue(...);

Putting it all together

I've included a jsbin at the end of this post that shows all of this put together in a working demo. This style is useful for more than just browser apps; I'm using ReactiveCocoa for the UI of my menu bar-based static site generator Staticly. Using FRP it's much easier to see exactly what's happening when, which removes a lot of the pain of maintenance.

What do you think? Does this sound useful? Is there more you'd like to see done in this style? Hit me up on Twitter, App.net or via email with your thoughts.

Permalink

Published on by Joe Fiorini.

Custom Models in Ember.js

Like Adam says, Ember-Data is pre-alpha software. Some projects may not allow the time needed to debug, file issues and dig through an unfamiliar codebase. But Ember.js is much more stable and ready to use. So the problem becomes, without Ember-Data, how to put the M in MVC?

You could use plain-old Javascript objects. But Ember provides such a rich object model, coupled with live-updating templates, you'd be stupid not to take advantage of it. Fortunately, writing a very simple custom base model that plays nicely with its observer-based templates is not very difficult.

In order to write your own base model, you need to understand that Ember's live-updating is not magic. It's based on always working with the same object references at all times. Therefore we make heavy use of caching via Ember.Map.

We will also make use of a Promise to allow more flexible ajax requests. To ensure we process API responses asynchronously we'll resolve the promise inside an Ember run loop.

The example below shows a base model and an example usage. It populates the model using a real API and displays data via an implicit controller and view.

Permalink

Published on by Joe Fiorini.

My Top Go-To Ember Resources

Gut intuition is a developer's most important resource. Instinct is what tells you that rendering a blank page means your route's promise isn't resolving, or that a controller is getting too big and needs to be split out into multiple objects. The catch is, the only way to develop a trustworthy gut is through building understanding and gaining experience.

Developers new to Ember often take the logical next step and start weeding through a ton of online content in hope of finding reliable resources to boost their learning. Hopefully this article will make that process less painful. I've created a list of the Ember resources I turn to most often, but more importantly I explain how and why I use them. Understanding how to dig in and get dirty is the best way to grow your gut intuition.

API Docs

The Ember.js API documentation will tell you exactly what the Ember codebase provides. Most classes will give some detailed usage instructions and examples. If you need more information than the docs give you, everything links directly to its implementation on Github.

I use the API docs a lot. Mostly it's just to look up what methods are available on an object but it was also useful to differentiate between different array observer callbacks such as arrayContentDidChange and enumerableContentDidChange. I also learned that an ArrayController is just a fancy ArrayProxy by reading this documentation. There are a few things that sorely need documentation, but it's still a resource to keep close at hand.

Github

Github is to code what the public library system is to books. It is not only a great place to publish source code, but also to read code written by others. It contains some mechanisms to discover code in a way that was previously impossible. For example, if you want to see some examples of writing Ember routes search for Ember.Route and filter to "Code" results.

I don't just search on Github though. There are a few repositories I jump to when I'm looking for something specific. For example, I have a project with some custom models. To get a better idea of how to write models for Ember, I looked at Erik Bryn's ember-model library and Discourse for examples. Also Erik's Backburner.js can help you better understand how the run loop works.

JSBin

JSBin is an app that lets me create a single web page quickly without littering more files around my filesystem. I can quickly drop in HTML, SCSS and Javascript (or CoffeeScript) using their online editor and then interact with the page immediately. It even lets me choose from a myriad of JS & CSS libraries (unless you want to keep up on Ember releases) to drop into my HTML page. No more futzing around with creating files or downloading dependencies just to create a small example.

When I'm trying to solve a problem with Ember, and just can't get it working, JSBin is often my savior. Provided I can quickly think of a simplified example of the problem I'm trying to solve, I can code it up in no time with JSBin and share it with others to try to get help. For example, I created this JSBin to try out Adam Hawkin's GroupableMixin with constantly changing data. JSBin can also be useful when trying to determine if a problem is a bug in Ember or in your code; if you open an issue, it's likely someone will ask you for a JSBin.

JSBin is not great at keeping up on Ember releases. To get around this I link directly to releases from http://builds.emberjs.com and upgrade as necessary.

Misc

Besides the resources mentioned above, there are a few blog posts I reference now and then that have helped me learn some of the more complex things about Ember.

Everything You Never Wanted to Know About the Ember Run Loop

The run loop is central to Ember's power, but to understand it you also have to understand the benefits and drawbacks of async programming. I highly recommend reading this once you understand the parallel between setTimeout and threaded programming (I did not when I first started with Ember, and until I did, the run loop was endlessly confusing).

Performance Testing Views in Ember.js

This post shows how to use the little known, and scantly documented Ember Instrumentation module to check how long it's taking your views to render. It's worth a quick read, but after reading I'd recommend looking through the source for Ember.Instrumentation. I learned some nice tricks for debugging performance issues looking at that code (see console.time).

Render, Control, Partial, View, Template

Ember has a few different helpers for getting templates into your page. They each work differently in subtle ways. It's important to know which to use when, and this post does a great job differentiating them.

As you go through the process of learning Ember, you will likely get frustrated at points. UI development at this level is a very different beast from the server-side coding many of us are used to. Using the resources here (and the many others I didn't have time to write about) you will eventually build an instinct that you can rely on.

Permalink

Published on by Joe Fiorini.

User-friendly live collections in Ember.js

What is a live collection?

Demo

You need to display a fairly large list of data, say for example a list of tweets returned from a Twitter search. There will be new results every few seconds; do you really want your users to refresh your site every time they think there's new results? Not only would that be a bad user experience, it could wreak havoc on your server resources.

Instead let's use the magic of Javascript to rerun the Twitter search for the user on a regular basis. Using Ember.js we can search over and over again and watch the UI update every time we get new results.

In this article we'll see how we can leverage the strengths of Ember.js bindings to detect when new search results are available and display them without providing a jarring experience for the user.

User-friendly?

Like any other cool idea, this one has already been done by Thomas Reynolds. In his blog post, Thomas walks through building a Twitter search that updates every 2 seconds. As new tweets come in, they get added to the end of the list.

This is a great example, but I think we can improve the user experience here. First off, I'd like to see the most recent tweets at the top at all times. Of course, that means when new tweets arrive, the list would push down to make room for the new ones. This could lead to a pretty bad user experience if I search for a popular term.

Let's take this example a little further and improve the UI. Instead of displaying new tweets as they come in, we'll queue them up and display a prompt letting the user know that they have new results waiting for them. Then, we can wait to load them in until the user has indicated they are ready to view them (just like twitter.com does today).

Searching for Tweets

Let's assume we have a model, called App.Tweet that can search for tweets containing given keywords and hydrate a collection of App.Tweet instances with the properties of each tweet.

First, we perform a search for the hashtag "#flickr" in our route.

App.ApplicationRoute = Ember.Route.extend({
model: function(){
return App.Tweet.find("#flickr");
}
});

We'll need a controller to keep the collection of tweets, sorted by most recent first, for the view.

App.ApplicationController = Ember.ArrayController.extend({
sortProperties: ["created_at"],
sortAscending: false
});

It would be nice to format the tweets' timestamp similarly to Twitter (15 minutes ago, 1 hour ago, etc). Let's decorate the tweet model with an itemController and use moment.js to format the date.

App.ApplicationController.reopen({
itemController: 'tweet'
});

App.TweetController = Ember.ObjectController.extend({
formattedTimestamp: function(){
return moment(this.get("created_at")).fromNow();
}.property("last_updated_at")
});

Finally, we'll need a template to display the tweets. I'm using an extremely basic list to show the username, content and timestamp.

  <script type="text/x-handlebars">
<h1>Items</h1>
{{#if searchTerm}}
<p>Searched for {{searchTerm}}</p>
{{/if}}
<ul>
{{#each tweet in controller}}
<li>
<h3>{{tweet.from_user}}</h3>
<em>{{tweet.formattedTimestamp}}</em>
<p>{{tweet.text}}</p>
<small><em>({{tweet.id}})</em></small>
</li>
{{/each}}
</ul>
</script>

Live-updating the Results

Now that we have some search results displaying on the page, let's make them live-update. To do that, we're going to poll the Twitter search API at a set interval. Any time we get new results we'll call a refresh function on our model to add the new results to the array.

Polling like this is incredibly simple in Javascript, in its most basic form.

// Poll for new tweets every 5 seconds
setInterval(function(){
App.Tweet.refresh();
}, 5000);

Doing this with other APIs can get expensive, especially if you have a rate limit. Being able to disable polling can be extremely useful while you are debugging your app. Therefore, I like to wrap setInterval in a Javascript object that can handle starting and stopping the poll.

App.Pollster = {
start: function(){
this.timer = setInterval(this.onPoll.bind(this), 5000);
},
stop: function(){
clearInterval(this.timer);
},
onPoll: function(){
App.Tweet.refresh();
}
};

As users navigate around our app, we probably want our pollsters starting/stopping depending on what data the current route needs. In this case we have only one route so we can simply start the pollster when the route activates and stop it when the route deactivates.

App.ApplicationRoute.reopen({
activate: function(){
App.Pollster.start();
},
deactivate: function(){
App.Pollster.stop();
}
});

We now have a route that performs a Twitter search and populates an array controller with the search results. We have an item controller to decorate each tweet with a nicely formatted timestamp and then we display the tweets in a template. And of course, our results are automatically updated every 5 seconds.

But this isn't the user experience we want. Instead of pushing new tweets to the user, we want to queue them up and let the user choose when to load them in. For that, we'll have to use some of Ember's array observing magic.

Queueing Controller Content

The Power of Array Observers

To queue up new search results as they come in, we need to listen for array changes. New items get added to the model's array on almost every poll. When this happens, Ember triggers a chain of observers that work their way up through the controller and result in rerendering templates. One such observer is the array controller's content array (the same one that gets set in your route's setupController callback using controller.set("content", model);).

To detect when new items have been added, we're going to use the contentArrayDidChange callback on our controller. This will be called anytime changes are made to the structure of the content array (ie. items added, removed). This is an important distinction as there are other callbacks for different situations.

App.ApplicationController.reopen({
contentArrayDidChange: function(array, start, removeAmt, addAmt){
// do something to respond to this change
return this;
}
});

Let's talk about what's going on in the above code snippet. We declare a controller as an Ember.ArrayController. This actually makes our controller a child of Ember.ArrayProxy, which is a wrapper around native arrays with some special properties for observing changes to the array and its elements.

The callback contentArrayDidChange will be called whenever items are added to or removed from the instance's content. It gets the new array, the index at which the changes started, the number of elements removed and the number of elements added, respectively.

We can then use these parameters to create a separate array containing only new tweets; a "queue" if you will.

// snip...
contentArrayDidChange: function(array, start, removeAmt, addAmt){
var queued = [], added;
added = array.slice(start, start + addAmt);
added.forEach(function(item){
queued.push(item);
});
}
// ...snip

The above snippet is a naive implementation of queueing tweets for display. Since start is the index where the additions began, we can added addAmt to that to get the index where they end. Using Array#slice we'll get a new array containing only the added tweets. Then we can push each one onto our new array called queued.

Of course, this assumes that we'll add new tweets with every change. It's possible, however unlikely in this case, that our content array will change without any tweets being added. In that case, our final version will make sure we have added items.

The other problem with this implementation is that we're not saving the queue between changes. We'll need to add a property to our controller to hold onto the queue results until we're ready to display them.

App.ApplicationController.reopen({
queuedContent: function(){
return Ember.A();
}.property(),
contentArrayDidChange: function(array, start, removeAmt, addAmt){
var queued = this.get("queuedContent"), added;
if(start >= 0 && addAmt > 0){
added = array.slice(start, start + addAmt);
added.forEach(function(item){
if(!queued.contains(item)){
queued.pushObject(item);
}
});
}
return this._super.apply(this, arguments);
}
});

Filtering Array Content

Now we can call get("queuedContent") on our controller any time we want to get at the queued tweets! Of course, this seems pretty much useless, since our goal is to hide new tweets, not display them. Ah, but now that we know which tweets are queued, we can use that to filter them out of the tweets we want to display. How about we create one more property for that?

App.ApplicationController.reopen({
displayableContent: function(){
var queued = this.get("_queued");
return this.reject(function(obj){
var candidate = queued.findProperty("id", obj.get("id"));
return (typeof candidate !== "undefined" && candidate !== null);
});
}.property("queuedContent.[]"),
});

To get the tweets that we want to display, we're filtering down to only those that are not in the queue. Or, to say it as this function is written, we're rejecting any tweets that are in the queue.

Since this computed property observes queuedContent.[], any time items are added to, or removed from queuedContent, this property will update (if we just observed queuedContent without the [] it would only respond to a call to this.set("queuedContent", ...).

Let's look at what we have so far. We can search for tweets and poll for updates to the search results. We have a template that displays the search results and updates automatically as new ones come in. But they are getting pushed to user immediately, which is not what we want. Let's update our template to use our new displayableContent property.

{{#each tweet in displayableContent}}
<li>
<h3>{{tweet.from_user}}</h3>
<em>{{tweet.formattedTimestamp}}</em>
<p>{{tweet.text}}</p>
<small><em>({{tweet.id}})</em></small>
</li>
{{/each}}

So now we're hiding new tweets, but how do we notify the user as they come in? Let's add a couple properties to our controller to tell us if there are any queued tweets and how many.

App.ApplicationController.reopen({
queueCount: function(){
return this.get("queuedContent.length");
}.property("queuedContent.length"),
hasNewTweets: function(){
return this.get("queueCount") > 0;
}.property("queueCount"),
});

More Observer Goodness

When the user is ready to load in all the queued up tweets, we'll need a way to update the UI. Typically we'd have to iterate over our queue and manually insert each item into the DOM. But this is Ember.js. Thanks to the observer chain we have setup, updating the UI is as simple as emptying out our queue.

App.ApplicationController.reopen({
unqueueAll: function(){
this.get("queuedContent").clear();
}
});

What!? How could it possibly be that easy? Since our displayableContent computed property observes queuedContent.[], when we clear the array it will cause displayableContent to update. Since queuedContent is now empty (or, put simply, we have no more queued tweets), displayableContent is now a collection of all the tweets. Our template has an observer (thanks to Ember's {{#each}} helper) on displayableContent and will update whenever it changes.

Now let's update our template to show the number of tweets that are queued. We'll also add a button to load them in using the unqueueAll action.

{{#if hasNewTweets}}
You have {{queueLength}} new tweets.
<button {{action unqueueAll}}>Load</button>
{{/if}}

Conclusion

Well, there you have it. A user-friendly, live updating collection written in Ember.js. If you found any part of this article confusing, I highly recommend reading it a couple times and looking up any methods you don't know in the Ember API docs or by searching the source code (for example, the contentArrayDidChange method is not in the API docs but is well-commented and tested).

Ember.js can be quite overwhelming at first, but as you start to grasp its heavy use of the observer pattern, it becomes a lot less magic. Once you start letting your framework handle the heavy-lifting of model-observing and DOM updating, you can focus more on building the best UI for your users.

As always, feel free to hit me up on Twitter or App.net with any questions or feedback.

Permalink

Published on by Joe Fiorini.

Developer as Designer

I am a designer. You can see some of my designs on Dribble. But I started out as a developer; you can see my work on Github. Back then I was lucky enough to work with some great designers. Their designs looked nice and always met our users’ needs.

But these designs were always really hard to implement. I didn’t have the experience then to understand the real problem, so instead I told myself: “if I was a designer I could always make easily realized designs, because I know programming”.

When I got my opportunity to prove it, I was determined to always keep implementation in mind. My designs would be easy to build, dammit.

Instead, I learned that my time as a developer would come in handy in a much different way.

My first project as a designer was a website redesign for a rather large client. I started with a wireframe for their page of industry award winners (it was a big site). When I sat back and looked at my design I thought “well, isn’t this plain”? Seriously, it was boring, difficult to navigate, not at all what a good design should be.

What the hell do I do now? Maybe if I let go of the implementation just a little bit I could come up with something better. Besides, I thought, I can always think through how to build it out after I mock it up.

That's when the past came back and smacked me in the face: the real problem of my experience with those designers. We couldn’t question constraints because we didn’t identify the risks until it was too late. With enough planning, couldn’t we push back a deadline or change some technical architecture to make a feature reality? But the designers couldn’t spend all of their time designing within development constraints. If they did that, we’d never know what is possible.

From then on I naturally found myself going through phases of sketching and gut-checking against constraints, followed by more sketching then more gut-checking. And when I’m out of my programming element I take my sketches to a real developer to help me confirm what I’m thinking. At no time do I wear both designer and developer hats at once.

So, next time you’re designing think about when it might be a good time to show it to a developer. The sooner you can identify the risks of breaking set-in-stone constraints the sooner you can take a step back and rethink your designs if necessary. If you wait until you’re done with Photoshop then it’s already too late.

Permalink

Published on by Joe Fiorini.