Bloggity Blog

We love our work so much, we want to tell the world about it.

Welcome Ricardo Thompson!

Written by Matt Sears

It is my great pleasure to introduce Ricardo Thompson as our new Creative Director. Ricardo is a 2004 graduate of the School of Advertising Art, where he's been teaching Web and Interactive design for the past 5 years. Ricardo brings 10 years of design experience to the team and we're super excited he's joined Littlelines. Follow Ricardo on Twitter and on Dribble.

Welcome aboard Ricardo!

My Approach

I love writing Ruby and I love using Rails. So when I started looking for a client-side framework to help organize my front-end process and code, I was cautious of frameworks that demanded I abandon my "Rails Way" and adopt their process, style, and approach. I was looking for a framework that added value to my "Rails App", not a solution that wanted Rails to instead act as a compliment to my client-side app.

Enter Angular stage left.

But wait, you say, tons of Angular apps use Rails (or any other framework) as a backend api for their purely client-side application. Yes, you would be very correct, however, unlike numerous other client-side frameworks, Angular allows me to easily and quickly sprinkle it on top of my traditional Rails app if that's my preference.

CAVEAT - This article is only meant to demonstrate how I stayed a happy, healthy Rails developer while still enjoying all the advantages Angular provides. If, in your heart, you want nothing more than to make purely client-side apps every day, then more power to you for being focused. Thanks for reading this far - and please accept my token of thanks.

My happy-place with Angular and Rails is to let each framework do what it's good at and then move aside. For Rails, it is well suited to handle routing, helpers and primary application logic. For Angular, it is best suited to handle client-side interactions, dynamic bindings, ajax requests and presentation logic. Using this approach I can stay away from so many headaches caused by Angular routing, Rails remote linking and endless arbitrary jQuery listeners.

Once I had settled on an approach to co-existence of Angular and Rails, my next obstacle was the somewhat verbose and obscure Angular syntax.

CoffeeScript Sanity

Personally, I love using CoffeeScript (through that is in no way required to enjoy Angular on Rails) and my first step in incorporating Angular into my daily Rails flow was to get a handle on some of the more obtuse Angular syntax in favor of the CoffeeScript class approach.

The first step was to create a base class (NGObject) to handle basic dependency injection. This class iterates through the array of dependencies passed via the class @$inject variable and creates an instance variable with the same name. This gives us the ability to easily reference scope, services, etc passed into our angular object by friendly means (@scope, @Thing, @ThingSvc, etc). Once the dependencies are handled, the NGObject class will check for an init() function and call it if one exists.

class @NGObject
  constructor: (dependencies...) ->
    for dependency, index in @constructor.$inject
      @[dependency.replace('$', '')] = dependencies[index]

Next, I use that NGObject base class to build a variety of other classes to handle specific angular object types such as NGController, NGService, etc. Each of these classes exposes a register function that wires up our object to the correct angular application. During object construction, we take the attributes of a given object (controller, service) and apply them to the proper scope. This allows us access to the attributes and functions of any object in the view layer.

class @NGController extends @NGObject
  @register: (app) ->
    app.controller "#{@name}", this

  constructor: (@scope) ->
    @scope[key] = value for key, value of this when !@scope[key]?

Specifically for service objects, we setup an NGService object that implements event notifications allowing controllers, directives, etc to register callbacks for specific service events. In the service, whenever desired, you can call the notify function and inform all registered observers that the specific event occurred.

class @NGService extends @NGObject
  @register: (app) -> app.service "#{@name}", this

  observableCallbacks: {}

  on: (event_name, callback) ->
    @observableCallbacks[event_name] ?= []
    @observableCallbacks[event_name].push callback

  notify: (event_name, data = {}) ->
    angular.forEach @observableCallbacks[event_name], (callback) ->

We use an event_name for each event type which adds the ability to sanely register and call multiple events explicitly as so:

handleEvent: -> notify 'my:event'
MyService.on 'my:event', -> doStuff()

Included in my Rails projects, this helper allow me to write concise and legible angular code in my preferred CoffeeScript class syntax. Here is a short example of a rewritten Angular controller with the new syntax and format:

class CalendarCtrl extends @NGController
  @register window.App

  @$inject: [

  init: ->
    @config = @Calendar.config()

Is there anything explicitly problematic or wrong about the verbose traditional Angular syntax? Absolutely not! Does this syntax make me a happier developer and allow me to get my code out the door quicker? Without a doubt. Setting up this syntax was a fun endeavor and my hope is it makes at least one other developer's life happier!

Rails Resource To The Rescue

One of the last remaining hurdles to quick and easy angular development with rails is wiring up Rails resources with Angular. One source of frustration is Angular's handling (or lack thereof) of nested resource parameters. Here are a few recent GitHub issues as examples of that frustration fix(ngResource): Add support for nested params and Query params not serializes as expected. Thankfully, Angular uses a modular approach to resource handling, so swapping ngResource with a different library is a breeze.

After months of massaging the flat params from Angular in my Rails controllers, I stumbled across Rails Resource. Rails Resource is a promise based resource module that handles Angular resources exactly as a default Rails application would expect. With very little code, we can wire up Angular with our Rails resource and be on our way.

As an example, I have a basic Rails app with a model Beer that belongs_to a Brewery. To wire up Angular with these resources using Rails Resource I could write an Angular factory such as:

App.factory "Beer", ['railsResourceFactory', 'railsSerializer', (railsResourceFactory, railsSerializer) ->
  resource = railsResourceFactory
    url: "/beers"
    name: "beer"
    serializer: railsSerializer ->
      @nestedAttribute 'brewery'

This code creates an Angular resource 'Beer' and maps it to the appropriate endpoints in our Rails application. Our next step is to setup the association with the Brewery model. You can see this done above with the following lines:

  serializer: railsSerializer ->
    @nestedAttribute 'brewery'

The serializer in Rails Resource looks to be quite powerful in allowing you to both specify relationships and alter the json coming and going to resource endpoints. The factory we have created above sets up a Beer resource in Angular that accepts_nested_attributes_for a Brewery resource. With only the code demonstrated above, the parameters sent to the logs on a create action (for example) are just what Rails expects and is handled easily by a traditional Rails create action.

  Started POST "/beers" for
  Processing by BeersController#create as JSON
  Parameters: {"beer"=>{"name"=>"Goose Island IPA", "description"=>"Hoppy Goodness",
               "brewery_attributes"=>{"name"=>"Goose Island"}}}

The Result

During this article I have described three tools I use to make me a happier Rails developer leveraging the power of AngularJS in my applications:

  1. Letting each framework handle what it's good at
  2. The CoffeeScript helper that allows me to write more concise code in a syntax I enjoy
  3. A resource module that wires up Rails resources with ease

Using these methods I setup a very basic CRUD Rails application on Github davidstump/beers. With the exception of the factory shown above, the only Javascript required was a short and sweet Angular controller:

class BeersCtrl extends @NGController
  @register window.App

  @$inject: [

  init: ->

  loadBeers: ->
    @Beer.query().then (results) =>
      @all = results

  create: ->
    new @Beer(@newBeer).create().then (results) =>

  destroy: (beer_id) ->
    @Beer.$delete(@Beer.resourceUrl(beer_id)).then (results) =>

This style of Angular fits seamlessly into my familiar mental model formed from my time developing Rails applications and ultimately makes me a quicker, happier and healthier developer.

I would love any and all feedback (and Pull Requests) on both these approaches as well as the NGHelper library itself. Thank you for taking the time to read through my thoughts and happy coding!

Do you ever feel like you spend most of your day repairing tests in your Rails app? If you have been building Rails apps as long for as we have, then you know the importance of a robust test suite. Working with a brittle and slow tests can really make the most basic tasks difficult. This is especially true for large Rails apps that have been around for a few years. The good news is that we can fix this with a few helpful tips I've picked up over the years that can keep your test suite running smoothly for the long-run.

First, let's define what maintainable means. It can take on a lot meanings, but let's break it down into three categories:

  1. Tests should be reliable. When we run our tests over and over; whether it's a single test or the entire test suite, we want them to consistently pass or even consistently fail. There's nothing more tedious than tracking down inconsistencies. I've spent countless hours and sometimes days fixing tests that run fine in isolation, but fail when running the complete suite.

  2. Tests should be easy to write. I confess, when I work with a Rails app that has slow or brittle tests, I skip writing new tests all together because I know it's too difficult or too time consuming setting up new tests. So it's critical that our test suite be straightforward enough to dive right in.

  3. Tests should be easy to understand. When tests fail, we should be able to look at the test code and quickly understand why it's failing and how to fix it. The last thing we want to do is waste time staring at code wondering "Why is this failing!".

The Test Environment

Now that we have an understanding of what maintainable tests mean, let's get started with a solid foundation - the test helpers. Here is what our test_helper.rb might look like:

require "minitest/autorun"
require "mocha/setup"
require 'simplecov'
require 'capybara/dsl'
require 'capybara/rails'


module TestHelper
  include Capybara::DSL

  def setup
    DatabaseCleaner.strategy = :truncation

  def teardown

Nice and simple! Let's take a closer at the gems we're using:

Minitest - I like to use MiniTest for writing tests because of its simplicity and it provides a complete set of testing facilities without the noise. Best of all it's shipped with Ruby 1.9.

Mocha - When we absolutely need to mock or stub, I reach for Mocha since it's a good lightweight option. I found Mocha to be the least fussy when it comes to stubbing.

SimpleCov is absolutely essential for measuring our code coverage. Our road to lean and mean tests start by knowing what has already been tested and what has yet to be tested.

DatabaseCleaner To avoid banging our head against bizarre inconsistencies with the test database, we are going to call on the help from DatbaseCleaner, which ensures that we have a clean database state between tests.

Capybara Capybara is an intuitive web browser simulation framework that allows us to test how a real user interacts with our web application. It also comes with a built-in DSL for describing user interactions. We'll use Capybara extensively for our acceptance tests.

Achieving Testing Zen

Now that we have a nice setup for our suite, we're ready to start adding tests. How we approach testing is important if we want to keep our test suite healthy. We want to write the minimal amount of code required to satisfy our test cases. The best way to do this is using the Top-Down approach. This brings us to our first tip.

Tip #1: Start at the top. Start with the acceptance tests and drive our implementation at the user interface level. This can be a great way to prototype our implementation, and starting at the top, we can cover a lot of code with little tests. Once we are satisfied with our acceptance tests, we can fill-in holes with unit tests for complete public interface coverage.

Tip #2: Use helper methods to keep your test DRY. To keep our tests nice and neat, extract common setup scenarios into helper methods. For example, if we know we have to log into the application to test our app, we can setup a handy login method:

def log_in_user(user)
  visit "/login"

  within("form") do
    fill_in "login", with: user.login
    fill_in "password", with: "anything"
  click_button "Log in"

Tip #3: Avoid Copy and Paste. Sometimes it's so easy to copy and paste code from one test to another - especially our setup code. Before you copy and paste, ask yourself "Should I move this code to a helper method instead?".

Tip #4: Don't test what has already been tested. It may sound simple, but chances are you've written tests for code that has already been tested without knowing it. I come across something like this quite often:

describe User do
  it { should have_many(:orders)}

What exactly are we testing here? Are we just wanting to be extra sure that we've spelled the has_many :order association correctly in the User model? ActiveRecord associations are well-tested by the Rails test suite, so there is not need to have this in our test suite.

Tip #6: Avoid Excessive use of mocks, stubs, and expectations. Too many mocks and stubs can lead to unexpected results and expectations often serve no benefit at all and almost always lock you to the internal implementation of the thing you're testing, thus making tests brittle. I have seen many projects use excessive mocks and often times it's not testing anything. Prefer to use real data from the database. The downside of this of course, is that our tests may be slower.

Tip #7: Makes tests fast enough. We're not focusing too much on speed. Don't get me wrong, if your tests are slow, you won't be encouraged to write them. So it's important to keep speed in mind. But in the end, the most important thing we want is a reliable, understandable code, even if they're not as fast as we'd like them to be.

Tip #8: Keep context and describe blocks flat. Avoid deeply nested describe contexts. For example:

describe "checking out" do

  describe "add items in shopping cart" do
    before do
      click_link 'Checkout'

    describe "pay with credit card" do

When go too deep in our describe blocks, it's easy to lose sight of the steps taken in the previous describe blocks. To compound the problem, we can't be sure of the database state either. Consider breaking describe blocks into separate tests or even separate files when deep nesting occurs. For our example above, we'll create a brand new test file for paying with credit card:

describe "paying with credit card" do
  before do

  it 'checks for valid promotion codes' do
    fill_in "promo_code", with: 'does not exists'
    click_link 'Place Order'
    assert page.has_content?("Sorry, invalid promotion code")

Tip #9: Only test public side effects. If a method changes the internal state, write your assertions based on the side effects available to the public. Keep test cases to external API - allows us to change internal implementation, while ensuring the consumers of your class still work.

And that is it! By following these tips, you're on your way to achieving a happy and health test suite. If you found this article helpful, you should also checkout:

  1. Practical Guide to User Testing
  2. Rails Testing Pyramid
  3. Minitest Quick Reference

Got any tips to share? Please leave them in the comments.