Portrait

Precompiling with Heroku

As Standards has progressed, I’ve ended up with a lot of CoffeeScript, Javascript and LESS files. I came to depend on require.js not only for its module management but it’s great, integrated r.js build step. less.js serves the same purpose for stylesheets.

On Heroku, using Git to deploy code, I found myself commiting compiled JS and CSS in order to deploy it. Maybe you just shook your head and thought “Nuh-uh! I’d never commit that code to master, I’ve got a deploy branch that handles compiled code!” Well, sure. There wasn’t a great way to handle the missing build step in between developing locally and pushing to a Heroku box until Rails 3.1 introduced the Asset Pipeline. But what happens if you’re not using Rails 3.1? Standards is a Sinatra app after all.

Turns out there are a few trickle-down effects from Heroku’s support for the Asset Pipeline that apply to all Ruby apps. After pushing code to Heroku, the Ruby buildpack will look for an assets:precompile rake task. If this task is detected the build pack will vendor Node.js and put it in the path of your app. This is important because, although Heroku supports Node.js apps, you don’t normally have access to it if you’re running a Ruby app. These are the two pieces necessary to move the require.js and LESS build steps onto Heroku.

I won’t go into the details of setting up require.js, it’s own website is a good resource, but compiling on Heroku doesn’t require any changes to be made to the normal build process.


I’ve borrowed the Rakefile from the requirejs-rails gem and stripped out most of what has to do with the Asset Pipeline or Sprockets. What remains is a barebone task that properly runs r.js and less.js on your code.

namespace :assets do

  def invoke_or_reboot_rake_task(task)
    Rake::Task[task].invoke
  end

  task :test_node do
    begin
      `node -v`
    rescue Errno::ENOENT
      STDERR.puts <<-EOM
        Unable to find 'node' on the current path.
        EOM
      exit 1
    end
  end

  namespace :precompile do
    task :all => ["assets:precompile:rjs",
                  "assets:precompile:less"]

    task :external => ["assets:test_node"] do
      Rake::Task["assets:precompile:all"].invoke
    end

    task :rjs do
      `cd public/js; ../../bin/node lib/r.js -o build.js`
      unless $?.success?
        raise RuntimeError, "JS compilation with r.js failed."
      end
    end

    task :less do
      less = File.open('public/less/main.less', 'r').read
      parser = Less::Parser.new :paths => ['public/less/']
      tree = parser.parse less
      css = tree.to_css
      Dir.mkdir 'public/css/'
      File.open('public/css/styles.css', 'w') {|f| f.write(css) }
    end
  end

  desc "Precompile JS and LESS assets"
  task :precompile do
    invoke_or_reboot_rake_task "assets:precompile:all"
  end
end
task "assets:precompile" => ["assets:precompile:external"]

It’s not a particularly flexible or robust solution, but it does the trick because the configuration is handled inside of require.js.

There is one gotcha that can crop up with running this task on Heroku. The production environment is not up and running when this Rake task is run which means that the environment variables aren’t there. This is usually an issue with anything that connects to a database or tries to detect the current environment with RACK_ENV, so make sure those tasks (if any) are in a different rakefile. If not, the task will fail silently and you’ll be left wondering why your site is style-less. As of me typing this, Heroku has an experimental feature they’re testing that makes env variables available, but it’s probably easier to keep this compile task isolated.

After committing this new Rakefile and pushing the changes up to Heroku, you should hopefully see Running: rake assets:precompile in your console. This is exactly what we want, and now you can also git rm any compiled files from your repo and never worry about them again.


So what does this all do? With one Rake task you get all of the benefits of require.js for JavaScript development and keep compiled JS/CSS out of the codebase. And you can use it with any Ruby app on Heroku.

Let me know what you think, I’m @interstateone on Twitter.

 

An update on Standards

It’s been slow going but Standards has been getting an overhaul over the past few weeks:

  • Pages involving user data go over SSL, so not only your password but tasks and stats are more secure. You’ll need to log out and back in again for it to take effect.
  • Everything should be a little more responsive in the app because there are less page refreshes. All of your information is just there.
  • It’s possible to navigate into the past to view your checks by clicking, tapping, swiping or even using the arrow keys on your keyboard. This is really handy on mobile devices where you can only see today and yesterday, so if you forgot to check something further back you can now.
I’m looking forward to adding some more features to Standards now that it’s been updated, if you haven’t checked it out yet you should sign up and let me know what you think!

And for those who are interested, the nitty-gritty:

  • HTTPS isn’t enforced but links will default to it. It’s one of the free benefits of sticking with the Heroku domain for now.
  • I’ve separated the public (unauthed) and private (authed) sides of the app. The public side still has Sinatra rendering and serving up each page and the private side has Sinatra serve up a single client-side ‘app’ page. I’d like full app/API separation but this makes it easier to manage authentication and also has the benefit of a static index page for search engines.
  • The app is running on Backbone.js with Marionette. Sinatra bootstraps the user’s data into the page when a refresh happens, but otherwise I’ve setup a second Sinatra app to give/take JSON at some API endpoints.
  • Touch events get handled with Hammer.js, a great cross-platform solution.
  • Client-side templates are Jade, these get managed and compiled into the single JS file using require-jade.
  • Everything client-side is written in CoffeeScript. (I will never write something non-trivial directly in JS again.) I’m using Require.js to manage dependencies, and I have r.js compiling everything to one file (with a Sublime Text build package) before pushing to Heroku. I’m using CodeKit to actually compile the CS (and LESS styles) though, so this process is convoluted and involves committing compiled code. I’ll be exploring a few options to solve this, like tying in r.js and less.js with the assets:precompile rake task that Heroku runs when building an app.

If you’re interested in the source, it’s up on GitHub.

 

An update on Standards

So far there have been over 50 of you amazing, crazy people that have signed up for Standards. For that I’m really grateful and I hope you get as much out of it as I’ve put into it. I’d love to tell you that in one short week you’ll be the most productive, wealthy and good looking that you’ve ever been. Maybe you already are. You are, come on.

Building habits is something that takes time. Some studies point to an average of 66 days (ugh, two whole slow-as-molasses months) before a task starts to seem automatic. I made Standards to increase my awareness about how long and consistently I’ve been doing something by making it easy to track it. That’s why it works as a web app you can have on your phone’s home screen. I also created Standards because sometimes you lose the motivation to stick with something; you burn out on it. That’s why Standards asks for the reason that you want to make something a habit: it can remind you about it later.

I’ve got more ideas and refinements that I’m constantly working on to make Standards better, and if you have any feedback (this is broken, this sucks, this would be better, etc.) I’d love to hear it. You can also follow @standardsapp for news and updates.

 
Standards: Get stuck on repeat
For a few years now I&#8217;ve been working with systems to make better habits. WeHaveStandards, Daytum, Doug&#8217;s DID and more are aimed at increasing your awareness of how successful you are at repeating tasks until they become second nature. These systems can range from a folded piece of paper to paid apps and all take slightly different approaches to the problem.
Standards is my own little foray into the genre, and it&#8217;s based on a few basic (proven) principles:
Habits are things that you do, not things that you avoid doing
They take an average of 66 days to form
Repetition is key
It&#8217;s okay to miss a day every once in a while
Try it out, and I&#8217;d love to hear your thoughts about it (email me or @interstateone)

Standards: Get stuck on repeat

For a few years now I’ve been working with systems to make better habits. WeHaveStandards, Daytum, Doug’s DID and more are aimed at increasing your awareness of how successful you are at repeating tasks until they become second nature. These systems can range from a folded piece of paper to paid apps and all take slightly different approaches to the problem.

Standards is my own little foray into the genre, and it’s based on a few basic (proven) principles:

  • Habits are things that you do, not things that you avoid doing
  • They take an average of 66 days to form
  • Repetition is key
  • It’s okay to miss a day every once in a while

Try it out, and I’d love to hear your thoughts about it (email me or @interstateone)

 

Standards Update

So here’s how it goes:

Checkbox grids are a game to me. Once I got in the habit of checking tasks off over a week or so I couldn’t help but see the empty spaces to improve.

The tasks that I track, and the way that I track them, have changed almost every week. I find that each week as I see how I’m doing I find a way to track it that more accurately reflects my results or motivates me by revealing my shortcomings. For example instead of just trying to cook three dinners each week I’m now tracking dinner every day. If I pay money for an immediate meal (fast food or restaurant) then I track the amount that I spent, and otherwise I get a checkmark. Same goes for breakfast and lunch too. This allows me to track what I’m eating and how much it’s costing me as well.

I’m still not cooking meals at home as much as I want to. I spoke with a friend, who cooks much more than I do, and they gave me some great suggestions that have me excited to try cooking a few meals this coming week. Be prepared with a recipe and ingredients! Planning is the biggest thing, and for myself I usually don’t have meal-worthy ingredients unless I’m actually going to make a meal so this should help.

What I consume in a day affects me a lot. I find I talk a lot at work and I can get dehydrated easily so I drink only lots of water. Fast food also makes me lethargic for hours afterwards. I’ve gotten better at making more conscious decisions about what I eat, but I still have some impulsiveness to hammer out.

The more I complete each week, the more that I try to do with my time. I’m not a particularly busy person, but an inefficient use of my time means that I don’t necessarily do that much. Like really do. This has started to improve over the past few months and I’ve really realized that I can always do more, more effectively, with my time. Since I began I’ve added daily French lessons, meditation, cleaning and journal entries to my list.

    The things I’m looking forward to:

    • Having a conversation with my girlfriend in French.
    • Consistent meditation.
    • Developing and tracking monthly goals as well.
    • Finding more things to do.
     
     

    Goals (12 Months)

    or, “How I Would Like To Amend My Resolutions, Because Waiting Until New Year’s Won’t Work”

    This won’t be that interesting for most people, I’m mainly posting it for myself because my roommate will be happier than if I Sharpie’d it on my bedroom wall.

    The year started with these:

    1. Start a 5-year project.
    2. Read one book each month.
    3. Put 10% away.
    4. Eat healthily, consistently.
    5. Engage in at least one hour of heavy physical activity every week.

    But I’m going to elaborate, because I need to. How will I do these? How do I know if I’ve done them?

    Start a 5-year project.

    What I really need is something significant to work on. It doesn’t need to be 5 years in length. I like building things for myself. I like tangible work. I’m highly (overly?) visual and kinesthetic and it’s much easier for me to feel a sense of accomplishment when I can see a finished product. I’ve learned a lot at my current job. I once said that it’s rewarding but not fulfilling, and that’s still the case. It’s not quite perfect for me, and those traits are what it’s missing. So what is this project going to be? Photography has been my semi-serious hobby in my spare time, but it needs to be bigger than that. It really feels like school, which I’ve made many excuses for not pursuing so far, is exactly what I need in my life. Now, being August, is exactly the wrong time to enroll, but exactly the right time to plan for next fall.

    Read one book each month.

    This hasn’t been an issue, but I think I can do better with why I want to do this. “If it’s not important to you, don’t consume it.” I find being busier makes sure that I don’t fall into the “check Google Reader, Twitter, Tumblr, Facebook, repeat” trap. Having an iPad was a great way to read more. It really made Instapaper a powerful tool, and iBooks, although ebooks still endlessly frustrate me, made finishing books a lot easier than I find with real books. The iPad was sold to get an iPhone 4, but I only wanted to downgrade to a smaller model, so I’ll be back on the bandwagon soon. With the previous goal, this one will become more fine-tuned as other priorities force themselves up the ladder.

    Put 10% Away.

    This was about managing my money much better. I’ve become a lot more conscious about it, I’ve been paying off my debt, I’m much more selective when I shop for clothing now, but I can do better. Food is still probably my biggest drain. Which leads me too:

    Eat healthily, consistently.

    Consistency. Bleh. I’ve made the decision to cut back on coffee again, opting for tea and water. No soda, sparing consumption of juice. Daily Starbucks is an emotional and monetary drain. I’ll grab coffee as a treat, opting for a slow breakfast at Elm or Transcend or something. Supporting Edmonton’s local businesses also feels more rewarding, and I get to meet cool people doing it. Eating an apple a day is surprisingly good for me (you). Eating breakfast at home, slowly, is also a very pleasant way to start the day. More of this. I need to start cooking at home though, I haven’t since I moved downtown. Start this. How? Two dinners each week, with leftovers for a meal the following work day.

    Engage in at least one hour of heavy physical activity each week.

    An hour a week doesn’t sound like much, and isn’t much. I had a couple rounds of biking to work. It’s 10KM each way, not a quick jaunt, and it feels great. I want to buy my own bike, which is not a good excuse to stop borrowing my roommate’s spare bike and biking to work, although it has been. I have still been doing the 50 pushups and crunches a couple times a week on and off. Again, consistency. Bleh.

    So here’s my list:

    I’m also going to try using Jake Lodwick’s wehavestandards.com as a method of tracking some fine-grain improvements I’d like to make. Starting with eat breakfast at home, check Facebook once at most and being in bed by midnight. I love checking things off of a list.