<p>Many many people&#8217;s first introduction to Ruby on Rails was the 15 minute video from <spanclass="caps">DHH</span> showing how you create a blog application with Rails. Nearly everyone finished that video asking one question: what was that editor? It is awesome.</p>

<p>Let&#8217;s take a stroll down memory lane. We pick up the action at the X minute mark:</p>

<p>[transition into a portion of the video that shows off TMs features, plus <spanclass="caps">DHH</span> saying &#8220;Whooops!&#8221;]</p>

<p>What is interesting, is that as fast as David is able to write his blog application, even with his detour demonstrating the now deleted scaffold command, he never uses any special TextMate extensions for Rails. He uses some <spanclass="caps">HTML</span> snippets and commands and some Ruby snippets and commands. The original Ruby on Rails extensions were in their infancy.</p>

<p>[Open Bundle Editor] A collection of TextMate extensions is called a &#8220;bundle&#8221;.</p>

<p>When working with Rails with TextMate you&#8217;ll use several &#8220;bundles&#8221;:</p>

<ul>

<li><spanclass="caps">HTML</span></li>

<li>Ruby</li>

<li>Ruby on Rails</li>

<li>JavaScript</li>

</ul>

<p>You might also use the ProtoType, jQuery or other JavaScript bundle if you use those libraries.</p>

<p>Ruby on Rails 2.0 was recently released and includes many improvements to</p>

<li>changes to some file name conventions [user_controller.rb &#8594; users_controller.rb, more commonly].</li>

</ul>

<p>The Ruby on Rails bundle has also been given a major upgrade to match all the changes for developing Rails 2.0 applications.</p>

<p>The snippets and commands we&#8217;re going to look at are actually described across all three bundles. Often it is the Rails bundle that reuses the <spanclass="caps">HTML</span> and Ruby bundles. For example, in an <spanclass="caps">HTML</span> file you have a variety of ways to create new elements. [examples] Within an html.erb file you can reuse all the same snippets and commands.</p>

<h2>Know thy Editor</h2>

<p>Overview key icons (see PeepCode TM video)</p>

<p>Preferences &gt; Advanced &gt; Folder References &gt; Folder Patterns: add &#8216;vendor/rails&#8217; and it will ignore that folder in any project &#8211; both from the Dock and from Search.</p>

<p>Access your bundles via Ctrl+Alt+Cmd+B.</p>

<p>Quick menu: Ctrl+Esc</p>

<p>Change language for a file, e.g. Ruby &lt;&#8212;&gt; Ruby on Rails. Either click the &#8220;L&#8221; section of the status bar and select the Language; or learn the Language shortcut. These always start with Shift+Alt+Cmd with a letter. Typically the letter is the first letter of the Language. So to choose either Ruby or Ruby on Rails, use Shift+Alt+Cmd+R and choose the language from the drop-down.</p>

<h2>Models and Migrations</h2>

<ul>

<li>Create new app</li>

<li>Go to app/controllers/application.rb (need a Ruby on Rails file)</li>

* In terminal, go to &#8220;/Applications/TextMate.app/Contents/SharedSupport/Support/lib&#8221; and rename/remove Builder.rb<br />

* Run migrations again</li>

</ul>

<ul>

<li>Go to post.rb<br />

* hm + comments; notice you can tab across to change fields if required<br />

* Also, hmt &#8594; for has_many :through*</li>

<li>Go to comments.rb<br />

* bt + post; notice the autocompletions are correct here, but still optional for rails so can be deleted<br />

* vp + name, body<br />

* [Ctrl-Esc &#8594; Models] All the validations are available as snippets based on the first letter of each word.</li>

<li>Place the cursor on &#8216;Comment&#8217; class name, Sft+Ctrl+Cmd+S &#8594; shows schema for this class. Alternately, place it on &#8216;post&#8217; to get the schema for Post class.</li>

</ul>

<h2>Testing</h2>

<p>I&#8217;ll talk more about navigating between files in a Rails application later, but for the moment, know that there is a special relationship between a model file and a unit test file. You can toggle between them with Alt+Cmd+DownArrow.</p>

<p>The Rails generator for models created this unit test file and a fixtures file.</p>

<p>First, let&#8217;s set up some fixtures for posts and comments. Go to posts.yml and create a &#8220;published&#8221; and a &#8220;unpublished&#8221; fixture. Now go to comments.yml &#8211; using Ctrl+Cmd+R to show posts.yml in the dock.</p>

<p><spanclass="caps">TODO</span> &#8211; how to move focus from editor to dock?</p>

<p>Within comments, create one comment:</p>

<pre>valid:

name: Dr Nic

body: Cool post

post:</pre>

<p>With Rails 2.0, your fixture ids are no longer required, and you can use Foxy Fixtures to select an associated fixture. Here we&#8217;d type &#8216;published&#8217; to reference that posts.yml fixture. But, since the column name is &#8216;post&#8217; we can get a drop-down list using Alt+Esc. We&#8217;ll use this same fixture autocompletion feature again within the test files.</p>

<p>Back to the comments unit test, and that dummy test needs removing.</p>

<p>Create a new test method with <code>deft</code> + <code>should_require_title</code>.</p>

<p>Type <code>posts(:)</code> and Alt+Esc to access the fixtures autocompletion. You can now select a posts.yml fixture. Note, the current implementation replaces the whole line, so if you need multiple or want a different instance variable you&#8217;ll need to make some manual changes.</p>

<spanclass="ident">assert</span><spanclass="punct">(</span><spanclass="attribute">@comment</span><spanclass="punct">.</span><spanclass="ident">errors</span><spanclass="punct">[</span><spanclass="symbol">:name</span><spanclass="punct">],</span> <spanclass="punct">&quot;</span><spanclass="string">Should be errors for name field</span><spanclass="punct">&quot;)</span>

<p>In order to write some functional tests for our blog, let&#8217;s generate a controller as it generates the functional test at the same time. [Ctrl-|] We won&#8217;t specify any actions for the moment, and we&#8217;ll clean away the open windows for the controller and the helper.</p>

<p>Since many functional tests start with the same setup, there are two functional test snippets to write tests faster. The last letter maps the the http method to be used for the test: g for <spanclass="caps">GET</span> and p for <spanclass="caps">POST</span>.</p>

<p>To create a test for the index action, use <code>deftg + 'index'</code>. Then delete the two optional @model sections.</p>

<p>Next, to load an instance variable into the test, type <code>asg + 'posts'</code></p>

<p>Type <code>ass</code> and press &amp;#x21E5;. Type <code>div#posts</code>, press &amp;#x21E5; and &amp;#x2326;, then &amp;#x21E5; twice to place the cursor within the <code>assert_select</code> block:</p>

<p>Now we create a test for the &#8216;show&#8217; action. Type deftg and &#8216;show&#8217;, and then &#8216;post&#8217;. Then tab into &#8216;fixture_name&#8217; and delete it. Now we&#8217;ll autocomplete on fixtures again. Alt+Esc and select &#8216;published&#8217;.</p>

<p>Now copy the &#8216;div.post&#8217; assert_select line for this test, but change the :count to 1.</p>

<p>To run our functional tests, use Ctrl+\.</p>

<h2>Controllers and Routing</h2>

<p>Similarly to navigating between model and unit test files, you can toggle between functional tests and controllers via Alt+Cmd+DownArrow.</p>

<p>In the controller, type <code>index</code> and use Shift+Enter to convert it to a method. Press BackSpace to delete the arguments.</p>

<p>One thing to note for developers of Rails apps using older versions of Rails. If you are in a template file with the extension .rhtml, then it will navigate to the singular controller name &#8216;post&#8217;, rather than the plural default for controllers. This is for backwards compatibility with older naming conventions.</p>

<p>So we can create a new <code>posts_controller.rb</code> by returning to the post.rb or post_test.rb files, and navigating to the matching controller. It doesn&#8217;t exist so a blank file is created.</p>

<p>We have a simple way to create new controller classes; the <code>cla</code> snippet has a &#8216;Create controller class&#8217; option. Select that, and type &#8216;Posts&#8217; and then &#8216;post&#8217; to create our posts_controller.rb class.</p>

<p>For simpler actions, use the standard techniques for new methods, def + &#8216;new&#8217; to create the &#8216;new&#8217; method.</p>

<p>For some of the common, more complex controller actions there are also snippets. For the create action, type &#8216;defcreate&#8217; and fill out the template with &#8216;post&#8217;.</p>

<p>What I want the &#8216;create&#8217; action to do is redirect back to the main blog controller for a page. Originally, I could use &#8216;recai&#8217; for <code>redirect_to :controller =&gt; "blog", :action =&gt; "show", :id =&gt; @post</code> but its uncool to use anonymous paths.</p>

<p>So instead let&#8217;s just enter a named route that sounds nice, replace <code>@post</code> with <code>blog_post_path(@post)</code>.</p>

<p>[Change to the &#8216;routes.rb&#8217; file.] So finally let&#8217;s setup our routes. I&#8217;m going to delete all the default comments and default routes, and reconstruct it with named routes.</p>

<p>Within a routes file, you have the three &#8216;map&#8217; snippets. As you&#8217;ll see in moment, the resources snippets include a block for nested resources.</p>

<p>So we&#8217;ll use &#8216;map&#8217; to create named routes. Leave the name as &#8216;connect&#8217; for anonymous routes. It is handy to know a Ruby snippet here: tabbing on colon (:) creates a hash key/value pair.</p>

<p>We could place this route within a with_options block, using &#8216;mapwo&#8217;. Then add <code>map.root</code> within it.</p>

<p>For our posts controller, we&#8217;ll use the resources snippets. We use &#8216;maprs&#8217; and change &#8216;resource&#8217; to &#8216;posts&#8217; and then we can tab into the block. Say we wanted comments to be a nested resource of posts, then we&#8217;d use &#8216;maprs&#8217; again, and change &#8216;map&#8217; to &#8216;post&#8217; and remove the block. [then delete the comment resource + post&#8217;s block].</p>

<p>There is also a shortcut for the respond_to block &#8211;&#8216;rest&#8217;, which gives a default html response. To add additional response formats, tab on &#8216;wants&#8217;. [remove these examples from new method]</p>

<p>Now let&#8217;s have a final look at functional tests for our create actions, which will require a <spanclass="caps">POST</span> request. [try to change to functional test] We don&#8217;t have a posts_controller_test.rb, so it creates a blank file for us.</p>

<p>To create a functional test class, use &#8216;cla&#8217; again and select &#8216;Create functional test class&#8217;, and type &#8216;Posts&#8217; for the class name prefix. Save the file, close the window and reopen within the project, otherwise some commands might not work if the file is initially not saved.</p>

<p>Remember that test methods are created with &#8216;deft&#8217;, and the <spanclass="caps">GET</span> + <spanclass="caps">POST</span> methods are created with deftg and deftp. Let&#8217;s test our create action with &#8216;deftp&#8217;.</p>

<p>Enter &#8216;post&#8217;, but remove the two optional sections as we&#8217;re creating a new object, not updating an existing object. Within the <code>:post =&gt; { }</code>, type : and tab to create the hash key values.</p>

<p>If you just want to run the tests in the current file, or in fact run any Ruby file, use Cmd+R. As we can see, this test passes.</p>

<h2>Views</h2>

<p>[back to posts_controller.rb]</p>

<p>In the posts controller, we have a new action but we haven&#8217;t created a template yet. As before, we can use the Navigation cmd to change from the controller to a view. In this case, the view is based on the current method. So we place the cursor in the new method, and it will ask us to create a new.html.erb file. Here is your opportunity to rename the template with alternate format or template extensions, say .xml.builder. But we&#8217;ll use .html.erb for now.</p>

<p>We&#8217;ll use &#8216;ffe&#8217; and enter &#8216;post&#8217;. In Rails 2.0, the form_for helper is very powerful and knows from the object it is passed whether it is creating or updating an object.</p>

<h3>Diagram: f. &#8211; list of available helpers; or use first initial of helpers&#8217; names (fftf &#8211; text_field)</h3>

<p>Inside the form_for block we have two ways to access the common helpers.</p>

<p>By using &#8216;f.&#8217; it reminds us what helpers are available and tells us what their tab completions are.</p>

<p>Now let&#8217;s put each label or form field in a separate paragraph. Select those lines and use &#8216;Wrap Each Selected Line in Open/Close&#8217;&#8211; Shift+Ctrl+Cmd+W, and type &#8216;p&#8217;.</p>

<h3>Diagram: Partials &#8211; Shift-Ctrl-H</h3>

<p>Since the form_for helper works with saved and unsaved model objects its easily reusable within new and edit templates. So let&#8217;s extract it as a partial. [do it] And now the render can be pasted into an edit.html.erb file as required.</p>

<p>[go to browser http://localhost:3000/posts/new]<br />

Now we can fire up the server and have a look at our form and use it. [submit form]</p>

<p>As requested, the browser is redirected to the public post page; which we haven&#8217;t implemented yet. So let&#8217;s do that.</p>

<p>We head back to the blog_controller, and create the show.html.erb via navigating away from the show action.</p>

<p>Create a div and set its class to post, then layout the title and body:</p>

<divclass="post">

<h3>&lt;%= @post.title %&gt;</h3>

&lt;%= @post.body %&gt;

</div>

<p>If we run our tests, the &#8216;show&#8217; action test is now passing.</p>

<p>[Shft+Ctrl+H] So we can reuse it in the index.html.erb file, let&#8217;s move it to a partial called &#8216;post&#8217; and remove the &#8216;@&#8217; signs to reference a local variable instead of an instance variable.</p>

<p>The returned &#8216;render&#8217; expression isn&#8217;t quite right as we need to pass the @post object into the partial. Let&#8217;s remove it and use the &#8216;render partial&#8217; snippets.</p>

<p>Create &lt;%= %&gt; and inside use &#8216;rpo&#8217; and set the :object =&gt; @post.</p>

<p>Now we create index.html.erb and use &lt;%= %&gt; with &#8216;rpc&#8217; and &#8216;post&#8217;. The tests require that its wrapped in a div with id=&#8220;posts&#8221;. So select all, and Shift+Ctrl+W + div id=&#8220;posts&#8221;.</p>

<p>In addition to html.erb templates, Rails supports any combination of output format and template engine. As appropriate you can combine html or javascript or xml with erb or rjs or builder, or any other 3rd party templating system such as haml.</p>

<p>The Rails TextMate bundle provides varying support for different combinations.</p>

<p>All these snippets include the page prefix and are nice ways to start each <spanclass="caps">RJS</span> expression.</p>

<p>[remove all lines; rename with .erb] Another way to generate JavaScript within Rails is with the .js.erb extension. Instead of <spanclass="caps">RJS</span> expressions, you write pure JavaScript, but you can embed ruby using erb.</p>

<p>A new syntax supported in the bundle is JavaScript (Rails), which maps to .js.erb files. That is, JavaScript files that permit embedded Ruby. This means, within the &lt;%= %&gt; tags you have access to your Ruby snippets and syntax highlighting.</p>