Switching Away from Angular
comments

Last updated 27 February 2015

As I’ve spent more time working with Rails, I’ve realized that, even without Angular, a Rails site is capable of being fully-interactive, ajax-powered fun-times machine. I know what you’re thinking: “Duh! That’s true of everything from plain html to php!” Okay, yes, that’s true. But with Rails you can do it without really having to translate between server-side and javascript. Here’s what I mean:

Unobtrusive Javascript

Using jQuery for a ajax-heavy site is truly obtrusive to your experience to a developer. Every time you type event.preventDefault() you are saying, “Don’t do the thing that I wrote code for, do something else that requires more code!” Angular makes this better with its ng-clicks and ng-submits, but you still have to spend time formulating a json response, and then translating that response into html in your javascript.

With unobtrusive javascript, you can respond with a js.erb file that just inserts a partial you already wrote for the initial html response, so your total new code is adding format.js to your controller and $('selector').html('<%= j render partial: "a partial" %>'). Obviously it can be more complicated than that, but it usually isn’t.

Degrading Gracefully

Honestly, I don’t think degrading gracefully when javascript is not enabled is very important, but if I can do it while writing less code than Angular I see that as a win. It is comforting to know that if my grandma accidentally turned javascript off in her browser she can still use my site just fine.

My conclusion

So I removed Angular from this site. I know it doesn’t really matter to users, but for me it’s made life easier. Since there is less code to write, I’m more likely to add new features. For example, I’ve already updated the site to use markdown instead of html, which has made writing posts faster and more fun!

I still think Angular is great and will continue to use it for projects, but I think when it comes to Rails, I’ll keep using unobtrusive javascript until I have a real reason not to.


Complex ActiveRecord Queries Pt. II - Greatest N Per Group
comments

Last updated 12 February 2015

It is time again to get ridiculous with ActiveRecord. Last time I talked about dealing with includes and sorting. Today I'll talk about an issue I had with sorting by a one-to-many relationship.

The situation

  • Users have many Subscriptions
  • A User's end date (when they are no longer active) is based on the expiration_date of the last Subscription that user has
  • You want to order the Users by end date

Okay! Great! Should be easy. You want to write this:

User.joins(:subscriptions).order('subscriptions.expiration_date ASC')

The problem

It doesn't work. Of course.

Why? Because if a User has more than one Subscription which one should be used for ordering? That code doesn't really make sense.

After some googling around I discovered that there's a name for this problem - greatest n per group. (By the way, isn't it annoying when it would be so easy to find the answer to something if you only knew the name? It's like the old joke about not being able to look up something in the dictionary to see how it's spelled unless you know how it's spelled.) In this case we want to find the latest (instead of greatest) Subscription in each group of Subscriptions owned by each User. I found this excellent blog post showing how to solve that problem in ActiveRecord.

After spending time trying to grok the post (it is confusing!) I produced this:

User.joins(:subscriptions).joins('LEFT OUTER JOIN subscriptions sp ON (subscriptions.expiration_date < sp.expiration_date and subscriptions.user_id = sp.user_id)').where('sp.id IS NULL').order('subscriptions.expiration_date ASC')

So simple! sp is an arbitrary name representing the Subscription that is later than the one represented by subscriptions. You keep searching until sp.id IS NULL, meaning that subscriptions represents the latest Subscription for that User.

As I'm sure you predicted, this doesn't work either. Postgres immediately complains that you can't order by something you aren't selecting (why didn't it complain in the first case? I don't know, ActiveRecord).

Okay! We'll just select that too:

User.joins(:subscriptions).select('users.*, subscriptions.expiration_date').joins('LEFT OUTER JOIN subscriptions sp ON (subscriptions.expiration_date < sp.expiration_date and subscriptions.user_id = sp.user_id)').where('sp.id IS NULL').order('subscriptions.expiration_date ASC')

Another beautiful ActiveRecord query. Just as a note, I really like ActiveRecord because it makes 99% of all the queries you do beautiful and semantic. Unfortunately, that other 1% is out there to get you.

I hope this helps someone trying to fight with ActiveRecord to sort by a single instance in a has_many relationship!


jump_back - a new gem to improve redirecting back in Rails
comments

Last updated 10 January 2015

Have you ever encounter encountered errors when running redirect_to :back in Rails and had to write a work around? What about saving a user's location on your site before redirecting them to your log in form so you can return them to what they were doing?

I've just released a gem, jump_back, that takes care of all of that for you with redirect_back, save_referer, and return_to_referer methods available in all your controllers. Check out the details in the Github README here.

If you have any ideas/feedback about jump_back you can leave a comment in here or, even better, open an issue on Github.

I hope you find it useful!


Intermediate Recursion - Fibonacci Sequence with Memoization
comments

Last updated 06 November 2014

After my last post where I described some recursion basics with JavaScript, I thought it would be fun to get into a slightly more advanced topic: Memoization.

You can read that article, but the basic concept of memoization is not repeating calculations if you've already found the answer. The example used there is finding factorials (5! = 5 * 4 * 3 * 2 * 1), but that only works if you call the function multiple times in your program. I want to talk about those rare cases where memoization comes in handy within the function itself.

Fibonacci Sequence

You've probably heard about this sequence before - it's the one followed by pine cones and the golden ratio. It starts 0, 1, 1, 2, 3, 5, 8, 13... where each number is the sum of the two previous numbers.

Based on that description, you can probably guess if we wanted to calculate the nth fibonacci number, recursion would come in handy. The first pass looks like this in JavaScript:

function fibonacci(positiveInteger) {
    if (positiveInteger === 1) {
        return 1;
    } else if (positiveInteger === 0) {
        return 0;
    } else {
        return fibonacci(positiveInteger - 2) + fibonacci(positiveInteger - 1);
    }
}

Makes sense? You build in some automatic returns for 0 and 1 and then it works as expected with the answer being the sum of the two previous fibonacci numbers.

The problem

It works great! The problem, though, lies in trying to calculate larger numbers. Running node in the terminal on my Chromebook starts getting slow around fibonacci(30) and fibonacci(100) appears to completely crash my terminal. I suspect it would stop running at some point, but I don't want to wait all day.

The solution - Memoization

As you probably guessed, we can use memoization to improve this behavior. How? Each time we calculate a fibonacci number using the above function, we were calculating all the fibonacci numbers down to 0. This involves a lot of repeated calculations. Let's try to remember all the fibonacci numbers we've calculated and pass them into the recursive calls.

function fibonacci(positiveInteger, foundFibonaccis) {
    if (typeof(foundFibonaccis) === 'undefined') {
        var found = { 0: 0, 1: 1 };
    } else {
        var found = foundFibonaccis;
    }
    if (typeof(found[positiveInteger]) !== 'undefined') {
        return found[positiveInteger];
    } else {
        found[positiveInteger] = fibonacci(positiveInteger - 2, found) + fibonacci(positiveInteger - 1, found);
    }
    return found[positiveInteger];
}

Now we are storing each calculated number in an object and passing it into future recursive calls. If nothing is passed in, I set the object to { 0: 0, 1: 1 } much like I supplied the answers for 0 and 1 in the first function.

Does that improve the performance? Oh yeah! On my Chromebook I now get the answer for fibonacci(1000) almost instantly. In fact, I get the answer up to fibonacci(1476) right away and the only reason I can't calculate higher fibonacci numbers is that JavaScript can't handle it and starts returning Infinity.

I hope you found this mini introduction to memoization helpful. If you've found other areas where memoization would be helpful sound off in the comments!


Recursion Basics - Adding Numbers in an Array with Javascript
comments

Last updated 31 October 2014

Recursion can be confusing, especially for people new to programming. I thought I'd post a very simple example here to help beginners.

The problem

Let's say you want to add all the numbers in an array without using a loop. (Why can't you use a loop? Because.) If you knew beforehand the number of items in the array you could write:

function addArray(arrayOfNums) {
    return arrayOfNums[0] + arrayOfNums[1];
}

That would work great for arrays with only 2 numbers. You could write out as many arrayOfNums[x] + as you wanted, but what if you needed to add an array with hundreds of numbers? Enter recursion. Try this:

function addArray(arrayOfNums) {
    return arrayOfNums.shift() + addArray(arrayOfNums);
}

What is happening there? arrayOfNums.shift() removes the first item in an array and returns that item, so you are basically asking your code to add the first number in the array to the sum (using the addArray function) of the remaining items in the array. The function keeps calling itself using progressively smaller arrays until it has added all the numbers together. That is the magic of recursion.

So we're all set? Unfortunately, no. Give it a try and you'll get an infinite loop! You need to set a condition upon which the recursion will end and the function will exit.

In this case, it makes sense to just return 0 if the array is empty because the sum of an empty array should be 0.

function addArray(arrayOfNums) {
    if (arrayOfNums.length === 0) { return 0; }
    return arrayOfNums.shift() + addArray(arrayOfNums);
}

Now if you run this code you will get the expected results! I hope this can help a beginner get the hang of recursion.


Complex ActiveRecord Queries with Includes
comments

Last updated 18 October 2014

ActiveRecord's way of separating Ruby developers from writing SQL is fantastic, but sometimes its behavior can be a little surprising. I ran into some ActiveRecord-related trouble recently and wanted to share the solution.

The situation

I had a model, let's call it DateRange that represents a range of dates (amazing, right?). Each date range could have many TakenDates representing a range of dates that fall within its parent date range and are no longer available.

The problem

Let's say I'm trying to find out if a given range of dates is not taken within an existing DateRange. That means that it falls within a given range and has not been taken by a TakenDate. So I want to do a query that returns all DateRanges and associated TakenDates if they exist. Great! ActiveRecord has an includes method just for this. So I wrote a query like so:

DateRange.includes(:taken_dates)
  .where('date_ranges.start_date >= ? AND date_ranges.end_date <= ?',
          some_date, some_other_date)
  .where.not('(taken_dates.start_date >= :start_date AND taken_dates.start_date <= :end_date) OR (taken_date.end_date >= :start_date AND taken_date.end_date <= :end_date)',
          start_date: some_date, end_date: some_other_date)

I know that is bewildering, but given two dates, it tries to find a DateRange that it falls within that doesn't have a conflicting TakenDate. It doesn't work, however. Why? Because it never returns any DateRange without any TakenDates. I was surprised about that, because I assumed the where.not call would happily return any DateRanges without TakenDates.

For a while I was stymied at how I could do this with a single query. It would be possible to do two different queries and combine them, but that would be slower and would not leave me with an ActiveRecord collection.

The solution

DateRange.includes(:taken_dates)
  .where('date_ranges.start_date >= ? AND date_ranges.end_date <= ?',
          some_date, some_other_date)
  .where('taken_dates.id IS NULL OR NOT (taken_dates.start_date >= :start_date AND taken_dates.start_date <= :end_date) OR (taken_date.end_date >= :start_date AND taken_date.end_date <= :end_date)',
          start_date: some_date, end_date: some_other_date)

That is one ugly query, but the key is specifying taken_date.is IS NULL OR some condition. This returns everything without an association while still allowing you to do a query based on the association if it exists!

I don't doubt that there is a better way to tackle this problem (feel free to let me know in the comments!), but I think it is good to know some tricks for those corner cases where ActiveRecord doesn't make your life easy.


Routing with Rails and Angular
comments

Last updated 11 October 2014

There are a lot of great blog posts about setting up an app with Rails as the back-end and AngularJS as the front-end. You can find some here, here, or here. When it comes to routing, though, the best approach is unclear.

If you are using ngRoute (and you really should be to allow deep linking on your Angular app) your server should be able to handle requests like /blog/posts/1 and show the appropriate blog post. You can easily do this by just routing all requests to your main index page and let Angular handle the routing. But what urls should Angular use to fetch the post from the server? You could namespace all of the server responses like /api/blog/posts/1 but that doesn't really make sense. What you really want is to respond to .html requests by displaying the single-page Angular html and to respond to .json requests with the appropriate resource as json.

Rails makes this easy!

As anyone who has generated scaffolding with Rails know, it is easy to craft a different response whether it is .html or .json. Your controllers frequently look like:

def show
  @post = Post.find(params[:id])
  respond_to do |format|
    format.html # render the html view
    format.json # render the json view
  end
end

So, if I have my home page at static_pages#home I might write:

respond_to do |format|
  format.html { render 'static_pages/home' }
  format.json # rendering the show.json.erb file
end

Now you don't have to try to redirect all requests in your config/routes file or do anything crazy to properly respond to deep links.

This works fine, but I don't usually feel it necessary to create the .json.erb file for simple models and it also gets quite repetitive to have the same respond_to block in every controller action that takes a get request. Instead, I find that declaring a custom method in your ApplicationController that handles it for you:

def ng_respond(response_for_json)
  respond_to do |format|
    format.html { render 'static_pages/home' }
    format.json { render json: response_for_json.to_json }
  end
end

That way you can create controller actions like this:

def show
  @post = Post.find(params[:id])
  ng_respond(@post)
end

I hope this helps you with routing in your Rails/Angular apps. Leave any tips you might have in the comments.