And, in keeping with his Developer DNA, the history lives on GitHub: to navigate, please use your left and right arrow keys.
Bonus: watch Ryan make a real time web app in his brief intro of AngularJS!
Mobomo webinars-now on demand! | learn more.
And, in keeping with his Developer DNA, the history lives on GitHub: to navigate, please use your left and right arrow keys.
Bonus: watch Ryan make a real time web app in his brief intro of AngularJS!
Hey RailsConf goers! You won't want to miss Jerry Cheung, co-author of (the just-released) MacRuby in Action book and Senior Engineer at Intridea present "Evented Ruby vs Node.js" Tuesday afternoon!
While Node.js is the hot new kid on the block, evented libraries like EventMachine for Ruby and Twisted for Python have existed for a long time. When does it make sense to use one over the other? What are the advantages and disadvantages to using node over ruby? In this talk, you will learn how to get the same power of concurrency enjoyed by Node.js while continuing to write in the language you know and love. Topics covered will include pubsub with redis or faye, building evented rack applications, and running evented applications alongside existing Rails apps.
Jerry will be in Salon K at 2:30 pm tomorrow.
Keep it weird, Austin Rails!
Of all of the new tools that I've picked up using for development in the past six months, there is one that has come to stand above the others for its nearly universal utility. That tool is Guard.
Guard is a RubyGem but don't let that fool you into thinking it's only useful for Ruby projects. Guard is essentially an autotest for everything. It provides a general purpose set of tools for watching when files are changed in your project and taking action based on it. You can use it to do just about anything, but common uses will include:
With a little creativity and a slight bit of Ruby coding, though, you can make your entire project's workflow run smoother and faster. It's like having a telepathic robot buddy who just goes around doing whatever you were about to do next without having to be told (except the first time).
Guard requires a basic Ruby setup. Once you have Ruby and RubyGems installed, simply run:
gem install guard
This will get you started. If you want to make it easier for others to run your guards as well, you should also install Bundler to encapsulate the different guard gems you'll be using:
gem install bundler
Once you have these installed, in the root of your project run:
guard init
This will initialize a Guardfile in the project root that will be telling Guard what to do going forward. From here, you will want to install some of the Guard extension gems that let you quickly create automation for your project. Some of my favorites:
-w option, I prefer Guard because it lets you define the configuration once and, in addition, run a single process for all of your project's automation.There's a full list of guards that include all kinds of magic (there's even guard-livereload that can automatically refresh your browser whenever you make a change to a project), and it's dead simple to create new Guard libraries if what you want isn't available (or you can just use guard-process).
For any of the Guard gems you install, you can add them to your Guardfile by running:
guard init guardname
Where guardname might be rspec or coffeescript, etc. That will fill your Guardfile with a basic implementation of the given guard and is usually enough for you to tweak the settings to your liking without further documentation.
There's a great example of using Guard for a big Rails project, but I'm not just using it for Ruby. I've used Guard on jQuery plugins, Node.js projects, even static websites that I've been building (more on that a little later).
To make it easier for others to jump into your project with Guard, it also helps to use Bundler to maintain a Gemfile that points to the various guards you're using for the specific project. Just run bundle init to get Bundler up and running then edit the file to look something like this:
source 'http://rubygems.org' gem 'guard' gem 'guard-coffeescript' gem 'guard-process'
Then run bundle install. Once your gems are installed and you've set up your Guardfile, just run:
bundle exec guard
Guard will start up right away and your project now has some smooth automation action. Guard will even reload itself if you modify the Guardfile, so feel free to tweak as you go!
I'm going to post just a couple examples of Guardfiles I've been using in my projects recently to give you an idea of its versatility.
Here's the Guardfile for Sketch.js, a jQuery plugin that I just released:
# Automatically build the source Coffeescript into the lib directory guard 'coffeescript', :input => 'src', :output => 'lib', :bare => true # Also automatically build the test Coffeescripts guard 'coffeescript', :input => 'test', :output => 'test', :bare => true # Run Docco guard 'process', :name => 'Docco', :command => 'docco src/sketch.coffee' do watch %r{src/.+.coffee} end # Copy the newly created lib file for minification. guard 'process', :name => 'Copy to min', :command => 'cp lib/sketch.js lib/sketch.min.js' do watch %r{lib/sketch.js} end # Use uglify.js to minify the Javascript for maximum smallness guard 'uglify', :destination_file => "lib/sketch.min.js" do watch (%r{lib/sketch.min.js}) end
This enabled my workflow to be instantaneous: I could immediately look at my work whether it was in my examples, my tests, or my documentation. Everything was immediately built and I never had to slow myself down with run and refresh cycles.
I've probably only scratched the surface here, but a simple Node.js project that I'm currently working on has this for a Guardfile:
guard 'coffeescript', :input => 'src', :output => '.', :bare => true guard 'process', :name => 'NPM', :command => 'npm install' do watch %r{package.json} end
Notice that using guard-process I'm automatically installing new dependencies that may arise when the package.json file is altered.
I've come to really appreciate both Coffeescript and SASS as worthwhile abstractions, so even if I'm building something that's vanilla HTML I might have a Guardfile like this:
guard 'sass', :input => 'sass', :output => 'css' guard 'coffeescript', :input => 'coffeescripts', :output => 'javascripts'
These are all basic examples, but that (to me) is the point: Guard is so simple to use and basic that you can drop it in every project you build. I've yet to run into something that I don't want to use Guard on.
I've been expanding my usage of Guard into, well, everything that I'm working on. Thus far it's included Ruby, Javascript, and static HTML projects, but if I move on to other things Guard will be coming with me. For instance, I'd love to build a Guard to automatically recompile and run an Android application whenever the XML views change. The possibilities are limitless.
If you're not using Guard, give it a try on one of your current projects. I think you'll quickly find immense satisfaction in being able to simply cd into the project directory, run guard, and know that you are completely ready to roll. I'd like to see a Guardfile in every open source project I fork, every client project I clone...Guard is so useful that I simply want to be using it all the time. And that is the mark of a great tool.
Do you know Chris Selmer? He’s one of the Senior Partners here at Intridea. He’s also a person that likes to run, even when nothing is chasing him. Its baffling, I know. Although, I guess I’m no better, as I’ve recently started going to the gym and picking things up just to put them down. Not my best decision. Regardless, Chris likes to run. Thanks to this little tidbit I was granted the fortune of attending Ruby Nation this month when Chris, who had already purchased a ticket to the conference, decided to sign up for a marathon to run an only-acceptable-while-in-a-car distance that very same weekend. Good for him, and good for me.
So what does this have to do with anything?
Well, it was at that conference that some things came together for me. By things, I mean some thoughts that had been lounging around in the back of my head for quite some time. I always knew they were there, but I hadn’t given them any attention. Until Ruby Nation that is. There were a handful of sessions that really brought these thoughts to the forefront.
The first session that caught my attention was our own Jerry Cheung’s presentation on Node.js (slides) where he gave a brief tour of Node and went over a handful of example scenarios where Node would work well alongside Rails. Then there was a Blake Mizerany's keynote in which he talked about being a polyglot, (someone who uses many languages). There was Chris Williams’ pirate-themed adventure called, “The Javascript Renaissance”. And finally, Ryan McGeary’s lightning talk on CoffeeScript (slides).
In addition to the conference, there were a number of things floating around the Twitterverse that also got my attention. There’s been an increasing trend of tweets either denouncing jQuery-only JS developers and/or their practices OR tweets praising some new JS tool/library. Another enticing find was a link to the talented Rebecca Murphey’s keynote presentation called, “The jQuery Divide”.
I’m guessing you’re probably starting to notice a theme here. It was the culmination of all these events that resulted this epiphany:
“Shit, I’m one of those jQuery-only jackasses. I need to do something about it.”
I tell myself that I write JS every day, but I don’t. I write jQuery. Don’t get me wrong, it gets the job done. But it never feels right. Now, jQuery and its DOM-centric approach (at least in common usage) aren’t all to blame. Its just as much my fault in that beyond the library, I know very little about the language. I intend to do something about it. I have a plan and I’m going to share it with you. First, here are my goals:
Here’s how I plan to do it. First, with two books that have come highly recommended:
The second part of my plan is to spend a non-trivial amount of time with each of these:
So that's my plan. With some poking and prodding from our Community Manager, Renae Bair, I’ll eventually post one or more follow-ups on what I’ve learned and my general thoughts on the experience.
In a nutshell, Node is a Javascript framework for building network apps. Network apps are broader in scope than webapps. They don't need to run on HTTP, thus freeing you to write lower level tools. Node doesn’t necessarily have to be part of your core app, and in many cases, it makes for a good fit for writing some of the support functions for your webapp. I'll cover the basics of getting Node setup, some event driven programming, and some miscellaneous Node goodies.
To get started, you can grab the latest Node release from Github. They have good installation instructions, but for the truly uninitiated Mac users, you can install it via homebrew:
brew install node
Once you have Node, you can try it out with an interactive session much like irb. Run node with no arguments:
node > console.log('hello world') hello world
Node's biggest core idea is evented I/O. Instead of blocking and waiting for I/O to finish, Node will start I/O, and execute a callback when data is actually ready. On top of reading and writing requests and responses, we spend a lot of time doing I/O when we fetch data from a datastore, or make external requests to other APIs. With Node, we save that wasted blocking time to do actual useful work.
Let's compare a really simple file I/O operation to compare Ruby to Node. Here's a simple Ruby script that will read a file 3 times and print when it finishes, and also print "doing something important".
(1..3).each do |i| contents = File.read('foo.txt') puts "#{i}. Finished reading file" puts "#{i}. doing something important..." end
We also print out the loop counter to see the order the statements were run. The output is unsurprising:
1. Finished reading file 1. doing something important... 2. Finished reading file 2. doing something important... 3. Finished reading file 3. doing something important...
Now let's look at the Node equivalent of the same script:
var fs = require('fs'); for (var i=1; i<=3; i++) { fs.readFile('presentation.key', function(err, data) { console.log(i + ". Finished reading file"); }); console.log(i + ". doing something important..."); }
What's interesting in this code is the callback we use with the readFile method. By having a callback on this I/O action, readFile will immediately return when called, which allows "doing something important" to be run before the I/O actually completes. When the file is finished reading, then we invoke the callback. Here's the output for the Node script:
1. doing something important... 2. doing something important... 3. doing something important... 4. Finished reading file 4. Finished reading file 4. Finished reading file
Were you surprised by the loop counter 4 in the results? This is one of those subtle "gotcha's" that takes time to get used to. Because the callback is invoked long after the loop is finished, the loop counter variable 'i' has been incremented to 4.
The community for Node is growing, and there is already a large number of non-blocking libraries that are Node friendly. Many of these can be used to build diagnostic and metrics tools for supporting your site. If your site has a need for push notifications or uses AJAX to poll for updates, you can also use Node to handle those features on your site. A few fun examples of apps built with Node include StatsD, Hummingbird Analytics, and Node Wargames.
That covers a brief introduction to Node. I leave you with a quote from the creator of Node that I'm a fan of. He says:
Node jails you into this evented-style programming. You can't do things in a blocking way, you can’t write slow programs.
The Node Knockout is this weekend right now and I've been trying to teach myself Node and get ready in a variety of ways. One of the most important (and least clear) aspects of preparation was figuring out how to properly vendor the latest Node libraries for use in Heroku. I've got NPM up and running locally, but as of its latest release it has no built-in support for vendoring. Here's how I managed.
Since this post, the maintainers of NPM have released an updated version with a new command: bundle. Here's how to use it (make sure you have NPM >= 0.1.27 for this to work).
First, create a package.json file in your project's root directory, and populate it with dependencies like so:
{ "name":"yourproject", "version":"0.0.1", "dependencies":{ "express":"1.0.0rc2", "ejs":"" } }
If you don't need a specific version, just specify a blank string. Now that you've created a package.json, you need to run bundle:
npm bundle ./vendor
This will bundle the dependencies specified into the vendor directory of your project. Now you're almost done! The last step is to add the vendor directory to your load paths:
require.paths.unshift('./vendor')
That's it! You can now require the dependencies you've specified like you would if NPM were installed normally (i.e. without special functions or directory specifiers). Happy Node-ing!
Warning: I am not an experienced Node developer and I may be doing this completely wrong. However, I am happy to publish this anyway with the hope that more learned Javascripters will correct my naive ways.
NPM provides a few helpful command options that let you specify the directory of installation when you install a library. By using the --root and --binroot options you can use a folder inside your local project instead of the default NPM root. For example, in my project I created a vendor folder and then, to install Express, specified:
npm install express --binroot ./vendor --root ./vendor
Now while this seems like it might do exactly what we want, it's not quite perfect. Rather than install everything in vendor, it installs the important stuff in vendor/.npm/.cache. This isn't the end of the world but can make for some pretty ugly require statements.
So now you've got your packages all nice and installed inside your project directory (probably a lot of support files that you don't need, as well, but the Node slugs on Heroku tend to be small anyway so no biggie). Now you need to include them in your application. To do this, I wrote a quick function, vrequire that adds the necessary load path and then requires the library all at once:
vrequire = function(lib) { require.paths.unshift("vendor/.npm/" + lib + "/active/package/lib"); return require(lib); }
Now if I call vrequire("express") it will load up from my vendored library. If I deploy my app to Heroku, it's able to find everything it needs and (cross your fingers) launch and work correctly!
Hopefully some people find this little guide useful, and I look forward to someone pointing me to the "real" way to do this stuff! If you want to poke around the exploratory code I've been creating to play with Node, you can find it on GitHub (but don't expect much!).