Rails 2.0 TextMate bundle - Tasty Tidbit - respond_to and view navigation
The new release of the Rails TextMate bundle is coming soon. Its guaranteed to be shiny, sparkly and will fit in with any home or office decor. More importantly, it will be upgraded for Rails 2.0.
Today is the first Tasty Tidbit - a demonstration of one of the snazzy new features coming to your Macintosh soon.
In this Tasty Tidbit, we look at respond_to and the ability to create and navigate to view templates based on the selected format block, such as wants.js -> .js.rjs.
Cannot see the embedded video? Want the Hi-Def version? Download the video (5 Mb).
Contribute to the Bundle
To clone the git repository and start sharing your own personal goodness, see previous article.
Zero Sign On - 1 better or Infinitely better than Single Sign On?
This article has no code in it. There are no TODO steps. Nothing to install. Its a picture of the future.
There is no reason to bookmark this article and read it another day. Its nearly all pictures. You can read it now.
This “picture of the future” was actually added to our browsers in the 90s. Netscape and MSIE3.0 both had it.
“It” is Client Certificates, and to me to means “never logging on with username/password NOR OpenID ever again”. Zero Sign On. It must be better than the much-targetted Single Sign On.
Client Certificates
Firefox 2.0:

Or on Safari/KeyChain:

Small problem: no website I’ve ever used has ever offered them, so I never knew they existed. I didn’t know what they did, nor as a web developer that I could create them for users who’d never need to login again.
Clifford Heath showed me the light. On #roro irc channel, we were exploring how “Zero Sign On” might be implemented using ssh-keygen, and browser plugins etc. Clifford mentioned client certificates and then someone else mentioned that MyOpenID already supported them. [someone = Michael Kedzierski]
I already had an myopenid account, so raced over to explore the new world of certificates.
Under “Authentication Settings”:

After submit:

And then:

Then feedback:

So I thought to test out if “Zero Sign On” actually worked. Normally, after logging out you’d need to submit username/password or if a site supported OpenID (yes myopenid.com is an OpenID provider which is a bit circular but bear with me) you login by entering your OpenID url and pressing Enter. Either way, you’ve got work to do.
Instead, I clicked “Login” link on the home page, and was redirected immediately to:


So it was still using cookies so that it could log me in immediately next time without clicking “login”, but either way, there is no username/password nor any other “type something here” login form. Just a “Remember Me” checkbox.
Finally, myopenid.com shows a log of your sign-in attempts:

Your sites and the future
As a web developer, you can do one of two things to get some leverage of Client Certificates.
- Support OpenID as a login mechanism. Users with myopenid.com accounts (or other openid providers that support client certificates) will benefit from automatic login to their openid page and instant redirection to your site. You’ll also be able to help new users import their profile data to get them started quickly.
- Implement Client Certificates yourself. I would have liked to have had a crack at this before posting about Client Certificates and all their sweet loveliness, but I didn’t. My bad. Instead, I found a nice step-by-step (plus comments with updates) on implementing Client Certificates
If you have/do implement Client Certificates in Ruby/Rails world, you’ll get a 1000 Happy Points from me if you open source it/blog about it. Happy Points are redeemable for Happiness in all countries.
One-stop JavaScript Unit Testing for Rails 2.0
Previously, I mentioned a multi-step/multi-project solution to doing JavaScript Unit Testing for Rails, including an autotest script to make TDD life easier for the autotest-addicted.
It was too many steps, too many different projects, and too much dependence on prototypejs. So let’s fix this via the spanky new newjs (introduced here):
Instead of several steps, there is now two steps:
cd myrailsapp # rails 2.0 app
sudo gem install newjs # v1.3.1+
script/generate javascript_test application
create vendor/plugins/javascript_unittest/lib
create vendor/plugins/javascript_unittest/tasks
create test/javascript/assets/jsunittest.js
create test/javascript/assets/unittest.css
create config/javascript_test_autotest.yml.sample
create vendor/plugins/javascript_unittest/lib/jstest.rb
create vendor/plugins/javascript_unittest/tasks/runner.rake
create vendor/plugins/javascript_unittest/tasks/autotest.rake
create vendor/plugins/javascript_unittest/README
create test/javascript/application_test.html
create script/rstakeout
create script/js_autotest
It installs all assets, gives you a rake test:javascripts task, gives you script/js_autotest, and finally (and most importantly), creates the application_test.html test stub.
As always, you can also run a single test file by loading it into a browser.
Prototype independence
Previously, the test suite - unittest.js - had a dependency on prototypejs. This was wonderful if you’re developing in prototypejs, but could cause some grief if you weren’t.
newjs now comes packed with an identical test suite - jsunittest - but it is built without a dependency on prototypejs.
Merb et al support
I wrote a rails generator because I used Rails. If a merb/other framework (Ruby or non-Ruby) wants a similar generator, just ask. Its pretty simple - I copy over the rails_generators folder into a merb_generators folder in newjs and change some things based on your frameworks’ structure.
Alternate test suite support
If you like another test suite, and want it included in the generators, this might require some additional effort on your part. It probably has different mechanisms for launching runners etc; whereas I was able to steal the rake tests + support libraries from prototypejs. But, it can be done.
Peepcode
These tools will be discussed in animated detail in the forth coming Peepcode “JavaScript Unit Testing”.
newjs = newgem for JavaScript projects; free TDD suite
Want to start a new JavaScript project for a library or widget/badge for your website?
You know you should do TDD but wouldn’t know how to get started, what support libraries you need and where to get them from?
You need tools to deploy your library, your website etc?
You’d like a consistent structure to your project so that IDEs could provide support (toggle btw src/person.js and test/unit/person_test.html) [I haven’t done this bit yet, I’m sure I’ll add it to the JavaScipt Unit testing textmate bundle one day soon].
I couldn’t find anything helpful like this, so I created newjs - the JavaScript Project Generator.
Why?
But first, an brief history of everything…
I fell instantly in love with Rails for a couple reasons:
rails&script/generatecommands - they teach you what files you need
and where they should go- Ajax support - the marketing phrase “its as easy to use Ajax as not to” took me
away from ASP.NET where the new Ajax.NET library was non-trivial to use; RJS
didn’t exist at this stage, but Rails’ JavaScript support was still awesome - TextMate - though I didn’t get to use it for 18 mths til I bought a Mac
Later I fell in love with Ruby, for its meta-programming, syntactical possibilities
and free TDD support within Rails.
Then I fell out of love with JavaScript. Partly because Rails started generating JavaScript for me, and ultimately because I didn’t have test support. Whether you use Rails JavaScript helpers, or write your own unobtrusive JavaScript libraries you’re still living in an unhappy world without tests; let alone without TDD.
I still wrote JavaScript because it still needed writing. But a lot of my JavaScript
became “write-once, modify-never” affairs. Not just because I had no tests,
but each project had a different structure, different deployment processes, etc.
Finally, this year I figured out “TDD for JavaScript”. For every 1000 blog articles about Rails or Ruby, there is 0-1 article on unit testing JavaScript. Or perhaps I just don’t know how to use Google. Soon, the “JavaScript Unit Testing” PeepCode will be finished, so hopefully it will add to this lacking body of knowledge.
What I needed now was one-line starter-kit for new JavaScript projects that included:
- A standard structure for JavaScript libraries/projects
- In-built testing support, with
raketasks andscript/generate unit_test
generators - Tasks for deploying distribution files (via version numbers)
- Tasks for managing the project website
I don’t think there is one already, thus my hand was forced: newjs.
Installation & Getting Started
Installation and maintenance of generated JavaScript projects requires the installation of Ruby and RubyGems.
The command-line application newjs is installed as below, for any operating system (except the ‘sudo’ part - use as necessary):
sudo gem install newjs
You’ll note it uses RubiGen because I like to cheat when it comes to generating things.
To kick-off your new project/library, run the command-line app newjs:
$ newjs mylib -a "Dr Nic" -e "drnicwilliams@gmail.com" -u "http://mylib.rubyforge.org"
create config
create lib
create src
create script
create tasks
create test/assets
create test/assets/unittest.css
create test/assets/unittest.js
create test/assets/prototype.js
create tasks/javascript_test_autotest_tasks.rake
create tasks/environment.rake
create tasks/deploy.rake
create config/javascript_test_autotest.yml.sample
create lib/protodoc.rb
create lib/jstest.rb
create Rakefile
create README.txt
create History.txt
create License.txt
create src/HEADER
create src/mylib.js
create script/rstakeout
create script/js_autotest
dependency install_rubigen_scripts
exists script
create script/generate
create script/destroy
And you thought you wanted to create all that by hand…
TDD for JavaScript
Personally, I can never remember what basic HTML + JavaScript goes in the test HTML files. I quite like the javascript_test plugin for Rails, which allows you to generate a test HTML stub. So I’ve included a version of it
here.
Two actually: one for unit tests and one for functional tests.
$ script/generate unit_test some_lib create test/unit create test/unit/some_lib_test.html
For functional tests, use functional_test generator. See the newjs site for more details.
Lifecycle of JavaScript files
You create JavaScript files in src/ and then when you run rake dist
they can compressed into dist/project_name.js.
To make this work, add new src/ files into src/project_name.js via
<%= include "file_name.js" %>.
This is the build mechanism used by prototypejs and I stole it. Actually, I stole nearly everything from the prototypejs source structure.
Other stuff
Like newgem you can create a simple website (via textile files):
script/generate install_website
BONUS: instead of the crap purple default theme for newgem, newjs websites have a nice yellow theme - see example.
Source for newjs
Get it via git: master branch
Credits
The generated structure, the unittest.js test suite, and its included help files mostly come from prototypejs and newgem.
The generator mechanism is from RubiGem which comes from the Rails Generator created by Jeremy “I made someone leave Rails for PHP” Kemper.
Actually, I stole nearly everything from the prototypejs source structure. They are much cleverer than I am.
Using Git within a project (forking around)
In Star Wars, when Grand Moff Tarkin orders the destruction of the planet Alderaan, you must question his motivations. Historically, I think too much emphasis has been placed on “he’s an Evil Warlord doing the bidding of Darth Vader and the Emperor”, and “the Rebel scum must be tortured and punished.” But I’m not so sure this is the whole picture.
As developers, we know how exciting it is for a project/website to “go live”. You’ll get some praise from users, some bugs reports, but mostly, you will get the thrill of having finished something and seen it in action.
I’ve got to believe that when Tarkin gave the orders to “open up the taps on this baby,” there was a very different emotion at work amongst all his outwards “Give in to the Empire, Princess Leia” soapboxing. After flying around the emptiness of space in his brand new Death Star, never having actually used its main weapon, he just wanted to see if the thing actually worked.
If George Lucas hadn’t cut away from the cockpit of the Death Star to show us the planet Alderaan being obliterated, I guarantee you that Tarkin was waving his arms in the air, yelling “Oh that’s what I’m talkin’ ’bout,” with his lackies were all high-fiving each other in the background.
This brings me to Git.
Since moving the development of the Rails TextMate bundle to a git repository, several people have forked the repository.
When I pulled in the first “patch” from one of the forked repositories, I finally felt I’d “opened up the taps” on git. It was a sweet feeling.
Whilst Git was created by Linus for managing the Linux project, I get the feeling that Git’s raison d’être was to manage TextMate bundles. Weird since Linus probably doesn’t use TextMate.
A TextMate bundle is a combination of common/default snippets and personal snippets. Those personal snippets may even be useful for other people. Other people way want them. They may even join the set of default snippets.
Git’s system of forked repositories makes all this a reality. In a different, subversion-tainted reality, this scenario would mean that your local subversion checkout of the bundle becomes a mess of modified files and patch requests. With Git, you can stop caring about the central SCM. You make your own local changes, you push them to your own remote fork of the repository, and if they get absorbed into the common/default/central bundle so be it.
As I’m to understand it, this workflow is to Git as destroying planets is to the Death Star. Both Git and the Death Star are technologically impressive and to associate with them is to be seen as “cool”, but they can both do so much more.
Forking and Cloning
I’m not sure if I’m using official vocabulary, but I think of “forking” and “cloning” as different and I’ll use these terms until I’m educated otherwise.
Cloning is to make a copy of a remote repository into your local development environment. Your work machine. With the exception of IM, bittorrent and your shared iTunes library, that FTP server you don’t know is running, etc, no one’s got access to this machine or your clone.
You can make changes to your clone. For the TM bundles you could create a new snippet etc. You can then add and commit those changes into your local Git clone. They are committed now like a normal subversion repository commit. Except only you have them.
You could share the changes with a patch. You create the patch, then email it or upload it to wherever patches are uploaded to for your project.
Alternatively, you can push your changes to remote repositories (see “fork” below). If you have commit access to the original repository you cloned, you’d probably push your commits to this repository. If you don’t have commit rights, then you can fork the repository and push your commits there. “Freeeeeedooooom!!!” cried William Wallace whilst simultaneously having his Scottish testicles emasculated.
Forking is to clone an entire remote repository into another remote repository. Now you have two repositories based around the same code base. At that one point in time, they have the same set of files and the same history of changes.
As suggested above, you might do this because you don’t have commit rights to another fork, or because you are literally doing just as the name suggests: forking the project and going your own way. Either a moderate or radically different direction.
This is exactly what is wonderful about Git with TextMate bundles - there is no “one true path”.
If you wanted to fork the Rails TM bundle that I’ve hosted on github into another repository hosted on github then you click the “fork” button. [Email me for for the secret "I want to help make TM Rails Bundle awesome" github password if you need it to create an account]
Alternately you could fork and host your repository on any public git server. Dean Strelau forked it onto Gitorious. You could also fork it onto gitorious.org, you’ll just need to give it a different name; e.g. prefix/suffix your name.
“In the end, there can be only one”
No. No one needs to have their head cut off, Highlander-style, with Git. I mean, unlike Subversion, Git doesn’t force any organisational behaviour. All commits don’t have to make their way back into one “root” repository.
But, once you have committed changes to your fork you might like to let other forkers know about them; especially if there is one repository that is commonly known as the “root” repository. For the TM Rails bundle it would be my repository since I’ll then aggregate changes and push them down to the official Subversion repository and from there they get pushed out with future TextMate releases.
For the Rubinius project, you’d probably want all your commits investigated and pulled into Evan Pheonix’s personal git clone. He’s not good looking enough to just be a poster boy so I assume he knows how to build and distribute the project for download.
I’m not sure what the organisation hierarchy of evil that is being built around the Rubinius project, but you can probably post a notification of your commits and your repository URL to the Rubinius lighthouse tracker. Don’t have a fork? Just submit patch files. Already have commit rights to Evan’s repository? Push directly to it.
Three different ways to contribute. Which one to use? The organisation of the project decides. Rubinius has a how to contribute page.
For the Rails TextMate bundle project, the preferred way to contribute is either patch files from your local clone, or to fork the project and let me know of your fork URL. Discussion of the project happens on the Google Group.
So, once your project has multiple forks floating around - how do you as a project maintainer pull in the commits contributed by others?
How to pull friends and influence people
Let’s continue with the example of Dean’s fork of the TM bundle. After he forked it, he used the previous article’s instructions to clone his own fork, rather than my repository. To you, once you’ve forked a repository, then your repository is your git “origin” and the original repository you forked just becomes a fork to pull from when you want to synchronise your repositories. Make sense? Thought so.
Put another way, if you don’t fork my TextMate repository rather you just clone it and modify it, then your “origin” will be my repository. You’ll then contribute by emailing patch files.
Or you can fork my repository and then you clone this new repository locally. This new repository is your “origin”. You contribute by committing changes locally and pushing them to your origin (your fork). I then investigate them (see below), and merge them into my repository if I feel like it (gifts help too).
So, Dean’s got a fork. He’s cloned it locally, made changes, committed them locally and pushed them out to his fork. I know I’ve said the three times, but it confused the crap out of me so I think its worth repeating… a lot.
Now how do I pull in Dean’s commits into my local clone, investigate them, and then merge them into my repository? I’m glad you asked.
From within my local clone:
git checkout two_point_ooh git remote add strelau git://gitorious.org/ruby-on-rails-tmbundle/mainline.git git checkout -b strelau/two_point_ooh git pull strelau two_point_ooh
The first line changes my local clone into the “two_point_ooh” branch. Dean has told me that he has made his commits into his own two_point_ooh branch. So, my own two_point_ooh branch is the closest so I’ll start here. Its probably irrelevant which branch you start with. Perhaps.
The second line stores the information about Dean’s fork into my .git/config file. I’ve given the fork a label “strelau”, to differentiate it from my own remote repository “origin”.
The third line creates a new branch of my local repository. This branch will not be pushed up into my remote repository later on, rather its just for my own personal collection. The name of this branch is arbitrary. I could call it “ginger_beer_cordial”, but “strelau/two_point_ooh” is more meaningful. “strelau” to remind me which fork I should pull from, and “two_point_ooh” to remind me which branch of “strelau” to pull from.
Note, you are best to run this “git checkout -b name” operation from within another branch that most closely matches the contents you are about to pull in. That’s why I did the first line - to change into my own two_point_ooh branch first.
The fourth line pulls down any changes from Dean’s two_point_ooh branch into the current branch - strelau/two_point_ooh. That is, you now have a copy of it locally.
UPDATE: I really think this needs a good diagram here to explain the existance of two remote repositories, and within the local clone, the existance of two branches: two_point_ooh, and strelau/two_point_ooh. Plus there’ll be other branches in the local clone: master, origin/master (my remote version), origin/two_point_ooh (my remote version that I’ll push too when I’ve merged in Dean’s changes).
I can now investigate his commits. gitk is a fun tool to see the various branches and differences. It also shows the unique SHA1 codes for each commit, if you want to cherry pick changes rather than merge all of Dean’s changes into your own code.
Later, when Dean has more commits to offer the world, I’ll just run:
git checkout strelau/two_point_ooh git pull strelau two_point_ooh
See how the name of “Dean’s branch” helps remember what the “git pull” command is? TIP: Give meaningful name to remote branches.
What now?
Once you’ve pulled down someone else’s remote branch (from their fork) it is just another local branch. You can explore it in gitk and see how it compares to other branches, for example.
But what you’ll ultimately want to do is merge some/all of Dean’s commits into your branch, commit them, and push them out to your remote repository. If you have the “central” repository then this is akin to “accepting a patch”.
This process is now basic Git. Like driving the Death Star. Boring, and described elsewhere. Go back to your own branch, merge changes over, and push out to remote repo.
And now, Dean’s changes are in my remote repo:
And my gitk now show’s I’m sweet:
But what about Dean?
That’s like caring about the people on Alderaan…
What I mean to say is… Dean can now pull in my remote “two_point_ooh” branch into his local “two_point_ooh” branch. He may or may not like what I did to it.
I guess Dean and the people of Alderaan can blog about that one…









