For Mac users, TextMate is powerful tool for writing code. But having a great tool is pretty pointless unless you know how to use it. By spending a few hours learning about TextMate’s features you can almost half the time it takes you to write code. This tutorial will walk you through creating a simple Rails app using some of TextMate’s more advanced features.
Before you start, I’d recommend you get the latest version of the Ruby on Rails TextMate bundle and install it. Also—I realise the application from this tutorial is far from perfect, but I figured this would be a good way to introduce the features and show examples of how they can be used. If you have any suggestions please leave a comment below.
Lets create a new rails app, in your terminal type the following:
rails text_mate_demo
Once the app has been created, type cd text_mate_demo
followed by mate .
to open the full application in TextMate.
cd text_mate_demo
mate .
In true Rails fashion, this demo is going to create a simple blog site. To create our first model type the following in your terminal window:
script/generate model Post title:string body:text
script/generate model Comment name:string body:text post:references
rake db:migrate
Note–TextMate does come with commands for calling generator scripts but I’ve never been able to get them to work. To try them out hit: ctrl + | (or ctrl + shift + \).
Next, jump back to TextMate and type ctrl + alt + cmd + D to hide the project drawer–we won’t be using it in this tutorial.
Instead we’ll navigate by pressing cmd + T and typing (part of) the name of the file you want to open. Lets go to post_test.rb
and write some unit tests for our Post model. Type cmd + T followed by “poste” and hit enter.
For our unit tests we’ll create a setup method. Here’s a good chance to introduce tab triggers. Type def
followed by the tab key. This should create a new empty method with the name highlighted. Name this method “setup” and hit tab again to jump down a line.
To setup our unit tests lets create a new Post instance and check if it’s valid.
require 'test_helper'
class PostTest < ActiveSupport::TestCase
def setup
@post = Post.new
@post.valid?
end
end
On a new line type “test” and hit tab to create a new test. Lets call it “should not be valid without title”. As a shortcut to writing assert_equal
, you can write ase
and hit tab, then tab for the expected value and tab again for the actual value.
I’ve also added another two tests to meet our requirements:
require 'test_helper'
class PostTest < ActiveSupport::TestCase
def setup
@post = Post.new
@post.valid?
end
test "should not be valid without title" do
assert_equal @post.errors.on(:title), "can't be blank"
end
test "should not be valid without a body" do
assert_equal @post.errors.on(:body), "can't be blank"
end
test "should have many comments" do
@post = posts(:one)
2.times { @post.comments.create! :name => "John Smith", :body => "This is a comment" }
end
end
Save this page and then press ctrl + \ followed by 7 to test units. The three tests should fail. Now press alt + cmd + down to jump to post.rb.
Our unit tests specify that our posts should not be valid without a title or a body. To quickly add a validates_presence_of
validation, type vp
and then press tab. Now type “title”
and then press tab and delete to clear the extra options (which we don’t require here).
For our second validation we’re going to try something different. On a new line, type va
and then press esc. The escape key can be used to auto-complete any method, constant or variable name that’s already present on that document. This is a great way to save time retyping long method/variable names.
To add our has_many
association, type hm
and hit tab. Type comment
and then tab, delete again.
These validations could do with being DRYed up but we’ll leave that for now. In the meantime, press cmd + / to start a comment and leave yourself a TODO note for later # TODO – DRY this up
.
class Post < ActiveRecord::Base
# TODO - DRY this up
validates_presence_of :title
validates_presence_of :body
has_many :comments
end
Now we need to create a Comment model so our third test passes.
script/generate model Comment name:string body:text post:references
rake db:migrate
Quick note – jump to comments.yml and populate the “post”
attribute like so:
one:
name: MyString
email: MyString
post: one
body: MyText
two:
name: MyString
email: MyString
post: two
body: MyText
Now jump to comment_test.rb
, again using cmd + T and add some tests like so:
require 'test_helper'
class CommentTest < ActiveSupport::TestCase
def setup
@comment = Comment.new
@comment.valid?
end
test "should belong to post" do
assert_equal( posts(:one), comments(:one).post )
end
test "should not be valid without name" do
assert_equal(@comment.errors.on(:name), "can't be blank")
end
test "should not be valid without body" do
assert_equal(@comment.errors.on(:body), "can't be blank")
end
end
Again, run the tests, see the failures and then write the model:
class Comment < ActiveRecord::Base
belongs_to :post
validates_presence_of :name, :body
end
The tests should now pass.
There’re a whole bunch of shortcuts for commonly used methods. Most of them are used by writing a few letters and then hitting tab. To browse through them go to Bundles > Ruby on Rails.
This may be a good time to DRY up the Post model. Press ctrl + shift + T to have a look at the annotations you’ve left in your code. You should see 1 TODO in post.rb. Click on the link to jump to this comment and remove the duplication:
class Post < ActiveRecord::Base
validates_presence_of :title, :body
has_many :comments
end
Now we need a controller for our posts. By pressing shift + alt + cmd + down you should see the goto menu. Press 1 for controller. Since there isn’t already a posts controller TextMate will ask if you’d like to create one. Click “create”. (From this point let’s just imagine we’ve written tests first).
Now we need an index action to display our posts. Again, using our “def” then tab shortcut, create an index action and try to add some code here to find all of the posts and order them by “created_at DESC”. But crap! We’ve forgotten the different options available for the find method. Here comes the coolest trick TextMate has to offer…
Highlight the find method and press ctrl + H. A window will pop up with either 2 or 3 options. If you only see 2, then select “Documentation for Selection” and select “ActiveRecord::Base::find”. If you do have the 3rd option “Documentation for Word” then select it. This gives you a chance to browse the Rails documentation for any method and see examples of how to use it. This is a really powerful tool! By pressing cmd + H you can see the documentation for practically any gem you’ve installed. It also works for other languages like HTML and CSS so it’s a great way to learn as you go.
You quickly read up on find and see the options available. Now you can add the required code to the index action:
class PostsController < ApplicationController
def index
@posts = Post.find :all,
:conditions => ['created_at > ?', 3.months.ago],
:order => "created_at DESC",
:limit => 5,
:include => :comments
end
end
If you want to clean up this hash a little, select the options by holding alt and clicking and dragging from before “:conditions” to the bottom right – just after “:comments”. With the hash selected, press alt + cmd + ] to align assignments. This should help make your code a little easier for others to read.
def index
@posts = Post.find :all,
:conditions => ['created_at > ?', 3.months.ago],
:order => "created_at DESC",
:limit => 5,
:include => :comments
end
To collapse this method and neaten your controller, press alt + cmd + 2. You can collapse foldings at different levels by using alt + cmd + 1,2,3 etc.
With the cursor still in the index action, press alt + cmd + down to create the view template for the index action.
To create rhtml tags press ctrl + >. By pressing this again you can cycle through the various erb tags available. To create new html tags press ctrl + <. Using this method, add the post title to our new heading tags like so:
<% @posts.each do |post| %>
<h3><%= post.title %></h3>
<%= post.body %>
<% post.comments.each do |comment| %>
<% div_for comment do %>
<p><%= comment.name %></p>
<p><%= comment.body %></p>
<% end %>
<% end %>
This tutorial could go on for quite some time but those are the commands that I feel are the most useful. You may have already noticed too that TextMate already has its own Rails tutorial which covers loads of the snippets etc. You can access this tutorial by pressing cmd + H and selecting “View Demo Help”.
If there’s anything you’d like to see here that I haven’t covered, feel free to leave a comment.