TextMate bundles for Merb

Posted by Dr Nic on May 12, 2008

If you are using TextMate (OS X) or E Text Editor (Windows) then you’ll be dead keen to know there is a TextMate bundle for Merb, and another one for Datamapper.

[This is cross-posted on the new Merbunity community site for Merb]

Currently, you can access the bundles via git:

cd "~/Library/Application Support/TextMate/Bundles"
git clone git://github.com/drnic/datamapper-tmbundle.git Datamapper.tmbundle
git clone git://github.com/drnic/merb-tmbundle.git Merb.tmbundle

Now “Reload Bundles” or restart TextMate.

You can now select from three Merb syntax/scopes. Press Shift+Alt+Cmd+M to see the options (below)

Merb TextMate bundle - select ORM

  • If you select Merb (Datamapper) you will have access to the Merb bundle AND the Datamapper bundle.
  • If you select Merb (ActiveRecord) you have access to the Merb bundle AND the Ruby on Rails bundle.
  • If you select Merb (Sequel) then nothing special happens as there isn’t a Sequel bundle yet. Want to create one?

Currently there is no separation in the Rails bundle for ActiveRecord and non-ActiveRecord snippets and commands, so if you use Merb (ActiveRecord) there will be some snippets + commands that you don’t want from Rails. In future, there may be more separation to help the Merb bundle. Also, TextMate 2 may help this cause.

As always, to learn what snippets are available at any given cursor position, use Ctrl+Cmd+T.

If you have new snippets for any of the bundles, I suggest forking the git repositories, pushing up the changes to github and sending Pull Requests to me (drnic).

Sponsored by Engine Yard

The initial development of this bundle was sponsored by Engine Yard because they care.

Rails bundle

There is also the hughly popular Ruby on Rails bundle for TextMate that you can use. Download from http://railsbundle.com/ or via github.

If you want to learn everything about the new Ruby on Rails bundle for TextMate and daily life with TextMate (short cuts, editing bundles) then I highly recommend the new TextMate for Rails 2 Peepcode:

TextMate for Rails 2

This recommendation comes from inside information on the quality of the Peepcode… it was written by me, and incorporates the vocal skills of the operatic Geoffrey Grosenbach.

One-stop JavaScript Unit Testing for Rails 2.0

Posted by Dr Nic on February 19, 2008

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

Posted by Dr Nic on February 17, 2008

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/generate commands - 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 rake tasks and script/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)

Posted by Dr Nic on February 03, 2008

Death Star - as seen on TV

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]

drnic's ruby-on-rails-tmbundle at two_point_ooh 2014 GitHub

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.

gitk: Ruby on Rails.tmbundle

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:

Commit History for drnic's ruby-on-rails-tmbundle 2014 GitHub

And my gitk now show’s I’m sweet:

gitk: Ruby on Rails.tmbundle

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…

Get ready for the TextMate “Trundle to Rails 2.0 Bundle”

Posted by Dr Nic on January 31, 2008

logo_bundle.png

Have you noticed lately that the Rails TextMate git pull origin two_point_oohbundle (also installed with e - the Text Editor for Windows) isn’t quite as helpful as it once was - guiding and amplifying your rails app development.

Your resourceful/restful rails apps are now filled with named routes, but none of the helpers (link_to, redirect_to, etc) use them. The default view template was still rhtml for a long time (latest svn trunk fixes this to be html.erb, though Marc Jeanson is having a crack at supporting both through a per-project config file).

Or perhaps you were hoping for some snippets for new features of Rails 2.0: assert_difference (asd), assert_select (ass), respond_to (rst).

Or just maybe, you’ve been updating your local bundle to Rails 2.0 already? Please say yes, please say yes. If you are saying “yes”, read at the bottom for how/where to send me the patches. If you are saying “no”, read at the bottom for how/where to start creating patches and sending them to me.

Firstly, DHH didn’t write the Rails bundle

I didn’t know this - I just assumed the guy who created Rails and helped promote TextMate also created the Ruby on Rails TextMate bundle. Instead if was WWF’s “The Rock” himself Duane Johnson (figurines sold separately, and may look different to the real Duane Johnson who writes Rails code instead of prancing around in his underpants with other adult males in confined spaces).

The TextMate SVN logs say that it the bundle was first committed in Jan 2005. Its now Jan 2008. That’s three years of maintaining a suite of code that thousands of people take for granted every day writing Rails code. What a champion.

Like the Australian Cricket team’s wicketkeeper, Adam Gilchrist, he’s also retiring at the top of his game.

New Maintainer… me

Instead of maintaining my own projects, I’ve decided to maintain this one. I love the TextMate bundles. Before I had a Mac, I ported them across to RadRails and many RadRailers entered a golden era of snippet happiness.

My bundle-fu may not be the equivalent of Bruce Lee, but I’m keen to see my favourite Rails tool live on strong.

Bleeding edge bundle

Whilst the TextMate SVN administrators process the maintainer change request (Allan is on holidays somewhere and he took the house keys with him), you might think all is lost!

Never.

The straight-off-the-cow bleeding edge Rails bundle can be accessed via Git. Specifically the branch two_point_ooh.

So, let’s all do away with our pre-existing Rails bundle and live on the edge.

cd ~/"Library/Application Support/TextMate/Bundles/"
mv "Ruby on Rails.tmbundle" "RoR.tmbundle.orig"
git clone git://github.com/drnic/ruby-on-rails-tmbundle.git "Ruby on Rails.tmbundle"
cd "Ruby on Rails.tmbundle"
git checkout --track -b two_point_ooh origin/two_point_ooh
git pull

Now, back in TextMate, go to menu “Bundles” > “Bundle Editor” > “Reload Bundles”.

You, my friend, are sitting pretty.

Upgrading to when newer blood is on the bleeding edge

Coming back for more?

cd ~/"Library/Application Support/TextMate/Bundles/Ruby on Rails.tmbundle"
git checkout two_point_ooh  # optional; only if you changed to another branch etc
git pull

Now, back in TextMate, go to menu “Bundles” > “Bundle Editor” > “Reload Bundles”.

Bathe yourself in glory. Splash it all over yourself.

Submitting patches

If you go into TextMate, launch the Bundle Editor (Cmd+Alt+Ctrl+B) and change something in the Ruby on Rails bundle, then files will added/changed within your local git clone.

What I mean is, you can very simply submit patches now. [When I say "simply", I mean, "I think this is the best approach but I could be completely wrong here..."] Git is so cool that I don’t know what its doing most of the time; but let’s hang in there as a team.

cd ~/"Library/Application Support/TextMate/Bundles/Ruby on Rails.tmbundle"
git add .   # to add any new files/snippets/commands you created; TextMate uses one file per snippet
git commit -a -m "Useful message about this patch goes here"
git diff -p HEAD^ HEAD

[Theoretically] this creates a patch based on your most recent commit. So you can easily create patches for changes even if your repository and the remote/central/bleeding edge repository look different.

If your patch was created over several commits, then replace HEAD^ with HEAD~4, if there were 4 commits.

I think. God I could be wrong about this though.

Just try your best and if it works, let me know and I’ll remove all this “I don’t know what I’m talking about” text and future readers will think I know everything. Web 2.0 rocks.

Send patches to…

Me drnicwilliams@gmail.com [update] or via the new Google Group.

Want to fork the git repo? Use a free account at Gitorious or GitHub.

Google Groups
Ruby on Rails: TextMate
Visit this group

Trundle to Rails 2.0 Bundle

Arguably, we just keep patching the bundle forever and bleeding edges will continue to live happily within the blood and muck of said existence.

But, lots of other people want nicely zipped up bundles. No doubt “e - the Text Editor” will want a “released” version so they can clean it of all the ugly things they can’t yet replicate like Macros. And eventually I’ll push it all down to the SVN repo and it will be released with future TextMate upgrades.

So, there will be a “Rails 2.0 compatible” grand opening one day soon. Probably before 14th of March 2008, when I’m giving a “What’s new in Rails 2.0?” talk at QCON London. Showing off the new bundle will be sweet.

That gives us 6 wks to refactor this bundle to make it a shining example of all that is wonderful in Rails 2.0. Every patch helps.

[Please consider Rails 1.2.6 and before developers when conceiving of patches, and please consult your doctor if pain persists.]