<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
  <channel>
    <title>Learning Rails</title>
    <link>http://www.buildingwebapps.com/learningrails" /></link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Learning Rails is a podcast and screencast series that teaches how to build web applications with Ruby on Rails.</description>
    <itunes:author>Michael Slater and Christopher Haupt</itunes:author>
    <itunes:subtitle>The easy way to learn Ruby on Rails</itunes:subtitle>
    <itunes:owner>
      <itunes:name>Michael Slater and Christopher Haupt</itunes:name>
      <itunes:email>contact@webvanta.com</itunes:email>
    </itunes:owner>
    <itunes:explicit>No</itunes:explicit>
    <itunes:category text="Technology" />
    <itunes:image href="http://www.buildingwebapps.com/learningrails.gif" />
    
        
        <item>
          <title>23: Performance Analysis with the New Relic RPM</title>
          <description>&lt;p&gt;For most non-trivial Rails applications, there's going to be some performance issues. Rails has been subject to a lot of performance criticism, but in reality, Rails can perform very well&amp;mdash;it just takes some tuning to get there. In this screencast, which is sponsored by New Relic, we're going to focus on the tools and service that New Relic provides for monitoring and analyzing the performance of Ruby on Rails applications.&lt;/p&gt;</description>
          <pubDate>Mon, 29 Sep 2008 21:00:56 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79348-performance-analysis-with-the-new-relic</guid>
          <link>http://www.buildingwebapps.com/podcasts/79348-performance-analysis-with-the-new-relic</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-23.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we take a look at techniques for monitoring and improving the performance of your Rails application.&lt;/p&gt;
&lt;p&gt;Please note that, while we&amp;rsquo;ve tried to make these notes complete, they aren&amp;rsquo;t the full tutorial; that&amp;rsquo;s in the screencast, which you can access via the button on the left. We recommend that you right-click on the button and choose Save As to download it to your computer.&lt;/p&gt;
&lt;p&gt;This lesson does not depend on the sample application code, although you can start with the sample application code (in the &lt;a href=&quot;http://github.com/chaupt/learning-rails-sample-app&quot;&gt;Github repository&lt;/a&gt;) to explore the developer mode of the New Relic plugin, as we do in this screencast.&lt;/p&gt;
&lt;h2&gt;Improving the Performance of Your Rails Application&lt;/h2&gt;
&lt;p&gt;For most non-trivial Rails applications, there&amp;rsquo;s going to be some performance issues. Rails has been subject to a lot of performance criticism, but in reality, Rails can perform very well&amp;mdash;it just takes some tuning to get there.&lt;/p&gt;
&lt;p&gt;Rails makes it quick and easy to get your application up and running, and in the process it also makes it easy to ignore a lot of issues that require some attention when performance is critical. Fortunately, there are plenty of tools and techniques at your disposal when it comes to performance tuning. You&amp;rsquo;ll need to look for slow queries, for queries that are being performed too frequently, and for opportunities to cache pages and parts of pages.&lt;/p&gt;
&lt;p&gt;In this screencast, which is sponsored by &lt;a href=&quot;http://newrelic.com&quot;&gt;New Relic&lt;/a&gt;, we&amp;rsquo;re going to focus on the tools and service that New Relic provides.&lt;/p&gt;
&lt;p&gt;A word about our sponsorships: we think of this like public radio. Sponsors underwrite the cost of producing and distributing a lesson, and we give them opportunities to review the content. But the words and opinions are all ours, and we wouldn&amp;rsquo;t say anything we didn&amp;rsquo;t personally stand behind.&lt;/p&gt;
&lt;p&gt;New Relic is being used by a lot of folks who we&amp;rsquo;d trust to have made a good choice: &lt;a href=&quot;http://37signals.com&quot;&gt;37signals&lt;/a&gt; (Basecamp and other apps), &lt;a href=&quot;http://twitter.com&quot;&gt;Twitter&lt;/a&gt;, &lt;a href=&quot;http://lighthouseapp.com&quot;&gt;Lighthouse&lt;/a&gt;, and &lt;a href=&quot;http://shopify.com&quot;&gt;Shopify&lt;/a&gt;, to name a few. It&amp;rsquo;s also included in all hosting packages at &lt;a href=&quot;http://engineyard.com&quot;&gt;Engine Yard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are alternatives to New Relic&amp;rsquo;s service, such as those from &lt;a href=&quot;http://fiveruns.com&quot;&gt;Five Runs&lt;/a&gt; and the recent entrant from &lt;a href=&quot;http://rubysophic.com&quot;&gt;Rubysophic&lt;/a&gt;. There&amp;rsquo;s related services, such as Scout, and a variety of open source performance tuning tools, such as http-perf.&lt;/p&gt;
&lt;p&gt;For more information on a variety of performance optimization tools and techniques, see the &lt;a href=&quot;/topic/24292-performance-tuning-for-ruby-on-rails&quot;&gt;performance tuning&lt;/a&gt; section of the BuildingWebApps site.&lt;/p&gt;
&lt;h2&gt;Installing the New Relic Plugin&lt;/h2&gt;
&lt;p&gt;The New Relic &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; service connects to your application via a plug-in that they provide, called the agent. Installing it is as simple as for any other plug-in:&lt;/p&gt;
&lt;pre&gt;
script/plugin install http://svn.newrelic.com/rpm/agent/newrelic_rpm
&lt;/pre&gt;
&lt;p&gt;There&amp;rsquo;s two modes in which &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; can run. In development mode, it runs on your local development server. In either mode, the plugin hooks into the Rails framework to automatically collect performance data.&lt;/p&gt;
&lt;p&gt;In Development mode, you examine the performance data &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; collects via views that it installs into your application. In this mode, &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; stores only the last 100 &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; transactions, and it keeps all the analysis data in memory, so it doesn&amp;rsquo;t touch your database.&lt;/p&gt;
&lt;p&gt;In production mode, it runs on your production server and sends data to New Relic&amp;rsquo;s server once per minute. New Relic&amp;rsquo;s server then provides performance reports that you can view via the web, without impacting your production server.&lt;/p&gt;
&lt;p&gt;In the screencast, we explore the basic features of the New Relic system, and then dive into a specific performance optimization example. For details on New Relic&amp;rsquo;s system, check out their &lt;a href=&quot;http://sites.google.com/a/newrelic.com/rpm-docs/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll start with development mode, and then take a look at a real application running in production mode.&lt;/p&gt;
&lt;h2&gt;Exercise the Application&lt;/h2&gt;
&lt;p&gt;With the plug-in installed in our sample application, we&amp;rsquo;ll start the server:&lt;/p&gt;
&lt;pre&gt;
  script/server
&lt;/pre&gt;
&lt;p&gt;And then browse to &lt;code&gt;localhost:3000&lt;/code&gt;. So far, this should look very familiar.&lt;/p&gt;
&lt;p&gt;Before we look at the analysis screens, we need some data to analyze. So let&amp;rsquo;s click around to several of the pages, and then log in and go to the admin interface.&lt;/p&gt;
&lt;h2&gt;Viewing Performance Data in Developer Mode&lt;/h2&gt;
&lt;p&gt;Now, to view the performance data, just browse to &lt;code&gt;localhost:3000/newrelic&lt;/code&gt;. In doing so, you&amp;rsquo;re accessing a controller and views that the New Relic plug-in installed. The data is coming from the in-memory cache of information about the most recent 100 controller actions.&lt;/p&gt;
&lt;p&gt;The main &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; Developer Mode page lists the URLs for each of these actions, and the total time taken to complete each one. As you can see, nothing in this application takes very long, as you&amp;rsquo;d expect&amp;mdash;there&amp;rsquo;s nothing here that&amp;rsquo;s doing very much work.&lt;/p&gt;
&lt;p&gt;Click on one of the URLs, and you&amp;rsquo;ll see a pie chart of where the time goes for that action. In the case of one of our simple &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; pages, about half the time is in the controller action, and you can see how the remaining half of the time is split among the rendering, database, and Active Record code. Below the pie chart, you&amp;rsquo;ll see the items listed out; click the question mark next to any of them to see a description and some tuning hints.&lt;/p&gt;
&lt;p&gt;Click the Details link to see a time-sequential breakdown of the components.&lt;/p&gt;
&lt;p&gt;The Duration column shows the total time spent in a particular method, including time spent in any other methods called by the selected method. The Exclusive column subtracts off time spent in framework code called in the method, such as ActiveRecord methods.&lt;/p&gt;
&lt;p&gt;For each line that involves a database query, you can click on the &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; link to see the query that was produced, as well as the stack trace that shows the related code.&lt;/p&gt;
&lt;h2&gt;Running in Production Mode&lt;/h2&gt;
&lt;p&gt;In production mode, the agent doesn&amp;rsquo;t accumulate data in memory; it sends it to New Relic&amp;rsquo;s servers. You then log in to the New Relic application, running on their servers, to view your data.&lt;/p&gt;
&lt;p&gt;New Relic has recently released a free version of its production mode service, called &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; Lite. It is limited to a couple of views, and to the last 30 minutes of data, but you can use it on any number of servers with any number of hosts (previously, the free plan was limited to a 90-day trial period and two mongrels).&lt;/p&gt;
&lt;p&gt;On a paid plan, which is priced starting at $40 per host for the Bronze subscription, you can view data from the last 7 days and you get many more views. The premium plans provide more ways to analyze the data.&lt;/p&gt;
&lt;p&gt;The Silver and Gold plans provide longer data retention of one and three months respectively  and a bunch of advanced views and features, including transaction tracing, automatic incident detection, error tracking, day to day and week by week comparisons, and scalability analysis.&lt;/p&gt;
&lt;p&gt;To use &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; in production mode, you need to get a license key from New Relic, by signing up for either a paid or a free account. Your confirmation email will include a &lt;code&gt;newrelic.yml&lt;/code&gt; file, which you should put in your config directory. There&amp;rsquo;s a variety of other settings you can tweak in that file. (You can also just copy your key from the New Relic site and paste it into the &lt;code&gt;newrelic.yml&lt;/code&gt; file that the plugin installs.)&lt;/p&gt;
&lt;p&gt;With the agent and &lt;code&gt;newrelic.yml&lt;/code&gt; file installed in your application, deploy it to the production server. That&amp;rsquo;s all it takes to begin collecting performance data.&lt;/p&gt;
&lt;h2&gt;Viewing Production Mode Performance Data&lt;/h2&gt;
&lt;p&gt;In production mode, there&amp;rsquo;s much more information available. Since it&amp;rsquo;s accumulated in New Relic&amp;rsquo;s database (currently at the rate of more than 10 billion reports a month for all customers combined), you can view data from a relatively long period of time. And the ways you can drill down into the data are much more flexible than in developer mode.&lt;/p&gt;
&lt;p&gt;Browse to &lt;code&gt;http://rpm.newrelic.com&lt;/code&gt;, and log in with your (free or paid account) user name and password.&lt;/p&gt;
&lt;p&gt;In the screencast, we look at the live performance data for BuildingWebApps.com, and then show how we track down a missing database index, as well as the need for more caching, and then make changes to the code and verify that the performance did indeed improve. You&amp;rsquo;ll have to watch the screencast to see this information, since it is not publicly accessible.&lt;/p&gt;
&lt;p&gt;The home page lists each of the servers associated with the account. In our case, we have two production slices and one staging slice. You can define server clusters, so the production data all appears together.&lt;/p&gt;
&lt;p&gt;This &amp;ldquo;stoplight&amp;rdquo; view shows you at a glance if everything appears to be running ok. If all the lights are green, it&amp;rsquo;s good. Yellow means something is getting marginal, and red means trouble. You can define the thresholds for these color levels by clicking the &amp;ldquo;traffic light&amp;rdquo; icon next to the host or cluster name.  You can click on any of the numbers next to the lights to go to a detail page.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll start by going to the overview page for the production server, by clicking on the Production label. From the strip at the top of any of these pages you can choose (from the three pop-up menus) which server or cluster you want to look at, which view you want, and what time period you want to examine. You can choose a period as short as 30 minutes, which lets you see a data point per minute, or extend a period as long as the last 7 days (one month for the Silver plan and three months in the Gold plan).&lt;/p&gt;
&lt;p&gt;These graphs show that our application&amp;rsquo;s &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt;, memory, and database usage levels, as well as the response times, have been relatively stable, with modest fluctuations.&lt;/p&gt;
&lt;p&gt;On the Lite plan, there&amp;rsquo;s just one more view available. The Controllers view shows the overall throughput and response time graphs, plus a list of the slowest 20 controller actions during the time interval being shown.&lt;/p&gt;
&lt;h2&gt;Advanced Views&lt;/h2&gt;
&lt;p&gt;At the Bronze level (the least expensive paid version), you get a bunch of additional views:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Page Volume: Shows the number of views for the 15 most frequently viewed URLs during the selected interval&lt;/li&gt;
    &lt;li&gt;Active Record: Shows the total time spent in the database for find, save, and destroy operations, the database response time, and actions that are the top 15 database consumers&lt;/li&gt;
    &lt;li&gt;Index Hunter: Shows the slowest Active Record queries, which are good places to look for missing indexes&lt;/li&gt;
    &lt;li&gt;Time Consumption: The top 15 consumers of time &amp;mdash; a good way to find the places where optimization would have the biggest impact&lt;/li&gt;
    &lt;li&gt;Cluster Breakout: How performance varies for each cluster and each Mongrel&lt;/li&gt;
    &lt;li&gt;Compare with Yesterday: Are things better or worse than yesterday?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Silver levels adds:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Transaction Tracer: Lists all &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; transactions that took more than two seconds; click on one to drill down into the details&lt;/li&gt;
    &lt;li&gt;Errors: All Rails errors, nicely aggregated; click one for details&lt;/li&gt;
    &lt;li&gt;Incidents: List of metrics that were more than 50% worse than for the same time period one week ago&lt;/li&gt;
    &lt;li&gt;Week-to-Week Comparison: Compare summary metrics against one week ago&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the Gold level adds:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Scalability Analysis: Plots performance vs. application load&lt;/li&gt;
    &lt;li&gt;Response Time Report: A configurable report that shows the sources of response time degradation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tracking Down a Performance Issue&lt;/h2&gt;
&lt;p&gt;To see an example of a performance problem being tracked down and corrected, watch the screencast (right-click the button at the top left to save the video file to your computer).&lt;/p&gt;
&lt;p&gt;The tasks we demonstrate on the live BuildingWebApps.com code include:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Identifying when too many transactions are happening (lots of small calls to our DB adding up). We proceed to implement a caching solution to reduce the number of calls.&lt;/li&gt;
    &lt;li&gt;Identifying longer duration queries that are sometimes caused by lack of proper indicies on relevant database tables. We apply an index and see our queries change from traversing through many DB rows of data to near constant time access.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We give a demonstration of the MySQL &lt;span class=&quot;caps&quot;&gt;EXPLAIN&lt;/span&gt; command, and then show that the same information is available within NewRelic in both development and production modes.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:50:00</itunes:duration>
        </item>
        
        <item>
          <title>22: Deploying to a Public Web Server</title>
          <description>&lt;p&gt;In this lesson, we finally deploy our application to a public web server. We describe how to use MySQL for the production database, set up the Passenger application server to work with Apache, and configure and use Capistrano to manage your deployments.&lt;/p&gt;</description>
          <pubDate>Mon, 01 Sep 2008 04:56:01 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79347-deploying-to-a-public-web-server</guid>
          <link>http://www.buildingwebapps.com/podcasts/79347-deploying-to-a-public-web-server</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-22.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we finally deploy our application to a public web server.   Please note that, while we&amp;rsquo;ve tried to make these notes complete, they aren&amp;rsquo;t the full tutorial; that&amp;rsquo;s in the screencast, which you can access via the button on the left. We recommend that you right-click on the button and choose Save As to download it to your computer.&lt;/p&gt;
&lt;p&gt;The code used in this lesson has all been checked in to the &lt;a href=&quot;http://github.com/chaupt/learning-rails-sample-app/&quot;&gt;Github repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Rails deployment overview&lt;/h2&gt;
&lt;p&gt;Deploying a Rails application is more complex than for a simple web site or &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; application for two reasons:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;In general, a separate application server is used to keep the Rails application in memory, and execute requests that come in through the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; server. This requires more configuration, and that the application server be restarted when the code is changed.&lt;/li&gt;
    &lt;li&gt;Static and &lt;span class=&quot;caps&quot;&gt;PHP&lt;/span&gt; sites are typically deployed by simply uploading files to the server, with &lt;span class=&quot;caps&quot;&gt;FTP&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;SFTP&lt;/span&gt;. Although there is nothing about Rails that requires it, Rails applications are almost universally deployed by having the server check the code out from a version control system. (This is a better practice for all kinds of sites, but it less often used with simpler technologies.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The flow of a deployment is thus as follows:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Make changes to your code locally&lt;/li&gt;
    &lt;li&gt;Test the changes&lt;/li&gt;
    &lt;li&gt;Check the changes in to version control (and push to the main repository, if using Git)&lt;/li&gt;
    &lt;li&gt;Optionally, display a maintenance page to replace the site while it is being updated&lt;/li&gt;
    &lt;li&gt;Perform a checkout of the code from the version control system to the web server&lt;/li&gt;
    &lt;li&gt;Run any migrations that the new code requires&lt;/li&gt;
    &lt;li&gt;Restart the application server&lt;/li&gt;
    &lt;li&gt;Disable the maintenance page, if any&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Although this may sound complicated, with the right tools it is quite simple once you&amp;rsquo;re all set up. The key tool is a program called &lt;a href=&quot;http://capify.org&quot;&gt;Capistrano&lt;/a&gt;, which can automate the entire process (starting with step 4). In the previous few lessons, you&amp;rsquo;ve been through the first three steps; by the end of this lesson, you&amp;rsquo;ll have been through the whole process.&lt;/p&gt;
&lt;h2&gt;Choosing a web and application server configuration&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a huge array of choices to be made when it comes to server software selection and configuration. We&amp;rsquo;ll describe one of many possible approaches in this lesson. You&amp;rsquo;ll almost surely want to explore other options, and need to learn more about issues specific to your server, to do your own deployments. Here&amp;rsquo;s where to find some useful resources on our &lt;a href=&quot;http://www.buildingwebapps.com&quot;&gt;BuildingWebApps&lt;/a&gt; site:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24356-the-linux-open-source-operating-system-for&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24358-hosting-alternatives-for-ruby-on-rails&quot;&gt;Rails Hosting&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24348-application-servers-for-ruby-on-rails&quot;&gt;Rails Application Servers&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24383-http-servers-the-front-end-for&quot;&gt;&lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; Servers&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24400-automation-for-web-application-development-and&quot;&gt;Automation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also highly recommend the book &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0978739205/buildicom-20&quot;&gt;Deploying Rails Applications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the past two years or so, the most widely used setup has been &lt;a href=&quot;/topic/24384-the-apache-web-server-a-common&quot;&gt;Apache 2.2&lt;/a&gt; as the front-end server, which processes &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; requests, serves static files (including JavaScript, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, and images, as well as any cached &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; pages) and passes (&amp;ldquo;proxies&amp;rdquo;) requests that must handled by Rails to the application server(s). Many people have started using &lt;a href=&quot;/topic/24385-the-nginx-lightweight-http-web-server&quot;&gt;Nginx&lt;/a&gt; instead of Apache as the front-end server.&lt;/p&gt;
&lt;p&gt;Whether Apache or Nginx is the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; server, the most widely used application server is &lt;a href=&quot;/topic/24349-the-mongrel-application-server-for-ruby&quot;&gt;Mongrel&lt;/a&gt;, which is installed as a gem. Mongrel handles only one request at a time, so most servers use two or more Mongrels (dozens for a system designed to handle high loads), and another gem called mongrel_cluster manages the Mongrels.&lt;/p&gt;
&lt;p&gt;Setting this up can be a little complex, and if you&amp;rsquo;re going to take this route, going with a hosting company that provides a &amp;ldquo;stock&amp;rdquo; configuration, and knows how to support it, is usually a good investment.&lt;/p&gt;
&lt;p&gt;A relatively new alternative, &lt;a href=&quot;http://modrails.org&quot;&gt;Passenger&lt;/a&gt; (a.k.a. mod_rails), makes all this much simpler by operating as an Apache module. Not only does it eliminate most of the configuration, it shuts down Rails processes that have been idle for a while, freeing the memory they use. This has the disadvantage of a several-second delay the first time an idle site is accessed, but it is a tremendous advantage for a server that is running lots of low-traffic sites, since they don&amp;rsquo;t always need to sit in memory.&lt;/p&gt;
&lt;p&gt;In this lesson, we&amp;rsquo;ll use Apache 2.2 with Passenger.&lt;/p&gt;
&lt;h2&gt;Set up database configuration for MySQL&lt;/h2&gt;
&lt;p&gt;Before we get to the server setup, we need to do a little work on our application.&lt;/p&gt;
&lt;p&gt;So far, we&amp;rsquo;ve used &lt;a href=&quot;/topic/24373-sqlite&quot;&gt;SQLite&lt;/a&gt; for our development and test databases, and the production database is set up to use it as well. &lt;a href=&quot;/topic/24368-the-mysql-database-server-for-web&quot;&gt;MySQL&lt;/a&gt; is generally a better choice for production, so let&amp;rsquo;s change the production configuration.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;config/database.yml&lt;/code&gt;, replace the section under &lt;code&gt;production&lt;/code&gt; to the following:&lt;/p&gt;
&lt;pre&gt;
adapter: mysql
database: learningrails_production
username: deploy
password: secret
host: localhost
&lt;/pre&gt;
&lt;p&gt;The development and test databases can remain set up for SQLite.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve also added a &lt;a href=&quot;http://github.com/mzslater/learning-rails-sample-app/tree/master/db/migrate/011_default_pages.rb&quot;&gt;migration&lt;/a&gt;) that will create all the pages and a couple of sample resource categories and links, so the application when deployed should look much like the version you have on your development system. This migration won&amp;rsquo;t do anything unless there are no pages defined in the database.&lt;/p&gt;
&lt;p&gt;Remember that the contents of your local SQLite database aren&amp;rsquo;t transferred to production, so you&amp;rsquo;ll need to enter, on the production system, any data you&amp;rsquo;ve added to the database on your development system (or add a migration to do so, as we&amp;rsquo;ve done for the basic site contents). This is a bit of a pain for ongoing development &amp;mdash; you&amp;rsquo;ll probably find that you&amp;rsquo;ll want to copy the database from the production system down to development when you&amp;rsquo;re doing development work, and sometimes push it back up to production when you&amp;rsquo;ve added content locally. A &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; tool such as &lt;a href=&quot;http://www.navicat.com/&quot;&gt;Navicat&lt;/a&gt; simplifies this process.&lt;/p&gt;
&lt;h2&gt;Install Capistrano&lt;/h2&gt;
&lt;p&gt;Capistrano is a powerful utility for automating any kind of web deployment. It is nearly universally used by Rails developers.&lt;/p&gt;
&lt;p&gt;First, install the Capistrano gem if you don&amp;rsquo;t already have it:&lt;/p&gt;
&lt;pre&gt;
sudo gem install capistrano
&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;ve used version 2.5 in this lesson. Some details will be different if you&amp;rsquo;re using an earlier version, and if it is much earlier, it may not work with Git.&lt;/p&gt;
&lt;p&gt;Capistrano runs on your development system, not on the server. It performs actions on the server by connecting to it via &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; and issuing commands, just as you would from an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; terminal session.&lt;/p&gt;
&lt;p&gt;To configure the application for Capistrano, the first step is to &amp;ldquo;Capify&amp;rdquo; it. From your root application directory, simple enter in a terminal:&lt;/p&gt;
&lt;pre&gt;
capify .
&lt;/pre&gt;
&lt;p&gt;(That&amp;rsquo;s &amp;ldquo;capify&amp;rdquo;, space, period.)&lt;/p&gt;
&lt;p&gt;This adds two files to your application: &lt;code&gt;Capfile&lt;/code&gt; at the root of the app, and &lt;code&gt;deploy.rb&lt;/code&gt; in the config directory. We don&amp;rsquo;t need to make any changes to &lt;code&gt;Capfile&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Set up deploy.rb&lt;/h2&gt;
&lt;p&gt;The file &lt;code&gt;deploy.rb&lt;/code&gt; is where you tell Capistrano how to access your code repository, as well as other details of your production server(s). The art of configuring Capistrano is mostly a matter of setting up the &lt;code&gt;deploy.rb&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a &lt;a href=&quot;http://github.com/guides/deploying-with-capistrano&quot;&gt;guide at github&lt;/a&gt; that gives us some guidance about what is needed so Capistrano can fetch our code directly from our github repository. There&amp;rsquo;s also a lot of tutorial content at &lt;a href=&quot;http://capify.org&quot;&gt;capify.org&lt;/a&gt;. Here&amp;rsquo;s the lines we need to add to support checking out from our public Git repository:&lt;/p&gt;
&lt;pre&gt;
  default_run_options[:pty] = true
  set :repository,  &amp;quot;git://github.com/chaupt/learning-rails-sample-app.git&amp;quot;
  set :scm, &amp;quot;git&amp;quot;
  set :branch, &amp;quot;master&amp;quot;
  set :deploy_via, :remote_cache
&lt;/pre&gt;
&lt;p&gt;The first line ensures that password prompts are passed through. The next three lines tell Capistrano where the repository is, that it is a Git repository, and which branch to use. The last line tells Capistrano to keep a cache of the repository on the web server, so it only has to transfer new code from the repository when deploying a new version.&lt;/p&gt;
&lt;p&gt;If you are deploying from your own repository, you&amp;rsquo;ll need to change the repository &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, and if it isn&amp;rsquo;t a public repository, you&amp;rsquo;ll want to set up an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; key pair, with the private key on your server and the public key added to your Github account; see the &lt;a href=&quot;http://github.com/guides/home&quot;&gt;help docs on Github&lt;/a&gt; for details.&lt;/p&gt;
&lt;p&gt;Then we need to tell Capistrano about our servers:&lt;/p&gt;
&lt;pre&gt;
  set :application, &amp;quot;learningrails&amp;quot;
  set :deploy_to, &amp;quot;/var/www/apps/#{application}&amp;quot;
  set :user, &amp;quot;deploy&amp;quot;
  set :admin_runner, &amp;quot;deploy&amp;quot;
  
  role :app, &amp;quot;sampleapp.learningrails.com&amp;quot;
  role :web, &amp;quot;sampleapp.learningrails.com&amp;quot;
  role :db,  &amp;quot;sampleapp.learningrails.com&amp;quot;, :primary =&amp;gt; true
&lt;/pre&gt;
&lt;p&gt;The application name is used to name the folder into which the application code is deployed. The second line allows us to specify where this folder is located on the system, with the application name substituted in as a variable. Then we tell Capistrano what user name to use when logging into the server. (It is customary to use a dedicated user name just for deployments.)&lt;/p&gt;
&lt;p&gt;By default, Capistrano uses sudo to execute commands on the server. This won&amp;rsquo;t work on most shared servers, where you don&amp;rsquo;t have sudo access, so you might need to add the option &lt;code&gt;set :use_sudo, false&lt;/code&gt;. If you do so, however, Capistrano might not be able to create the directories for your application. We&amp;rsquo;ve left sudo enabled, and used the &lt;code&gt;admin_runner&lt;/code&gt; variable to set the user name under which Capistrano will use the sudo command when creating directories. This is what worked best for us in our server configuration, but your mileage may vary; if in doubt, check with your hosting company. (Versions of Capistrano prior to 2.4 behave somewhat differently.)&lt;/p&gt;
&lt;p&gt;The three &amp;ldquo;role&amp;rdquo; lines tell Capistrano about our servers. We&amp;rsquo;re using a very simple configuration, in which the web (&lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt;), application (Rails), and database (MySQL) servers are all on the same machine, but they don&amp;rsquo;t have to be. You can also have a cluster of servers, with more than one server performing each role, and Capistrano will take care of, for example, checking out a copy of the code to each application server, and modifying the setup on each web server to display a maintenance page.&lt;/p&gt;
&lt;p&gt;Finally, you need to tell Capistrano how to start and restart the application server. There are standard Capistrano tasks for this that are designed for Mongrel and similar application servers; for Passenger, things are simpler, but we need to tell Capistrano just what to do, with these lines of code:&lt;/p&gt;
&lt;pre&gt;
  namespace :deploy do
    desc &amp;quot;Restart Application&amp;quot;
    task :restart, :roles =&amp;gt; :app do
      run &amp;quot;touch #{current_path}/tmp/restart.txt&amp;quot;
    end
    desc &amp;quot;Start Application -- not needed for Passenger&amp;quot;
    task :start, :roles =&amp;gt; :app do
      # nothing -- need to override default cap start task when using Passenger
    end
  end
&lt;/pre&gt;
&lt;p&gt;The namespace block tells Capistrano what name prefix to use for these tasks. Namespaces help avoid unintentional name conflicts in complex setups.&lt;/p&gt;
&lt;p&gt;To restart Passenger, you only need to update the modification date of the &lt;code&gt;restart.txt&lt;/code&gt; file, which is done with the &lt;code&gt;touch&lt;/code&gt; command. Note that you can simply write &lt;code&gt;run&lt;/code&gt; and then the command, and Capistrano knows to open an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; terminal to the app server (as specified on the &lt;code&gt;task&lt;/code&gt; line) and issue this command. &lt;code&gt;current_path&lt;/code&gt; is a variable that provides the path to the current version of the application.&lt;/p&gt;
&lt;p&gt;With Passenger, you don&amp;rsquo;t need to do anything to start the app server, but we need to define an empty start task to override the one that is part of the default Capistrano tasks.&lt;/p&gt;
&lt;p&gt;These tasks give you a hint of what&amp;rsquo;s possible with Capistrano &amp;mdash; you can use it to automate nearly everything you&amp;rsquo;d want to do on your server. Keep in mind, though, that if you use the &lt;code&gt;:use_sudo, false&lt;/code&gt; setting, you can&amp;rsquo;t do things that require a privileged user.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re done changing code now, so if you&amp;rsquo;re working in your own repository, commit your changes now. We&amp;rsquo;ve already made all these changes in the public Github repository.&lt;/p&gt;
&lt;h2&gt;Install Passenger&lt;/h2&gt;
&lt;p&gt;Now we&amp;rsquo;re ready to set up the server. There&amp;rsquo;s a vast array of options here, depending on whether you&amp;rsquo;re on a shared or dedicated server, what operating system is installed, and so forth. To avoid a lot of system-specific discussion and keep this lesson to a reasonable length, we&amp;rsquo;re going to assume you have a Linux server with Apache 2.2, MySQL 2, and Git installed. If not, see the links at the start of this article for pointers to some resources, or check with your hosting company.&lt;/p&gt;
&lt;p&gt;To install Passenger, simply enter in an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; terminal window connected to your server:&lt;/p&gt;
&lt;pre&gt;
  sudo gem install passenger
&lt;/pre&gt;
&lt;p&gt;And then:&lt;/p&gt;
&lt;pre&gt;
  passenger-install-apache2-module
&lt;/pre&gt;
&lt;p&gt;The Passenger installer will check for any required dependencies and give you specific instructions if there&amp;rsquo;s anything else you need to set up first.&lt;/p&gt;
&lt;h2&gt;Configure Apache&lt;/h2&gt;
&lt;p&gt;Now we need to configure Apache. Your system should have a base Apache configuration already, often in &lt;code&gt;/etc/httpd/conf/httpd.conf&lt;/code&gt;, though this varies depending on the Linux variant and system configuration.&lt;/p&gt;
&lt;p&gt;We need to add a few lines to the Apache configuration file to tell Apache to use the Passenger module:&lt;/p&gt;
&lt;pre&gt;
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.0.3
PassengerRuby /usr/bin/ruby
&lt;/pre&gt;
&lt;p&gt;The Passenger installer will provide these lines for you; the paths and other details may be different for your system configuration.&lt;/p&gt;
&lt;p&gt;Then we need a virtual host configuration for our site. We put this is a separate file, which is included by reference at the end of the main Apache config file. Here&amp;rsquo;s what we used:&lt;/p&gt;
&lt;pre&gt;
  &amp;lt;VirtualHost *:80&amp;gt;
     ServerName sampleapp.learningrails.com
     DocumentRoot /var/www/apps/learningrails/current/public 
     &amp;lt;Directory &amp;quot;/var/www/apps/learningrails/current/public&amp;quot;&amp;gt;
          Options FollowSymLinks
          AllowOverride None
          Order allow,deny
          Allow from all
    &amp;lt;/Directory&amp;gt; 
  &amp;lt;/VirtualHost&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The first line identifies the root &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; for your site. We&amp;rsquo;ve used the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; for our demonstration server, but you&amp;rsquo;ll want to use your own server &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; here. You&amp;rsquo;ll need to set up a &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; record to point this name to the IP address of your server.&lt;/p&gt;
&lt;p&gt;The second line must point to the &lt;code&gt;public&lt;/code&gt; directory of your Rails application. We told Capistrano to put the application in &lt;code&gt;/var/www/apps/learningrails&lt;/code&gt;, and as we&amp;rsquo;ll see shortly, &lt;code&gt;current&lt;/code&gt; is a symlink that points to the currently active version.&lt;/p&gt;
&lt;p&gt;The Directory directives ensure that Apache is allowed to access the public directory. This may or may not be necessary, depending on what the rest of your Apache config file looks like.&lt;/p&gt;
&lt;p&gt;Now restart Apache, and make sure there are no errors reported. On our server, this can be done with:&lt;/p&gt;
&lt;pre&gt;
  sudo /sbin/service httpd restart
&lt;/pre&gt;
&lt;p&gt;Once again, the command may be different for your server configuration.&lt;/p&gt;
&lt;h2&gt;Set up MySQL&lt;/h2&gt;
&lt;p&gt;We have just one more thing we need to do on the server: create the empty database. You can do this with a MySQL &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; application, if it can connect to your server (typically using an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; tunnel), or you can do it from the command line in a &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; terminal session. To use the latter approach, first create the database with the following command at the shell prompt:&lt;/p&gt;
&lt;pre&gt;
  mysqladmin -u root -p create learningrails_production
&lt;/pre&gt;
&lt;p&gt;This command assumes that you have a user configured for MySQL named root, and you&amp;rsquo;ll be prompted for root&amp;rsquo;s database password after you enter this command.&lt;/p&gt;
&lt;p&gt;Then, start the mysql monitor program by entering&lt;/p&gt;
&lt;pre&gt;
  mysql -u root -p
&lt;/pre&gt;
&lt;p&gt;and create the deploy user by entering the following command at the mysql prompt:&lt;/p&gt;
&lt;pre&gt;
mysql&amp;gt; grant all privileges on *.* to 'deploy'@'localhost' identified by 'secret';
&lt;/pre&gt;
&lt;p&gt;(Note that you don&amp;rsquo;t enter &lt;code&gt;mysql&amp;gt;&lt;/code&gt;; that&amp;rsquo;s the prompt.) The user name (deploy) and password (secret) must correspond to those in your database.yml file&amp;rsquo;s production section.&lt;/p&gt;
&lt;h2&gt;Your first deploy&lt;/h2&gt;
&lt;p&gt;Now, on to Capistrano tasks. First, to get an overview of all the Capistrano commands available, enter (in a terminal on your development system):&lt;/p&gt;
&lt;pre&gt;
  cap -T
&lt;/pre&gt;
&lt;p&gt;Remember, Capistrano always runs on your development system, even though it is issuing commands to your server.&lt;/p&gt;
&lt;p&gt;Now there&amp;rsquo;s some one-time-only setup:&lt;/p&gt;
&lt;pre&gt;
  cap deploy:setup
&lt;/pre&gt;
&lt;p&gt;Capistrano will connect to your server, and will prompt you for the server password if don&amp;rsquo;t have an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; key set up. Capistrano will then create some directories to hold your application code.&lt;/p&gt;
&lt;p&gt;To make sure everything is ok, enter:&lt;/p&gt;
&lt;pre&gt;
  cap deploy:check
&lt;/pre&gt;
&lt;p&gt;Hopefully, this tells you that everything looks good; if not, read the error messages carefully and correct any problems. If there are permissions issues, Capistrano may not be able to create the directories it needs. You may need to log into the server and create the &lt;code&gt;/var/www&lt;/code&gt; directory manually. For our server, the owner of this directory is set to &lt;code&gt;deploy&lt;/code&gt;, and the group to &lt;code&gt;apache&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, just enter:&lt;/p&gt;
&lt;pre&gt;
  cap deploy:cold
&lt;/pre&gt;
&lt;p&gt;And you should see lots of lines fly by, as Capistrano tells the server to check out the code from Github and sets up some symlinks. At the end, all the migrations should be run.&lt;/p&gt;
&lt;p&gt;If all has gone well, you should now be able to browse to your server and see the application running. (You can visit http://sampleapp.learningrails.com to see the copy that we deployed.)&lt;/p&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a lot that can go wrong in this process, and unless everything works, your app won&amp;rsquo;t. So watch the Capistrano scripts carefully while they&amp;rsquo;re running. If there were no errors there, but it hangs on checking out the code, then there&amp;rsquo;s a problem with the authentication with Github (if you&amp;rsquo;re using a private repository) or the Git &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;If you get no response when you try to access the application, make sure your &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt; is set up correctly and has propagated to your computer, and that Apache is running. The Apache error log file may be helpful (the location varies depending on the system configuration; on our system, it is &lt;code&gt;/var/log/httpd/error_log&lt;/code&gt;). If you get a Rails error page (error 500), then check the Rails log on the server for clues (&lt;code&gt;/var/www/apps/learningrails/shared/log/production.log&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Because of the wide range of issues that can come up, it&amp;rsquo;s unlikely that we&amp;rsquo;ll be able to answer all your questions here. Here&amp;rsquo;s some resources to try:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://groups.google.com/group/capistrano&quot;&gt;Google group for Capistrano&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://groups.google.com/group/rubyonrails-deployment&quot;&gt;Google group for Rails Deployment&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://groups.google.com/group/rubyonrails-talk&quot;&gt;Google group for general Rails issues&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://groups.google.com/group/phusion-passenger&quot;&gt;Google group for Passenger&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://railsforum.com&quot;&gt;RailsForum&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://linuxquestions.org&quot;&gt;LinuxQuestions forum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, of course, there&amp;rsquo;s always the tutorials, FAQs, and support staff at your hosting company.&lt;/p&gt;
&lt;h2&gt;Deploy, and deploy again&lt;/h2&gt;
&lt;p&gt;Once this is all set up and working, deploying new versions is gloriously simple. First, be sure to commit your changes and push them to Github. Then, just:&lt;/p&gt;
&lt;pre&gt;
   cap deploy
&lt;/pre&gt;
&lt;p&gt;Or, if you&amp;rsquo;ve added any migrations:&lt;/p&gt;
&lt;pre&gt;
    cap deploy:migrations
&lt;/pre&gt;
&lt;p&gt;If you want to put up a maintenance page during deployments, first issue this command:&lt;/p&gt;
&lt;pre&gt;
   cap deploy:web:disable
&lt;/pre&gt;
&lt;p&gt;And then do the deployment. When it&amp;rsquo;s done, just:&lt;/p&gt;
&lt;pre&gt;
   cap deploy:web:enable
&lt;/pre&gt;
&lt;h2&gt;Something wrong? Just roll back&lt;/h2&gt;
&lt;p&gt;Another great thing about Capistrano is that it maintains multiple versions of your application on your web server. In the directory &lt;code&gt;/var/web/apps/learningrails&lt;/code&gt;, you&amp;rsquo;ll find three directories: &lt;code&gt;shared&lt;/code&gt;, &lt;code&gt;releases&lt;/code&gt;, and &lt;code&gt;current&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;shared&lt;/code&gt; is for information that doesn&amp;rsquo;t change with each deployment. Log files, for example are stored in &lt;code&gt;shared/log&lt;/code&gt;. If you have assets that are uploaded to the server and don&amp;rsquo;t go in the database or the repository, then they should go here, and you&amp;rsquo;ll want to add a Capistrano task (which can be automatically executed after each deployment) to symlink to the shared location from the current &lt;code&gt;public&lt;/code&gt; directory.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;releases&lt;/code&gt; has a directory for each deployed version. By default, Capistrano keeps the most recent four versions.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;current&lt;/code&gt; isn&amp;rsquo;t a real directory; it&amp;rsquo;s a symlink to the current release directory. So you can always refer to the current version as &lt;code&gt;/var/www/apps/learningrails/current&lt;/code&gt;, and you&amp;rsquo;ll really be accessing one of the directories inside &lt;code&gt;releases&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what&amp;rsquo;s the use of all these releases directories? If you deploy a version and then find that your application has a serious problem, just roll back:&lt;/p&gt;
&lt;pre&gt;
   cap deploy:rollback
&lt;/pre&gt;
&lt;p&gt;This task takes only a moment to execute, because all it has to do change the &lt;code&gt;current&lt;/code&gt; symlink to point to the previous &lt;code&gt;releases&lt;/code&gt; directory.&lt;/p&gt;
&lt;h2&gt;And there&amp;rsquo;s more&amp;hellip;&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ve just scratched the surface in this lesson, as deployment is a very complex topic. There&amp;rsquo;s much more you can do with Capistrano, and more that you should know to create a secure production deployment. Check out the links early in this lesson page to dive deeper.&lt;/p&gt;
&lt;p&gt;Next lesson, we&amp;rsquo;ll look at how to evaluate the performance of your deployed application and find performance troublespots using New Relic&amp;rsquo;s &lt;span class=&quot;caps&quot;&gt;RPM&lt;/span&gt; service.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:42:00</itunes:duration>
        </item>
        
        <item>
          <title>21: Version control with git</title>
          <description>&lt;p&gt;In this lesson, we put our application into the git version control system, in preparation for deploying the application in the next lesson. We do this first because the proper way to deploy an application is not to copy it from your computer to the server, but to have the server pull the application from the version control system.&lt;/p&gt;</description>
          <pubDate>Sun, 03 Aug 2008 20:23:47 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79346-version-control-with-git</guid>
          <link>http://www.buildingwebapps.com/podcasts/79346-version-control-with-git</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-21.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we put our application into a version control system, in preparation for deploying the application in the next lesson. We do this first because the proper way to deploy an application is not to copy it from your computer to the server, but to have the server pull the application from the version control system.   Please note that, while we&amp;rsquo;ve tried to make these notes complete, they aren&amp;rsquo;t the full tutorial; that&amp;rsquo;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Choosing a version control system&lt;/h2&gt;
&lt;p&gt;There are many version control systems. &lt;span class=&quot;caps&quot;&gt;CVS&lt;/span&gt; was the first system widely used in the open-source community. Several years ago, it was largely replaced by Subversion. And in early 2008, most of the Rails world moved to a newer version control system, called git. We&amp;rsquo;re going to use git in this lesson, since it has become the standard in the Rails community, and is used for Rails itself and most plugins.&lt;/p&gt;
&lt;p&gt;git was originally written by Linus Torvalds to manage development work on the Linux kernel. It&amp;rsquo;s an extremely capable system, with more than 100 commands. We&amp;rsquo;re going to just scratch the surface of its capabilities in this lesson, but you&amp;rsquo;ll learn enough to use it for day-to-day development. To make full use of it, spend some time with the resources listed on our &lt;a href=&quot;/topic/24425-the-git-distributed-version-control-system&quot;&gt;git page&lt;/a&gt;. In particular, you may want to purchase the &lt;a href=&quot;http://peepcode.com/products/git&quot;&gt;PeepCode git screencast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re familiar with other version control systems, you probably expect there to be one central repository stored on a remote server somewhere. git is different; it is a distributed version control system, in which there can be any number of repositories for a single project. You&amp;rsquo;ll create a local repository on your computer, and if you want, you can create a remote repository elsewhere, such as on a hosted git service like github.com. (You&amp;rsquo;ll need to have a repository that is accessible from the Internet to deploy your application.)&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We aren&amp;rsquo;t making any changes to the code in this lesson, and you don&amp;rsquo;t need to have the code installed locally to complete the lesson. If you follow along, by the end of the lesson you&amp;rsquo;ll have your own copy of the code on your computer, managed by a local git repository, and you&amp;rsquo;ll have your own repository stored on github as well.&lt;/p&gt;
&lt;p&gt;First we need to install git. Assuming you&amp;rsquo;re on a Mac and have Macports installed, open a terminal and enter:&lt;/p&gt;
&lt;pre&gt;
sudo port install git-core
&lt;/pre&gt;
&lt;p&gt;Now set up your user information in the git configuration:&lt;/p&gt;
&lt;pre&gt;
git config --global user.name &amp;quot;Michael Slater&amp;quot;
git config --global user.email learningrails@buildingwebapps.com
&lt;/pre&gt;
&lt;p&gt;See our articles on installing Ruby on Rails for more details:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/6433-setting-up-rails-on-leopard-mac&quot; title=&quot;Mac OS X 10.5&quot;&gt;Setting up Rails on Leopard&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/6455-setting-up-rails-on-tiger-mac&quot; title=&quot;Mac OS X 10.4&quot;&gt;Setting up Rails on Tiger&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/6491-setting-up-rails-on-windows-vista&quot;&gt;Setting up Rails on Windows Vista&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/6467-setting-up-rails-on-windows-xp&quot;&gt;Setting up Rails on Windows XP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Creating a git repository for an application on your computer&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s two paths you could take to creating a repository on your computer:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;If you have an application already on your computer, you can create a local git repository and add the application to it&lt;/li&gt;
    &lt;li&gt;If you want to start from an existing application, such as the Learning Rails sample application, you can make your own copy of that repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this lesson, we&amp;rsquo;ll do both of these things. First, we&amp;rsquo;ll show how we put the sample application into a git repository and then created a public repository on github. Then we&amp;rsquo;ll show how you can make your own version of that repository.&lt;/p&gt;
&lt;p&gt;Change to the root directory for the application and enter:&lt;/p&gt;
&lt;pre&gt;
git init
&lt;/pre&gt;
&lt;p&gt;This creates the .git folder at the root of your application, where git stores all of its information.&lt;/p&gt;
&lt;h2&gt;Telling git to ignore files we don&amp;rsquo;t want it to track&lt;/h2&gt;
&lt;p&gt;We don&amp;rsquo;t want git to track our log or temp files, so we need to create a file call .gitignore at the root of the application. If you&amp;rsquo;re using textmate, you can enter in the terminal:&lt;/p&gt;
&lt;pre&gt;
mate .gitignore
&lt;/pre&gt;
&lt;p&gt;And then enter the following lines into this file:&lt;/p&gt;
&lt;pre&gt;
*.log
tmp/**/*
.DS_Store
&lt;/pre&gt;
&lt;p&gt;The first line tells git to ignore any files that end with the .log extension. The second line tells it to ignore the temp directory contents (individual files as well as subdirectories), and the last line tells it to ignore the OS X housekeeping hidden file that is in each directory. (If you&amp;rsquo;re on Windows, you might want to replace this with Thumbs.db.)&lt;/p&gt;
&lt;p&gt;Now there&amp;rsquo;s one more little complexity with the ignore. Since we&amp;rsquo;ve told git to ignore all .log files, it sees the log directory as empty, and git doesn&amp;rsquo;t track empty directories. As a result, the log directory would not be put in the repository, and if you just checked out the files, you&amp;rsquo;d get an error on starting the application because Rails wouldn&amp;rsquo;t be able to create the log file. So we put a dummy file into the log directory, so git will not see the directory as empty and will put it in the repository.&lt;/p&gt;
&lt;pre&gt;
touch log/.gitignore
&lt;/pre&gt;
&lt;h2&gt;Adding files to our local git repository&lt;/h2&gt;
&lt;p&gt;Now we&amp;rsquo;re ready to add files to the repository. From the root of the application, enter:&lt;/p&gt;
&lt;pre&gt;
git add .
&lt;/pre&gt;
&lt;p&gt;which tells git to add all the files (except those excluded by our .gitignore file). Note that this doesn&amp;rsquo;t actually commit the files to the repository; it just adds them to what git calls the index, which lists files that are ready to be committed. You can view the list by typing:&lt;/p&gt;
&lt;pre&gt;
git status
&lt;/pre&gt;
&lt;p&gt;Now we can commit the files to the local repository by typing:&lt;/p&gt;
&lt;pre&gt;
git commit -m &amp;quot;Initial commit&amp;quot;
&lt;/pre&gt;
&lt;p&gt;The -m option allows us to specify a commit message, which is required. (If you leave off the -m option, git will try to open an editor for you to provide the commit message, but this will only work if you have the proper environment variable set up.)&lt;/p&gt;
&lt;h2&gt;Setting up a github account&lt;/h2&gt;
&lt;p&gt;We now have our application in our local repository. At this point we have all the benefits of version control, but we still want to copy this to a remote repository. There&amp;rsquo;s two reasons for this: first, as a backup, and second, so that other contributors, and most immediately, our deployment code (which we&amp;rsquo;ll get to in the next lesson) can access it.&lt;/p&gt;
&lt;p&gt;First, we need to create an account on &lt;a href=&quot;http://github.com&quot;&gt;github&lt;/a&gt;. We&amp;rsquo;re going to create a temporary account for the purpose of this lesson. You&amp;rsquo;ll need to create your own if you want to have your own repository there.&lt;/p&gt;
&lt;p&gt;Visit www.github.com and click the Pricing and Signup link at the top. You can choose the free account as long as you&amp;rsquo;re willing for your code to be public; if you want a private repository, you&amp;rsquo;ll have to choose one of the paid accounts.&lt;/p&gt;
&lt;h2&gt;Setting up your &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; key&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ll need an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; key to use your repository. If you already have a key pair you&amp;rsquo;ve made for other purposes, you should be able to use your existing public key. If not, go ahead and create one now.&lt;/p&gt;
&lt;p&gt;For details on creating an &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; key, see the &lt;a href=&quot;http://github.com/guides/providing-your-ssh-key&quot;&gt;github guide on &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; keys&lt;/a&gt;. If you&amp;rsquo;re on Windows, you may also find &lt;a href=&quot;/articles/6397-using-ssh-keys-to-speed-login&quot;&gt;our article on &lt;span class=&quot;caps&quot;&gt;SSH&lt;/span&gt; with Windows&lt;/a&gt; to be useful.&lt;/p&gt;
&lt;p&gt;Whether you&amp;rsquo;re using an existing key or created a new one, paste the public key into the signup form.&lt;/p&gt;
&lt;h2&gt;Push to the remote repository&lt;/h2&gt;
&lt;p&gt;The following command tells git that we want to add a remote repository definition, called origin by default, and provides the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; to that repository. (Note that we&amp;rsquo;ve shown the address for our learningrails repository at github here; you won&amp;rsquo;t be able to push to this repository, since you don&amp;rsquo;t have write access rights. We&amp;rsquo;ll show how you can push your version to your own remote repository shortly.)&lt;/p&gt;
&lt;pre&gt;
git remote add origin git@github.com:learningrails/learning-rails-sample-app.git
&lt;/pre&gt;
&lt;p&gt;And now we can copy to the remote repository with the command:&lt;/p&gt;
&lt;pre&gt;
git push origin master
&lt;/pre&gt;
&lt;p&gt;This tells git to push all changes in the local repository to the remote repository named &lt;em&gt;origin&lt;/em&gt;, and to use the &lt;em&gt;master&lt;/em&gt; branch (which in our case is the only branch that exists).&lt;/p&gt;
&lt;p&gt;When this completes, we have synchronized our local and remote repositories.&lt;/p&gt;
&lt;h2&gt;Making our own repository to hold your own version of the Learning Rails code&lt;/h2&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen how to create a repository from scratch, let&amp;rsquo;s make your own fork of the Learning Rails repository so you can use it to maintain your own version. In the next lesson, we&amp;rsquo;ll show how to deploy your application from that repository.&lt;/p&gt;
&lt;p&gt;First, you need to create an account at github, if you haven&amp;rsquo;t done that already, and log in.&lt;/p&gt;
&lt;p&gt;Once your account is set up, browse to http://github.com/mzslater/learning-rails-sample-app/tree/master (or search for learning-rails-sample-app from the github search facility, but make sure you choose the version whose owner is mzslater).&lt;/p&gt;
&lt;p&gt;Click the Fork button, and github will create a repository that is a duplicate of our repository, and it also keeps track of the relationship between the two repositories.&lt;/p&gt;
&lt;h2&gt;Cloning your repository&lt;/h2&gt;
&lt;p&gt;You now have your own repository! The next step is to clone it on your local machine.&lt;/p&gt;
&lt;p&gt;On your computer, open a terminal and change to the directory in which you want to place your code. We use a directory called &amp;ldquo;development&amp;rdquo; in our user directory. You don&amp;rsquo;t need to make a subdirectory for the application; git will do that for you.&lt;/p&gt;
&lt;p&gt;On your repository page on github, you&amp;rsquo;ll see the clone &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; listed, and if you click it github will display the full command that you need to enter on your computer to create the clone. It will be something like:&lt;/p&gt;
&lt;pre&gt;
git clone git://github.com/accountname/learning-rails-sample-app.git
&lt;/pre&gt;
&lt;p&gt;where accountname is the name you chose when you created your github account.&lt;/p&gt;
&lt;p&gt;Run this command, and if all goes well, you&amp;rsquo;ll have a local clone of your github repository.&lt;/p&gt;
&lt;p&gt;If you get a permission denied message, you probably have a problem with your ssh key. Check &lt;a href=&quot;http://github.com/guides/addressing-authentication-problems-with-ssh&quot;&gt;this page&lt;/a&gt; for some pointers.&lt;/p&gt;
&lt;h2&gt;Changing your version of the code&lt;/h2&gt;
&lt;p&gt;Now make some edit to your local code, so you can test the process of committing changes and pushing them up to the github repository.&lt;/p&gt;
&lt;p&gt;After making the change, enter the command:&lt;/p&gt;
&lt;pre&gt;
git commit -a -m 'make up a commit message here'
&lt;/pre&gt;
&lt;p&gt;Your change is now committed to your local repository, but the github repository hasn&amp;rsquo;t yet been updated. To push the change up to that repository, enter the command:&lt;/p&gt;
&lt;pre&gt;
git push origin master
&lt;/pre&gt;
&lt;p&gt;Now you can visit your repository at github, and it will show the commit. You can click on the commit to see the changes that were made, and use the source code browser to see all the code.&lt;/p&gt;
&lt;p&gt;If you make improvements to the code that you think would be of interest to others, click the Pull Request button on your repository page to send us a message telling us what you&amp;rsquo;ve done, and we&amp;rsquo;ll consider adding it to our repository. Please be specific about describing the changes you&amp;rsquo;ve made and why they are useful to everyone.&lt;/p&gt;
&lt;h2&gt;Coming Up&lt;/h2&gt;
&lt;p&gt;In our next lesson, we&amp;rsquo;ll explore the Capistrano deployment utility and deploy the code from the github repository.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:24:00</itunes:duration>
        </item>
        
        <item>
          <title>20: Testing your site (Part 2)</title>
          <description>&lt;p&gt;We've ignored testing so far, so you could learn as quickly as possible how to build something. This episode concludes our testing journey by focusing on the functional tests that are still broken in our application.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:55 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79345-testing-your-site-part-2</guid>
          <link>http://www.buildingwebapps.com/podcasts/79345-testing-your-site-part-2</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-20.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we finish up our testing journey by fixing up some of our functional tests.   Please note that, while we&amp;rsquo;ve tried to make these notes complete, they aren&amp;rsquo;t the full tutorial; that&amp;rsquo;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;The code in this episode is the same as the ending state of the previous episode and contains all of the fixed tests.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_20.zip&quot;&gt;Learning Rails example app code as of the end of this lesson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Functional Tests&lt;/h2&gt;
&lt;p&gt;We continue where we left off, having working unit tests but many broken functional tests.&lt;/p&gt;
&lt;h3&gt;Fixing the Functional Tests&lt;/h3&gt;
&lt;p&gt;We now know how to read the test results, so switching our attention to the functional test block results, we see we have our work cut out for ourselves:&lt;/p&gt;
&lt;pre&gt;
FEEFFEEFEEFFEEFFFFEFFFFFFFFF.........FEEEE.
&lt;/pre&gt;
&lt;p&gt;Which in my first run was equivalent to 43 tests, 36 assertions, 20 failures, 13 errors. Ouch.&lt;/p&gt;
&lt;p&gt;The Rails scaffold generator does a much better job at creating functional tests than it does with unit tests. Functional tests exercise our controllers. Peeking inside most of the test files in the test/functionals directory, you will note that they follow similar patterns.&lt;/p&gt;
&lt;p&gt;So what went wrong? In scanning through the test diagnostics, we see a lot of tests with similar issues. There are many tests with problems with redirects: &amp;ldquo;Expected response to be a &amp;lt;:success&amp;gt;, but was &amp;lt;302&amp;gt;&amp;rdquo;. There are many tests where things were not created, updated, or destroyed when expected. Thinking back, the common thread here is that all of these things need you to be logged in, yet, when the tests are automatically generated for us, the generator has no idea about this requirement. Let&amp;rsquo;s fix that.    The &lt;code&gt;restful_authentication&lt;/code&gt; plugin that we used provides a utility module called &lt;code&gt;AuthenticatedTestHelper&lt;/code&gt;. This module contains useful methods that you can mix-in to your test classes to simulate things like logging in, precisely what we need. Since we protected most of our administrative functions with those &lt;code&gt;before_filter :login_required&lt;/code&gt; checks, that will cause any of our tests that try to directly exercise an action to instead get redirected to a login screen.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s pick one of our controller&amp;rsquo;s tests to fix up as our example. The others will follow similar patterns and you can look at the final project code to see the changes (or try to make the changes yourself as an exercise).&lt;/p&gt;
&lt;p&gt;First, add the authentication system&amp;rsquo;s helper at the top of the test class. While there, add the user fixtures so we have some test user accounts to log in with:&lt;/p&gt;
&lt;pre&gt;
   class CategoriesController &amp;lt; ActionController::TestCase
      include AuthenticatedTestHelper
      fixtures :users
&lt;/pre&gt;
&lt;p&gt;Now, let&amp;rsquo;s use the new method we have to log in as the user quentin:&lt;/p&gt;
&lt;pre&gt;
   def test_should_get_index
      login_as :quentin
      get :index
      assert_response :success
      assert_not_nil assigns(:categories)
   end
&lt;/pre&gt;
&lt;p&gt;Run the tests again. The redirect failure on &lt;code&gt;test_should_get_index&lt;/code&gt; should now be gone.&lt;/p&gt;
&lt;p&gt;Go back to each method in this test class and add the &lt;code&gt;login_as :quentin&lt;/code&gt; line at the start of each test method. All of your redirect failures should now be cleaned up.&lt;/p&gt;
&lt;p&gt;But, there are still failures to fix. Look through the other functional tests and make the same changes to all of the others that are protected with the &lt;code&gt;before_filter&lt;/code&gt; (links_controller_test, messages_controller_test, pages_controller_test, users_controller_test).&lt;/p&gt;
&lt;p&gt;For the controllers that are selective about the login requirement, be sure to &lt;em&gt;not&lt;/em&gt; login when it isn&amp;rsquo;t needed. For instance, @MessageControllerTest@&amp;rsquo;s new and create tests are not protected by login. See the controller to confirm this.&lt;/p&gt;
&lt;p&gt;Run the tests again. We are getting closer. In my run, the results look like this:&lt;/p&gt;
&lt;pre&gt;
  Started
  FEE..EEFEE.E.EEF...E.F................FEEEE.
  Finished in 0.547902 seconds.
&lt;/pre&gt;
&lt;p&gt;Our &lt;code&gt;CategoryControllerTest&lt;/code&gt; is responsible for a number of those errors and failures, so let&amp;rsquo;s clean it up next.&lt;/p&gt;
&lt;p&gt;test_should_create_category fails with a pattern that will become familiar to you as you test code that uses validations. Here, the code is trying to make a new category object. The test, however, by default tries to create an empty category. Looking inside of the &lt;code&gt;Category&lt;/code&gt; model, we see a validates_presence_of on :title. We better fill in a value for the title:&lt;/p&gt;
&lt;pre&gt;
  def test_should_create_category
    login_as :quentin
    assert_difference('Category.count') do
      post :create, :category =&amp;gt; { :title =&amp;gt; 'test' }
    end

    assert_redirected_to category_path(assigns(:category))
  end
&lt;/pre&gt;
&lt;p&gt;Go through the rest of the code and find and fix the various create tests that need values.&lt;/p&gt;
&lt;p&gt;Some test methods seem to be using fixture data, note the &lt;code&gt;categories(:one)&lt;/code&gt; syntax we see in methods like &lt;code&gt;test_should_show_category&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;
  def test_should_show_category
    login_as :quentin
    get :show, :id =&amp;gt; categories(:one).id
    assert_response :success
  end
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The generator script preloaded the fixtures with the test data it created when we started. Since we renamed the IDs in our fixture files, we need to tweak all instances of fixture usage to use valid ID symbols:&lt;/p&gt;
&lt;pre&gt;
  def test_should_show_category
    login_as :quentin
    get :show, :id =&amp;gt; categories(:ruby).id
    assert_response :success
  end
&lt;/pre&gt;
&lt;p&gt;Go through all of the test code and fix up renamed fixtures now.&lt;/p&gt;
&lt;h3&gt;Writing a new functional test&lt;/h3&gt;
&lt;p&gt;There are places where we added methods to our RESTful controllers. For instance, in the &lt;code&gt;LinksController&lt;/code&gt; we added the &lt;code&gt;list&lt;/code&gt; action. We add a test for it in &lt;code&gt;LinkControllerTest&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;
  def test_should_get_list
    get :list, :name =&amp;gt; 'pageone'
    assert_response :success
    assert_not_nil assigns(:categories)
    assert_not_nil assigns(:pagetitle)
    assert_not_nil assigns(:page)
  end  
&lt;/pre&gt;
&lt;p&gt;In this example, we pass a parameter to the &lt;code&gt;list&lt;/code&gt; action. &lt;code&gt;list&lt;/code&gt; expects the name of the page so it can be passed through to the &lt;code&gt;get_page_metadata&lt;/code&gt; helper we wrote, which itself loads up &lt;code&gt;page&lt;/code&gt; and &lt;code&gt;pagetitle&lt;/code&gt; instance variables to be used to set the page title and appropriate tabs in our navigation interface. To make this work, we have to include the pages fixture to &lt;code&gt;LinksControllerTest&lt;/code&gt; and we tweak the fixture file itself so the with the id &lt;code&gt;one&lt;/code&gt; has a &lt;code&gt;name&lt;/code&gt; value of &amp;ldquo;pageone&amp;rdquo;. (See the source code if this is unclear.)&lt;/p&gt;
&lt;p&gt;We apply the same fix to the @MessagesControllerTest@&amp;rsquo;s &lt;code&gt;test_should_get_new&lt;/code&gt; method. While we are looking at MessagesControllerTest, we see one last failure on the update action. It is expecting a redirect (proper behavior on an update) but instead is getting a 200 response.&lt;/p&gt;
&lt;p&gt;Looking at the code for this action, we see that if validation fails when updating attributes, the action simply displays the &lt;code&gt;edit&lt;/code&gt; form again, and hence we get an &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; 200 code. Peeking inside of the default fixture data for messages, we see the problem. Change the email fields to be properly formatted:&lt;/p&gt;
&lt;pre&gt;
one:
  name: MyString
  email: bob@example.com
  company: MyString
  phone: MyString
  subject: MyString
  body: MyText

two:
  name: MyString
  email: two@example.com
  company: MyString
  phone: MyString
  subject: MyString
  body: MyText  
&lt;/pre&gt;
&lt;h3&gt;Final cleanup&lt;/h3&gt;
&lt;p&gt;We lost a valuable piece of information when we fixed all of those authentication tests. We really should also test that the right thing happens when someone is &lt;em&gt;not&lt;/em&gt; logged in. Let&amp;rsquo;s write a quick example of a test that succeeds when an unauthenticated person tries to get a protected resource. In &lt;code&gt;LinkControllerTest&lt;/code&gt;, add this test:&lt;/p&gt;
&lt;pre&gt;
   def test_should_not_get_index_not_logged_in
      get :index
      assert_redirected_to new_session_path
   end
&lt;/pre&gt;
&lt;p&gt;Here, we are not logged in, and we are trying to get the index of links. We should not be able to do this, and we expect to be redirected to the log-in screen. The &lt;code&gt;assert_redirected_to new_session_path&lt;/code&gt; uses the RESTful route to the session controller&amp;rsquo;s new action. This is where login is initiated.&lt;/p&gt;
&lt;p&gt;Run the test, and success!&lt;/p&gt;
&lt;h2&gt;Further Exercises&lt;/h2&gt;
&lt;ol&gt;
    &lt;li&gt;Install the ZenTest gem and take autotest for a spin (gem install ZenTest). This will continually run your tests as you code and save files. A real time saver.&lt;/li&gt;
    &lt;li&gt;Install &lt;a href=&quot;http://opensource.thinkrelevance.com/wiki/tarantula&quot;&gt;tarantula&lt;/a&gt; to explore integration testing and data fuzzing&lt;/li&gt;
    &lt;li&gt;See our &lt;a href=&quot;http://www.buildingwebapps.com/podcasts/79332-testing-rails-code&quot;&gt;Testing&lt;/a&gt; topic for many other articles&lt;/li&gt;
&lt;/ol&gt;</itunes:summary>
          <itunes:duration>00:15:00</itunes:duration>
        </item>
        
        <item>
          <title>19: Testing your site (Part 1)</title>
          <description>We've ignored testing so far, so you could learn as quickly as possible how to build something. Now it's time to go back and fix up the automatic tests and begin exploring how to add more complete tests.</description>
          <pubDate>Thu, 24 Jul 2008 08:00:54 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79344-testing-your-site-part-1</guid>
          <link>http://www.buildingwebapps.com/podcasts/79344-testing-your-site-part-1</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-19.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we&amp;#8217;re going to step back and look at a subject we&amp;#8217;ve neglected: Testing. First, we&amp;#8217;ll take a brief tour to understand the support Ruby and Rails provides us for using tests in our regular development. Then, we will take stock of the current status of our code and make sure it is on solid footing with testing.
 
Please note that, while we&amp;#8217;ve tried to make these notes complete, they aren&amp;#8217;t the full tutorial; that&amp;#8217;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 18. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_18.zip&quot;&gt;Learning Rails example app code as of the start of this lesson&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_19.zip&quot;&gt;Learning Rails example app code as of the end of this lesson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Brief Tutorial on Testing&lt;/h2&gt;
&lt;h3&gt;Why Write Tests?&lt;/h3&gt;
&lt;p&gt;In our previous 10 screencasts, we&amp;#8217;ve built a simple Ruby on Rails site. To move along as fast as possible, we&amp;#8217;ve neglected testing, and in this lesson, we&amp;#8217;re going to remedy that.&lt;/p&gt;
&lt;p&gt;Tests provide a safety net that helps you improve the quality of your code. You can certainly write significant Rails applications without writing tests &amp;#8212; I have to admit I&amp;#8217;ve done so myself, and I suspect that many Rails developers are continuing to do so. Rails doesn&amp;#8217;t force you to write tests. But it is one of the hallmarks of professional-quality code that it has complete tests.&lt;/p&gt;
&lt;p&gt;In the short term, writing tests adds one more thing you need to do, and another set of syntax and technology you need to learn. There&amp;#8217;s no doubt that this takes more time up-front. But in the long run, writing tests can save you time, since problems are easier to track down when they do occur.&lt;/p&gt;
&lt;p&gt;Many developers advocate writing tests even before you write the code, which forces you to think through exactly what your code is supposed to do. Tests are helpful in finding the corner cases that you might not remember to test manually, and in being able to automatically test all aspects of your code whenever you make a change. Without tests, it&amp;#8217;s common for a change you make to fix one thing to accidentally break something else, which you might not notice right away.&lt;/p&gt;
&lt;p&gt;Tests are especially valuable when you&amp;#8217;re doing major rework on your code, commonly called refactoring. With a good suite of tests, you can be confident after you&amp;#8217;ve rewritten some code that it hasn&amp;#8217;t broken anything.&lt;/p&gt;
&lt;h3&gt;Testing Background&lt;/h3&gt;
&lt;p&gt;Many studies have shown that the cost of fixing bugs rises with time. Imagine if you had a &amp;#8220;quality safety net&amp;#8221; that helped protect you by checking basic assumption about your code and notified you if something broke those assumptions. If you had such a tool, it would give you greater confidence as you added or refactored code in your program.&lt;/p&gt;
&lt;p&gt;The Ruby on Rails community has adopted many so-called Agile practices, and code testing is but one. The core Rails team has made it very easy to implement testing in your program by building in simple testing tools in the standard Rails installation.&lt;/p&gt;
&lt;p&gt;Whether you choose to write tests after coding parts of your program (&amp;#8220;Test After Development&amp;#8221; &amp;#8211; &lt;span class=&quot;caps&quot;&gt;TAD&lt;/span&gt;) or before you write a line of code (&amp;#8220;Test First or Test Driven Development&amp;#8221; &amp;#8211; &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;), Rails will accommodate you.&lt;/p&gt;
&lt;p&gt;Ruby on Rails has built in support for a variety of testing scenarios. Rails currently uses the Ruby Test::Unit library to implement three kinds of tests: Unit, Functional, and Integration Tests.&lt;/p&gt;
&lt;p&gt;Rails&amp;#8217; usage of the names for testing terms is slightly different than common meaning. In Rails, Unit tests are tests that exercise Model objects. Functional tests focus on testing controllers. Integration tests are meant to test multi-step workflows that trigger one or more actions, potentially across multiple controllers. A fourth type, &amp;#8220;acceptance tests&amp;#8221; is sometimes used to mean tests that exercise workflows from a user perspective, usually by automatically triggering actual view code. We&amp;#8217;ll skip that in this screencast.&lt;/p&gt;
&lt;h3&gt;Testing in Rails&lt;/h3&gt;
&lt;p&gt;When you generate a new Rails application, you will note that a test directory is created. Inside of test, you will see a number of directories: fixtures, functional, integration, mocks, and unit.&lt;/p&gt;
&lt;p&gt;Unit, functional, and integration directories match up with the test types we just defined.&lt;/p&gt;
&lt;p&gt;The fixtures directory is used to store test data that can be automatically loaded inside of test code to simulate a known state of your program. Commonly, fixtures are written in &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt;, although they can be stored in other formats and can also use Erb to implement dynamic data generation.&lt;/p&gt;
&lt;p&gt;Mock objects are objects that stand-in for real code, replacing expensive (resource-wise), external, or state-changing code. The mocks directory was originally intended as a place you could drop code that would replace other code in your project during testing. This practice is largely deprecated in favor of using external libraries such as &amp;#8220;Mocha&amp;#8221; or &amp;#8220;FlexMock&amp;#8221;. We&amp;#8217;ll passover this are in this screencast.&lt;/p&gt;
&lt;p&gt;When you use one of the script/generator scripts for making models, controllers, or even scaffold, they will generate pre-populated test code in the proper directory. You can make your own test files too.&lt;/p&gt;
&lt;p&gt;A test is simply a class that is derived from one of several parent class that Rails provides. Parent classes implement functionality appropriate for the kind of test, e.g. ActionController::TestCase sets up an environment that allows you to simulate calling a controller. Behind all of these Rails provided classes is the Ruby library called Test::Unit.&lt;/p&gt;
&lt;p&gt;A test class is made up of one or more methods. Each method examines one aspect of the object under test. The checks we do in a test method are called &amp;#8220;assertions&amp;#8221;. The testing framework provides a wide variety of helper methods that we can use to write assertions. Most assertions boil down to checking whether some condition is true or false. For instance, in our &lt;code&gt;links_controller_test.rb&lt;/code&gt; file, we can find a test that checks whether we can get the &lt;code&gt;new&lt;/code&gt; action&amp;#8217;s form:&lt;/p&gt;
&lt;pre&gt;
	def test_should_get_new
    get :new
    assert_response :success
  end
&lt;/pre&gt;
&lt;p&gt;We see one assertion using the &lt;code&gt;assert_response&lt;/code&gt; helper method. &lt;code&gt;assert_response&lt;/code&gt; examines the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; response object that comes back from doing an &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;GET&lt;/span&gt; on the @LinkController@&amp;#8217;s &lt;code&gt;new&lt;/code&gt; action. We are asserting that the response code will be a success code, such as 200. We&amp;#8217;ll see many different kinds of assertions as we write tests.&lt;/p&gt;
&lt;p&gt;You will note that certain naming convention are in play for tests, just like elsewhere in Rails. Test files end with the suffix &amp;#8220;_test&amp;#8221; and test methods inside of these files start with the &amp;#8220;test_&amp;#8221; prefix.&lt;/p&gt;
&lt;p&gt;As we look inside of the test subdirectories, we&amp;#8217;ll see a lot of files that have been generated as we&amp;#8217;ve worked on our &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; project. How do we use these tests?&lt;/p&gt;
&lt;h3&gt;Running Tests&lt;/h3&gt;
&lt;p&gt;Rails provides a complete environment for running your tests. Look inside the config directory and you will see an environment/test.rb file. This sets up testing specific options within the Rails framework to maximize the amount of testing checks that occur. Database.yml specifies a separate test environment as well. The test oriented database keeps your test data separated from your development or production data and allows the test tools to set up pristine testing conditions as needed. You can ascertain your test database is ready to go with the &lt;code&gt;rake db:test:prepare&lt;/code&gt; command. Let&amp;#8217;s do that now.&lt;/p&gt;
&lt;p&gt;Ruby and Rails provides a number of ways to run our tests. The easiest manual way is to fire up the &lt;code&gt;rake test&lt;/code&gt; command. This command will run all of our tests: unit, functional, and if present, integration. We can run a subset of our tests by specifying the type, such as &lt;code&gt;rake test:units&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s take a look at how the project is fairing at the moment:&lt;/p&gt;
&lt;pre&gt;
	rake test
&lt;/pre&gt;
&lt;p&gt;This runs our tests and we see a lot of diagnostics go by. Let&amp;#8217;s examine a few critical pieces of information.&lt;/p&gt;
&lt;p&gt;First, a test can be in one of three states:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Success, indicated with a period (&lt;code&gt;.&lt;/code&gt;), sometimes also called &amp;#8220;green&amp;#8221;;&lt;/li&gt;
	&lt;li&gt;Failure, indicated with an &lt;code&gt;F&lt;/code&gt;, (called &amp;#8220;red&amp;#8221;), which means one of the assertions we wrote to test an assumption about our code did not work;&lt;/li&gt;
	&lt;li&gt;Error, indicated by an &lt;code&gt;E&lt;/code&gt;, (also called &amp;#8220;red&amp;#8221;), which means a program logic problem was detected in our test or application code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The rake test results print out a sequence of progress characters for each test run:&lt;/p&gt;
&lt;pre&gt;
	....FFFF....E...
&lt;/pre&gt;
&lt;p&gt;Second, each test that fails or errors out will display relatively detailed information about what went wrong. This is your first line of defense to track the program down:&lt;/p&gt;
&lt;pre&gt;
	  3) Failure:
	test_should_get_edit(CategoriesControllerTest)
	    [./test/functional/categories_controller_test.rb:30:in `test_should_get_edit'
	     /Library/Ruby/Gems/1.8/gems/activesupport-2.0.2/lib/active_support/testing/default.rb:7:in `run']:
	Expected response to be a &amp;lt;:success&amp;gt;, but was &amp;lt;302&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The testing environment in Rails also has its own log file, so you can peek inside of log/test.log for more information too.&lt;/p&gt;
&lt;p&gt;Armed with this information, let&amp;#8217;s start cleaning up our &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; program&amp;#8217;s broken tests.&lt;/p&gt;
&lt;h2&gt;Cleaning up the tests&lt;/h2&gt;
&lt;h3&gt;Unit Tests&lt;/h3&gt;
&lt;p&gt;We are working through our tests type by type. First up is unit tests and on running &lt;code&gt;rake test&lt;/code&gt;, generally it looks good, only one problem, right? Yes and no. The error comes from our mailer test, which we&amp;#8217;ll fix shortly. It turns out that the other model tests are largely empty. We&amp;#8217;ll demonstrate adding a test to one of these files and leave it as an exercise to you to fill in more tests.&lt;/p&gt;
&lt;p&gt;Fortunately some plugins, such as the restful_authentication plugin we used, generate their own tests, and our user and session models start out with some useful tests that you can examine. Take a peek at user_test.rb. Lots of good tests for verifying that the User model is working.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s look at the tests for our Message model, since it is used by our mailer. The default scaffold generator creates a test file that contains an empty test:&lt;/p&gt;
&lt;pre&gt;
	require File.dirname(__FILE__) + '/../test_helper'

	class MessageTest &amp;lt; ActiveSupport::TestCase
	  # Replace this with your real tests.
	  def test_truth
	    assert true
	  end
	end&lt;/pre&gt;
&lt;p&gt;That isn&amp;#8217;t too useful. Recall that the Message model does some validation. Let&amp;#8217;s test those validators:&lt;/p&gt;
&lt;pre&gt;
	class Message &amp;lt; ActiveRecord::Base
	  validates_presence_of :name, :subject, :body
	  validates_format_of :email, :with =&amp;gt; /^(\S+)@(\S+)\.(\S+)$/
	end
&lt;/pre&gt;
&lt;p&gt;We add a variety of tests in MessageTest:&lt;/p&gt;
&lt;pre&gt;
  def setup
    @message = Message.create(:name =&amp;gt; 'Bob', :email =&amp;gt; 'bob@example.com', :company =&amp;gt; 'Acme', 
                            :phone =&amp;gt; '123.456.7890', :subject =&amp;gt; 'test subject', :body =&amp;gt; 'please test me')
  end
    
  def test_valid_model
    assert_valid @message
  end

  def test_missing_required_attributes
    assert_equal false, Message.new.valid?
  end

  def test_requires_name
    @message.name = nil
    assert_equal false, @message.valid?
    assert_equal &quot;can't be blank&quot;, @message.errors[:name]
  end

  def test_requires_subject
    @message.subject = nil
    assert_equal false, @message.valid?
    assert_equal &quot;can't be blank&quot;, @message.errors[:subject]
  end

  def test_requires_body
    @message.body = nil
    assert_equal false, @message.valid?
    assert_equal &quot;can't be blank&quot;, @message.errors[:body]
  end

  def test_does_not_require_phone
    @message.phone = nil
    assert_valid @message
  end

  def test_poor_email_formatting
    @message.email = 'spammer-no-domain'
    assert_equal false, @message.valid?
    assert_equal &quot;is invalid&quot;, @message.errors[:email]
  end
&lt;/pre&gt;
&lt;p&gt;The setup method is called before each test method is run and sets up a known correct example of our &lt;code&gt;Message&lt;/code&gt; object for us to use. We check whether the object is valid, we see that a new empty &lt;code&gt;Message&lt;/code&gt; is not valid (it fails validation on our required attributes), and proceed to test our required attributes and email formatting rules.&lt;/p&gt;
&lt;p&gt;We can use a different technique for setting up test data by using &lt;em&gt;fixtures&lt;/em&gt;. First, lets set up the fixture files links.yml:&lt;/p&gt;
&lt;pre&gt;
learningrails:
  url: http://learningrails.com/
  title: LearningRails podcast home page
  description: Pod and screencast dedicated to learning the Ruby on Rails framework
  categories: ruby, rails

google:
  url: http://google.com/
  title: Google
  description: Widely used search engine
  categories: search
&lt;/pre&gt;
&lt;p&gt;and categories.yml:&lt;/p&gt;
&lt;pre&gt;
ruby:
  title: Ruby
  description: Ruby the Programming Language
  links: learningrails

rails:
  title: Ruby on Rails
  description: Rails is a cool framework
  links: learningrails

search:
  title: Search Engine
  description: Used to find things on the web
  links: google	
&lt;/pre&gt;
&lt;p&gt;Fixtures are smart about associations. We can specify attributes &lt;em&gt;and&lt;/em&gt; associations. The associations are set up using the name of the association, then the id of the related fixture. The id is simply the first non-indented word of each &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt; block. When the test code loads up these fixtures, it automatically sets up the associations.&lt;/p&gt;
&lt;p&gt;Now we can use these fixtures in our link_test.rb file:&lt;/p&gt;
&lt;pre&gt;
	require File.dirname(__FILE__) + '/../test_helper'

	class LinkTest &amp;lt; ActiveSupport::TestCase

	  fixtures :categories, :links

	  def setup
	    @link = Link.create(:url =&amp;gt; 'http://buildingwebapps.com/', :title =&amp;gt; 'BuildingWebApps.com', 
	                      :description =&amp;gt; 'Resource for Web Developers')
	    @category = Category.create(:title =&amp;gt; 'Programming', :description =&amp;gt; 'All about programming')
	  end

	  # Replace this with your real tests.
	  def test_valid_model
	    assert_valid @link
	  end

	  def test_valid_from_fixture
	    assert_valid links(:learningrails)
	  end

	  def test_has_categories
	    link = links(:learningrails)
	    assert_valid link
	    assert !link.categories.nil?
	    assert_equal 2, link.categories.length
	  end

	  def test_add_category
	    assert_valid @link
	    assert_valid @category
	    assert @link.categories.empty?
	    assert @category.links.empty?
	    assert_difference &quot;@link.categories.length&quot; do
	      @link.categories &amp;lt;&amp;lt; @category
	    end
	    @link.reload
	    @category.reload
	    assert !@link.categories.empty?
	    assert !@category.links.empty?
	    assert_equal 1, @link.categories.length
	    assert_equal 1, @category.links.length
	  end

	end
&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Note the &lt;code&gt;fixtures&lt;/code&gt; call near the top. This explicitly tells the test code to load the named fixture files into the test database before each run of the tests. Like before, we also create a couple of hard-coded objects to use in some of our tests. &lt;code&gt;test_valid_model&lt;/code&gt; is exactly like before. &lt;code&gt;test_valid_from_fixture&lt;/code&gt; demonstrates how you can reference an instance of a fixture data object instead. Here we refer to the links fixture data with the id &lt;code&gt;:learningrails&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The rest of the tests exercise the &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; association.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ll leave testing the other model&amp;#8217;s to you. Before we leave unit tests, though, let&amp;#8217;s fix up the mailer test, since it is a little different.&lt;/p&gt;
&lt;pre&gt;
	  1) Error:
	test_message(ContactMailerTest):
	NoMethodError: undefined method `subject' for Thu Jun 26 14:53:52 -0700 2008:Time
	    /Users/chaupt/Documents/Business Documents/CollectiveKnowledgeworks/Podcasts/sc11/learningrails_19/app/models/contact_mailer.rb:4:in `message'
	    /Library/Ruby/Gems/1.8/gems/actionmailer-2.0.2/lib/action_mailer/base.rb:410:in `__send__'
	    /Library/Ruby/Gems/1.8/gems/actionmailer-2.0.2/lib/action_mailer/base.rb:410:in `create!'
	    /Library/Ruby/Gems/1.8/gems/actionmailer-2.0.2/lib/action_mailer/base.rb:403:in `initialize'
	    /Library/Ruby/Gems/1.8/gems/actionmailer-2.0.2/lib/action_mailer/base.rb:351:in `new'
	    /Library/Ruby/Gems/1.8/gems/actionmailer-2.0.2/lib/action_mailer/base.rb:351:in `method_missing'
	    ./test/unit/contact_mailer_test.rb:10:in `test_message'
	    /Library/Ruby/Gems/1.8/gems/activesupport-2.0.2/lib/active_support/testing/default.rb:7:in `run'

	18 tests, 30 assertions, 0 failures, 1 errors
&lt;/pre&gt;
&lt;p&gt;This gives us a clue as to what went wrong and where. The &lt;code&gt;ContactMailerTest&lt;/code&gt; class&amp;#8217; &lt;code&gt;test_message&lt;/code&gt; method had a programming error in it: an undefined method &amp;#8216;subject&amp;#8217;.&lt;/p&gt;
&lt;p&gt;This test is exercising the pseudo model that was created when we generated our contact mailer. The test inside of the test class looks like this:&lt;/p&gt;
&lt;pre&gt;
  def test_message
    @expected.subject = 'ContactMailer#message'
    @expected.body    = read_fixture('message')
    @expected.date    = Time.now

    assert_equal @expected.encoded, ContactMailer.create_message(@expected.date).encoded
  end
&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Mailer related unit tests are a little strange. What this code is trying to do is test to see if the mail message that gets generated by the &lt;code&gt;ContactMailer.message&lt;/code&gt; method is identical to a canned email fixture. &lt;code&gt;@expected&lt;/code&gt; is an instance variable created for us by the testing class that embodies a TMailer object and which we&amp;#8217;ll load with data and subsequently ask to generate a properly formed email body and headers (that is what &lt;code&gt;encoded&lt;/code&gt; does).&lt;/p&gt;
&lt;p&gt;Here we see that the other special calling convention on a mailer is being used:   &lt;code&gt;create_message&lt;/code&gt;. Like &lt;code&gt;deliver_message&lt;/code&gt;, this method uses the &lt;code&gt;message&lt;/code&gt; method we wrote, but rather than building a mail message and then actually emailing it out, this form just returns a string that contains the body of the email message.&lt;/p&gt;
&lt;p&gt;To fix this test, we are going to take a different approach. Since we generate a multipart email (plain text and html), we&amp;#8217;ll generate a mail message then probe it for correct results. We&amp;#8217;ll use Ruby&amp;#8217;s inline document string notation to specify a test value for our message body (rather than a fixture file). Note we could put some of this in a setup method like before, but in versions of Rails before 2.1, setup was slightly broken for mail tests:&lt;/p&gt;
&lt;pre&gt;
	  def test_message
	    # using a the setup method is not functioning properly for Rails prior to 2.1. This should 
	    # rightly be put in such a setup file
	    @message = Message.new(:name =&amp;gt; 'Bob', :email =&amp;gt; 'bob@example.com', :company =&amp;gt; 'Acme', 
	                            :phone =&amp;gt; '123.456.7890', :subject =&amp;gt; 'test subject', :body =&amp;gt; 'please test me')

	    test_body = &amp;lt;&amp;lt;EOF
	Email from your web site

	From: Bob

	Company: Acme

	Phone: 123.456.7890

	Message: please test me
	EOF

	    created = ContactMailer.create_message(@message,@expected.date)
	    assert_equal 2,created.parts.size

	    assert_equal &quot;multipart/alternative&quot;, created.content_type
	    assert_equal &quot;text/plain&quot;, created.parts[0].content_type
	    assert_equal &quot;text/html&quot;, created.parts[1].content_type
	    assert_equal test_body, created.parts[0].body
	  end
&lt;/pre&gt;
&lt;p&gt;We save and run this now, and Success! Our admittedly mostly empty unit tests are all running in the &amp;#8220;green&amp;#8221; state. Let&amp;#8217;s go on to fix up some of our functional tests.&lt;/p&gt;
&lt;h2&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;We will continue testing in the next episode where we focus on the functional tests.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:39:00</itunes:duration>
        </item>
        
        <item>
          <title>18: Adding a Contact Form and Mailer</title>
          <description>&lt;p&gt;In this lesson, we're creating the Contact page. There's two major parts to this: creating the message model and the associated forms and admin setup, and then creating a mailer that takes new messages and sends them to the site administrator via email.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:54 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79343-adding-a-contact-form-and-mailer</guid>
          <link>http://www.buildingwebapps.com/podcasts/79343-adding-a-contact-form-and-mailer</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-18.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we&amp;rsquo;re creating the &amp;ldquo;Contact Us&amp;rdquo; page. There&amp;rsquo;s two major parts to this: creating the message model and the associated forms and admin setup, and then creating a mailer that takes new messages and sends them to the site administrator via email.&lt;/p&gt;
&lt;p&gt;Please note that, while we&amp;rsquo;ve tried to make these notes complete, they aren&amp;rsquo;t the full tutorial; that&amp;rsquo;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 17. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_17.zip&quot;&gt;Learning Rails example app code as of the start of this lesson&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_18.zip&quot;&gt;Learning Rails example app code as of the end of this lesson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Creating the contact form&lt;/h2&gt;
&lt;h3&gt;Scaffolding the Message Model&lt;/h3&gt;
&lt;p&gt;If we only wanted to send an email when the contact form was filled in, we wouldn&amp;rsquo;t really need to use an Active Record model and save it to the database. But it&amp;rsquo;s actually easier to use all the scaffolding and other support that Active Record provides, and it is handy to have the messages stored in the database so the can be reviewed independently of email.&lt;/p&gt;
&lt;p&gt;We start by creating a scaffold for contacts:&lt;/p&gt;
&lt;pre&gt;
script/generate scaffold message name:string company:string phone:string email:string subject:string body:text
&lt;/pre&gt;
&lt;p&gt;This generates the model, controller, views, and test files.&lt;/p&gt;
&lt;p&gt;Now run the migration:&lt;/p&gt;
&lt;pre&gt;
rake db:migrate&lt;/pre&gt;
&lt;p&gt;And start the server:&lt;/p&gt;
&lt;pre&gt;
script/server&lt;/pre&gt;
&lt;h3&gt;Hooking up the Contact Form&lt;/h3&gt;
&lt;p&gt;First delete the layout file the scaffold generates (views/layouts/messages.html.erb), so the scaffolded views will use our standard layout.&lt;/p&gt;
&lt;p&gt;We already have a contact button in the navigation bar, but this is pointing to one of our initial static pages, and now we want it to point to the new contact form. So run the sample app (script/server), log in, go to the Page Admin, and edit the Contact page to set it to redirect (using the capability we added in the &lt;a href=&quot;/podcasts/79342-resources-page-links-categories-and-habtm&quot;&gt;Lesson 17&lt;/a&gt;) to the &lt;code&gt;new&lt;/code&gt; action in the &lt;code&gt;messages&lt;/code&gt; controller.&lt;/p&gt;
&lt;p&gt;Since we&amp;rsquo;ve hijacked a scaffolded form that was meant to be part of the admin and are using it for a user-facing form, we need to tweak it a bit. Delete this line from the end of views/messages/new.html.erb, since we don&amp;rsquo;t want visitors to try to get to the list of all messages:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= link_to 'Back', messages_path %&amp;gt;
&lt;/pre&gt;
&lt;h3&gt;Redirecting to Home after Submission&lt;/h3&gt;
&lt;p&gt;We don&amp;rsquo;t want to redirect to the message/show action, which is part of the admin interface and is what the scaffolding does by default. So we&amp;rsquo;ll change the redirect to go to the home page, and change the flash message to something more appropriate. Users who submit a message will see the thank-you message at the top of the home page.&lt;/p&gt;
&lt;p&gt;In the message controller&amp;rsquo;s show action:&lt;/p&gt;
&lt;pre&gt;
if @message.save
  flash[:notice] = 'Thanks for Your Message'
  format.html { redirect_to root_path }
&lt;/pre&gt;
&lt;p&gt;Later in this lesson, we&amp;rsquo;ll further modify this code to actually send the messages as an email, in addition to saving it to the database.&lt;/p&gt;
&lt;h3&gt;Message validations&lt;/h3&gt;
&lt;p&gt;We want to be sure that the message looks valid before processing it, so we add the following validations to the message model (models/message.rb):&lt;/p&gt;
&lt;pre&gt;
validates_presence_of :name, :subject, :body
validates_format_of :email, :with =&amp;gt; /^(\S+)@(\S+)\.(\S+)$/
&lt;/pre&gt;
&lt;p&gt;The second validation ensures that the email looks like a valid email address. This messy regular expression is one of the simpler ones of many that could be used.&lt;/p&gt;
&lt;p&gt;To apply some styling to the error messages that are displayed if a validation fails, modify the stylesheet line in application.html.erb:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= stylesheet_link_tag 'learningrails', 'scaffold' %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This includes the standard Rails &lt;code&gt;scaffold.css&lt;/code&gt; file, which the rails script created as part of the initial creation of the application.&lt;/p&gt;
&lt;h3&gt;Fetching the Page Object&lt;/h3&gt;
&lt;p&gt;To keep the Contact Us tab highlighted while the contact form is displayed, and to set the page title, we need to fetch the page object and set the pagetitle instance variable. We did this already for the links_controller/list action in the &lt;a href=&quot;/learningrails/17&quot;&gt;Lesson 17&lt;/a&gt;; let&amp;rsquo;s extract that code, and put it in a method that we store in application.rb:&lt;/p&gt;
&lt;pre&gt;
def get_page_metadata
  @page = Page.find_by_name(params[:name])
  @pagetitle = @page.title
end
&lt;/pre&gt;
&lt;p&gt;Now we can use this same method in both links_controller/list and messages_controller/new. In the future, we&amp;rsquo;ll include this method in any action to which we&amp;rsquo;re redirecting via the &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;.&lt;/p&gt;
&lt;h3&gt;Setting Up the Messages Admin&lt;/h3&gt;
&lt;p&gt;For convenience, we&amp;rsquo;ll edit the admin page (using the &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;) to add a link to the message admin:&lt;/p&gt;
&lt;pre&gt;
&amp;quot;Message Admin&amp;quot;:/messages&lt;/pre&gt;
&lt;p&gt;We don&amp;rsquo;t want site visitors being able to view the list of contact messages, so we need to add authentication to the contacts controller. But we do need the &amp;ldquo;new&amp;rdquo; action in this controller to be accessible to visitors, as well as the &amp;ldquo;create&amp;rdquo; action that is invoked by the form when it is submitted. So add the following line to the start of controllers/messages_controller.rb:&lt;/p&gt;
&lt;pre&gt;
before_filter :login_required, :except =&amp;gt; [:new, :create]
&lt;/pre&gt;
&lt;h2&gt;Preparing to Send the Message&lt;/h2&gt;
&lt;h3&gt;Setting Up the Mailer&lt;/h3&gt;
&lt;p&gt;Thanks to the scaffold generator and our &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;, we hardly had to write any code to create the contact form or the admin interface that allows us to read them. That was the easy part &amp;mdash; now we want to generate an email to the web site manager with the contents of the message.&lt;/p&gt;
&lt;h3&gt;Creating the Mailer&lt;/h3&gt;
&lt;p&gt;The first step is to create a special Rails model called a mailer. As with other things in the Rails world, there&amp;rsquo;s a generator to make them. The command is:&lt;/p&gt;
&lt;pre&gt;
script/generate mailer contact_mailer message
&lt;/pre&gt;
&lt;p&gt;This creates a mailer model, called contact_mailer, and its associated view, which we&amp;rsquo;ve called message. You can enter multiple views here, for example if you had different kinds of contact forms and wanted to format each message differently.&lt;/p&gt;
&lt;h3&gt;Configuring How Mail is Sent&lt;/h3&gt;
&lt;p&gt;To actually send mail, we need to tell Rails how it supposed to access the mail system. You can configure it to use an &lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt; server, or you can tell it to use sendmail, which is the more common approach if you&amp;rsquo;re on a Unix-type system; you&amp;rsquo;ll need a few details from the system administrator for the configuration for settings. In development mode, you&amp;rsquo;ll probably want to use an &lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt; server to which you have access for testing. For example, here&amp;rsquo;s the configuration for sending email via &lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt; over a Comcast connection:&lt;/p&gt;
&lt;pre&gt;
ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.smtp_settings = {
  :address =&amp;gt; 'smtp.comcast.net',
  :domain =&amp;gt; 'comcast.net'
}
&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;ll add this code to config/environments/development.rb. You&amp;rsquo;d need to add similar code to production.rb for whatever &lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt; server you&amp;rsquo;re using in your production environment.&lt;/p&gt;
&lt;p&gt;You can use :test for the method instead of :smtp, in which case all the messages are stored in an array, instead of being sent out.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;SMTP&lt;/span&gt; servers are picky about what mail they will accept, so if you&amp;rsquo;re not on a Comcast connection you&amp;rsquo;ll have to modify these settings. You can also specify additional parameters, including the port number, if it is not the default 25, as well as a user name and login if authentication is required.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re having trouble getting your mail to go out in development mode, you may want to change this line in your development environment:&lt;/p&gt;
&lt;pre&gt;
config.action_mailer.raise_delivery_errors = false
&lt;/pre&gt;
&lt;p&gt;And set it to &lt;code&gt;true&lt;/code&gt; instead. If you don&amp;rsquo;t do that, delivery failures are silently ignored in development mode.&lt;/p&gt;
&lt;h3&gt;Setting Up the Mailer Model&lt;/h3&gt;
&lt;p&gt;Once you&amp;rsquo;ve run the generator, you&amp;rsquo;ll find a file contact_mailer.rb in your models folder. Open that file, and you&amp;rsquo;ll find one method, &lt;code&gt;message&lt;/code&gt;. The method is in a class that inherits from ActionMailer::Base, rather than ActiveRecord::Base like all your other models, so it has a different set of characteristics and capabilities.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re going to replace this method with the following:&lt;/p&gt;
&lt;pre&gt;
def message(message)
  subject    message.subject
  body       :message =&amp;gt; message
  recipients CONTACT_RECIPIENT
  from       message.email
  sent_on    Time.now
end
&lt;/pre&gt;
&lt;p&gt;Note that we&amp;rsquo;re not setting variables with names like subject; we&amp;rsquo;re invoking methods, which are available to all mailer methods, and passing parameters to those methods (earlier versions of rails used instance variables instead).&lt;/p&gt;
&lt;p&gt;The subject is simple enough; we&amp;rsquo;re just setting the parameter for the subject method to the subject attribute of the message, which we&amp;rsquo;ve passed into this method.&lt;/p&gt;
&lt;p&gt;For the body, we provide a hash that has the name of the instance variable we want to pass, and the value of that variable. We have only one variable here; you could have several. This passes the message object to an instance variable named @message that will be available in the view.&lt;/p&gt;
&lt;p&gt;Now we set the recipient to a constant, rather than a literal value, because we don&amp;rsquo;t want a specific email address, which may change in time, deep in our code. Add this line in your config/environments/development.rb file:&lt;/p&gt;
&lt;pre&gt;
CONTACT_RECIPIENT = 'yourname@yourdomain.com'
&lt;/pre&gt;
&lt;p&gt;Another benefit of this approach is that you can set a different address in your production.rb environment file. For example, in development, you&amp;rsquo;ll probably want contact messages to go to you, but in production, they typically go to an administrative or sales person.&lt;/p&gt;
&lt;p&gt;Finally, we set the &amp;ldquo;from&amp;rdquo; address and the time.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it for the mailer model. Now on to the view.&lt;/p&gt;
&lt;h3&gt;Creating the Mailer View&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ll find an empty view in views/contact_mailer/message.erb. This is the view that will get invoked when we use the mailer model to request deliver of a message.&lt;/p&gt;
&lt;p&gt;The instance variables passed to this view are those we defined in the &lt;code&gt;@body&lt;/code&gt; variable in the model. Now we use them just like in a regular view, but remember that we&amp;rsquo;re generating a plain-text email here, so there&amp;rsquo;s no &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; code required. Everything we need is in the @message variable, which holds the message object created from the form. Here&amp;rsquo;s a simple view:&lt;/p&gt;
&lt;pre&gt;
Email from your web site

From: &amp;lt;%= @message.name %&amp;gt;

Company: &amp;lt;%= @message.company %&amp;gt;

Phone: &amp;lt;%= @message.phone %&amp;gt;

Message: &amp;lt;%= @message.body %&amp;gt;
&lt;/pre&gt;
&lt;h2&gt;Delivering the Mail&lt;/h2&gt;
&lt;p&gt;With all this setup behind us, actually delivering the mail is easy. Open the file controllers/messages_controller.rb, and add this line immediately after &amp;ldquo;if @message.save&amp;rdquo; (we only want to deliver the mail if the save was successful, indicating that any validations passed):&lt;/p&gt;
&lt;pre&gt;
ContactMailer.deliver_message(@message)
&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;re invoking the message method in the ContactMailer class (defined in models/contact_mailer.rb). We pass to that method the message object from the form.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one strange thing here: the method we&amp;rsquo;re invoking is &amp;ldquo;deliver_message&amp;rdquo;, not &amp;ldquo;message&amp;rdquo;. Rails creates this method name for us, and we have to use it. Just one of those oddities to get used to. (This odd syntax exists to support another option: you can call the create_message method, which will produce the mail object, ready to be sent, but won&amp;rsquo;t actually send it.)&lt;/p&gt;
&lt;p&gt;You can now start the server and create a contact message, and it should be sent. Depending on what system you&amp;rsquo;re running on, and how your mail delivery is configured, it may not actually go out, but you can look at the Rails log (which should be in the console window in which you started the server), and it will show the email that was generated, even if it couldn&amp;rsquo;t contact a mail system to actually send it.&lt;/p&gt;
&lt;h2&gt;Sending &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; and Multipart email&lt;/h2&gt;
&lt;p&gt;You can easily send &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; or multipart email as well. If you simply name your view files appropriately, Rails will automatically produce multipart mail, so mail readers that accept &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; will get that, and others will get text.&lt;/p&gt;
&lt;p&gt;Rename message.erb to message.text.plain.erb, and make a new file in that same folder called message.text.html.erb. In that file, put an &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; version of the message, such as:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;h1&amp;gt;Email from your web site&amp;lt;/h1&amp;gt;
&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;From: &amp;lt;%= @message.name %&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Company: &amp;lt;%= @message.company %&amp;gt;&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Phone: &amp;lt;%= @message.phone %&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;p&amp;gt;Message: &amp;lt;%= @message.body %&amp;gt;&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now when the message is sent, it will be sent as a multipart message.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00::00</itunes:duration>
        </item>
        
        <item>
          <title>17: Resources Page: Links, Categories, and HABTM</title>
          <description>&lt;p&gt;So far, our Resources page is just a page of text in the CMS. That's hard to maintain -- we want to have a database of links, shown by category.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:54 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79342-resources-page-links-categories-and-habtm</guid>
          <link>http://www.buildingwebapps.com/podcasts/79342-resources-page-links-categories-and-habtm</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-17.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we&amp;rsquo;re creating the database-driven Resources page, with links shown by category. Along the way, we look at join tables and &lt;span class=&quot;caps&quot;&gt;HABTM&lt;/span&gt; associations.&lt;/p&gt;
&lt;p&gt;Please note that, while we&amp;rsquo;ve tried to make these notes complete, they aren&amp;rsquo;t the full tutorial; that&amp;rsquo;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 16. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_16.zip&quot;&gt;Learning Rails example app code as of the start of this lesson&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_17.zip&quot;&gt;Learning Rails example app code as of the end of this lesson&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Adding the Links and Categories Models&lt;/h2&gt;
&lt;p&gt;For each link, we want to have a title and a description, and of course we need the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;. Let&amp;rsquo;s use the scaffold generator to create the model and the admin page:&lt;/p&gt;
&lt;pre&gt;
script/generate scaffold link url:string title:string description:text
&lt;/pre&gt;
&lt;p&gt;The &amp;ldquo;text&amp;rdquo; field type can hold longer strings that the &amp;ldquo;string&amp;rdquo; type, which is why we used it for the description.&lt;/p&gt;
&lt;p&gt;We also need a model for the categories, so let&amp;rsquo;s run another scaffold command for that simple model, which requires only a title and a description for each category:&lt;/p&gt;
&lt;pre&gt;
script/generate scaffold category title:string description:text
&lt;/pre&gt;
&lt;h2&gt;Creating the Join Table&lt;/h2&gt;
&lt;p&gt;When you have an association where one model has a &lt;code&gt;belongs_to&lt;/code&gt; declaration, you know that model must have a field to store the foreign key that is what creates the association. In the case of Categories and Links, however, a category can have many links, and a link can belong to many categories, so what we need here is a &lt;code&gt;has_and_belongs_to_many&lt;/code&gt; association.&lt;/p&gt;
&lt;p&gt;In this type of association, neither of the associated tables stores any foreign keys; instead, a separate join table stores just the pairs of foreign keys that define each association (i.e., associate one link with one category).&lt;/p&gt;
&lt;p&gt;We need to explicitly create this join table. There is no model associated with this table; it is just a database table that is use automatically along with the two associated models.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s generate an empty migration file with the migration generator:&lt;/p&gt;
&lt;pre&gt;
script/generate migration LinkCategoryJoin
&lt;/pre&gt;
&lt;p&gt;Note that the name is entirely arbitrary; we just want something that reminds us of what this migration is for.&lt;/p&gt;
&lt;p&gt;Now we define the migration by writing the &lt;code&gt;self.up&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;
def self.up
  create_table :categories_links, :id =&amp;gt; false do |t|
    t.integer :category_id
    t.integer :link_id
  end
end
&lt;/pre&gt;
&lt;p&gt;This creates a table with two columns, each of which is one of the foreign keys. This table doesn&amp;rsquo;t get an id column of its own, so we add the option &lt;code&gt;:id =&amp;gt; false&lt;/code&gt; to the &lt;code&gt;create_table&lt;/code&gt; method call.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s several Rails naming defaults that come into play here, and you need to know what they are to write this code correctly:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Join tables are always named with the names of the two associated tables, in alphabetical order, separated by an underscore. That&amp;rsquo;s why the table is called &lt;code&gt;categories_links&lt;/code&gt;, and not &lt;code&gt;links_categories&lt;/code&gt; (which won&amp;rsquo;t work because of this default).&lt;/li&gt;
    &lt;li&gt;The foreign key fields are named with the name of the table they are referencing, with &lt;code&gt;_id&lt;/code&gt; appended.&lt;/li&gt;
    &lt;li&gt;The foreign key is referencing a single element in that table, so it uses the singular name (e.g., &lt;code&gt;category_id&lt;/code&gt;, not &lt;code&gt;categories_id&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To keep our migrations reversible, we&amp;rsquo;ll add the &lt;code&gt;down&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;
def self.down
  drop_table :categories_links
end
&lt;/pre&gt;
&lt;h2&gt;Migrate!&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ve now created three new migrations, one for categories, one for links, and one for the join table. A single command runs them all:&lt;/p&gt;
&lt;pre&gt;
rake db:migrate
&lt;/pre&gt;
&lt;h2&gt;Model Associations&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;ve defined the foreign keys when creating our models, but we still need to specify the associations for the model classes. In models/link.rb, we need to add to the empty &lt;code&gt;Link&lt;/code&gt; class:&lt;/p&gt;
&lt;pre&gt;
has_and_belongs_to_many :categories
&lt;/pre&gt;
&lt;p&gt;This statement creates the association &amp;ldquo;link has and belongs to many categories.&amp;rdquo; Its presence allows us to write elsewhere in our code &lt;code&gt;link.categories&lt;/code&gt; to retrieve the list of categories that has been assigned to this link. The join table that represents these assignments is managed for us automatically by the Rails framework.&lt;/p&gt;
&lt;p&gt;While we&amp;rsquo;re modifying the Link class, let&amp;rsquo;s require that at least a title be entered; there&amp;rsquo;s not much use to having a record without one:&lt;/p&gt;
&lt;pre&gt;
validates_presence_of :title
&lt;/pre&gt;
&lt;p&gt;Now we need to make a corresponding set of additions to the Category model. We&amp;rsquo;ll add to that empty class:&lt;/p&gt;
&lt;pre&gt;
has_and_belongs_to_many :links
validates_presence_of :title
&lt;/pre&gt;
&lt;p&gt;This &lt;span class=&quot;caps&quot;&gt;HABTM&lt;/span&gt; declaration allows us to write elsewhere in our code &lt;code&gt;category.links&lt;/code&gt;, to find all the links associated with a category.&lt;/p&gt;
&lt;h2&gt;Finishing up the Admin Interface&lt;/h2&gt;
&lt;p&gt;You can now browse to &lt;code&gt;localhost:3000/links&lt;/code&gt; to see the link admin page, but it still needs a bit of work.&lt;/p&gt;
&lt;p&gt;The Rails scaffold generator generates an empty layout file for every scaffold, assuming for some reason that we probably want a unique layout for each one. We don&amp;rsquo;t &amp;mdash; we want to use the standard application layout. So we need to delete the extra files that the scaffold dumped into views/layouts.&lt;/p&gt;
&lt;p&gt;To protect the admin pages from public users, add to links_controller and categories_controller:&lt;/p&gt;
&lt;pre&gt;
before_filter :login_required
&lt;/pre&gt;
&lt;p&gt;For ease of access, let&amp;rsquo;s add links to our new admin pages to the admin home page. Log into the site, click the Admin button, and then click the Page Admin link. Click the Edit link for the Admin page, and add the following to the links that make up the page body:&lt;/p&gt;
&lt;pre&gt;
&amp;quot;Category Admin&amp;quot;:/categories

&amp;quot;Link Admin&amp;quot;:/links
&lt;/pre&gt;
&lt;p&gt;(You can also use the Edit link on the Admin page, which triggers the in-place editor we created a couple lessons ago.)&lt;/p&gt;
&lt;h2&gt;Setting Categories&lt;/h2&gt;
&lt;p&gt;Now you can use the newly-created Category Admin link on the admin home page to create some categories; the scaffolded interface does everything we need. Go ahead and make a few.&lt;/p&gt;
&lt;p&gt;You can also add a link, using Link Admin, but there&amp;rsquo;s no place on the scaffolded link admin pages to specify the category. That&amp;rsquo;s because when we created the scaffold, the association didn&amp;rsquo;t exist. To use the standard Rails scaffolding, you need to manually modify the scaffold-generated view files to display or modify fields that come from associations.&lt;/p&gt;
&lt;p&gt;To create a category selector control on the new link form, we use the following slightly messy bit of code:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
	&amp;lt;b&amp;gt;Category&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.collection_select :category_ids, Category.find(:all, :order =&amp;gt; 'title'), :id, :title, {}, :multiple =&amp;gt; true %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;collection_select&lt;/code&gt; method creates an &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; form element that allows the user to choose from a list of items. The parameters passed are:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;:category_ids&lt;/code&gt; &amp;mdash; the attribute this element is setting&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;Category.find(:all, :order =&amp;gt; 'title')&lt;/code&gt; &amp;mdash; an array of objects that creates the list of choices&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;:id&lt;/code&gt; &amp;mdash; the value field of the objects in the list array&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;:title&lt;/code&gt; &amp;mdash; the name field of the objects in the list array&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;{}&lt;/code&gt; &amp;mdash; placeholder for an options hash that we&amp;rsquo;re not using&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;:multiple =&amp;gt; true&lt;/code&gt; &amp;mdash; option to allow user to select multiple items&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this code inserted in views/links/new.html.erb, you should now have a list of categories from which to choose (provided that you have added some categories to the database already).&lt;/p&gt;
&lt;p&gt;The same bit of code for the category selector needs to be added to the edit view as well. Even better, you could pull out the form guts into a partial, and invoke the same partial from both the new and edit view, as we did in a previous lesson.&lt;/p&gt;
&lt;p&gt;Now you can create some links and assign them to categories.&lt;/p&gt;
&lt;h2&gt;The Resources Page&lt;/h2&gt;
&lt;p&gt;For the Resources page, we want to show a list of all the links, sorted by category. The index action of the links controller is already use as part of the admin interface, so we need another action. We&amp;rsquo;ll add this &lt;code&gt;list&lt;/code&gt; action to links_controller.rb:&lt;/p&gt;
&lt;pre&gt;
def list
  @categories = Category.find(:all, :order =&amp;gt; 'title')
end
&lt;/pre&gt;
&lt;p&gt;This action is simply providing the view with a list of categories.&lt;/p&gt;
&lt;p&gt;We also need to change the before_filter we set for login, so this action won&amp;rsquo;t require login. Change the line at the top of the controller to:&lt;/p&gt;
&lt;pre&gt;
before_filter :login_required, :except =&amp;gt; [:list]
&lt;/pre&gt;
&lt;p&gt;Now, we need to create a new file, views/links/list.html.erb, to respond to this action; here&amp;rsquo;s the basic code:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;h1&amp;gt;Resources&amp;lt;/h1&amp;gt;
&amp;lt;% for category in @categories %&amp;gt;	
	&amp;lt;h2&amp;gt;&amp;lt;%=h category.title %&amp;gt;&amp;lt;/h2&amp;gt;
	&amp;lt;p&amp;gt;&amp;lt;%=h category.description %&amp;gt;&amp;lt;/p&amp;gt;
	&amp;lt;ul&amp;gt;
	  &amp;lt;% for link in category.links %&amp;gt;
		  &amp;lt;li&amp;gt;&amp;lt;%= link_to link.title, link.url %&amp;gt;&amp;lt;/li&amp;gt;
	  &amp;lt;% end %&amp;gt;
	&amp;lt;/ul&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Finally, since we&amp;rsquo;ve added another method to a RESTful controller, we need to declare that method in the route. In config/routes.rb, there is already a set of standard routes declared:&lt;/p&gt;
&lt;pre&gt;
map.resources :links&lt;/pre&gt;
&lt;p&gt;To add the route, we modify this as follows:&lt;/p&gt;
&lt;pre&gt;
map.resources :links, :collection =&amp;gt; {:list =&amp;gt; :get}&lt;/pre&gt;
&lt;p&gt;This specifies that the additional route operates on the entire collection of objects (not on a specific object), that its name is &lt;code&gt;:list&lt;/code&gt;, and it responds to &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; &lt;span class=&quot;caps&quot;&gt;GET&lt;/span&gt; requests.&lt;/p&gt;
&lt;p&gt;Our list now works if you access it at &lt;code&gt;localhost:3000/links/list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One small issue: if there&amp;rsquo;s an empty category (a category with no links) the category heading is still displayed. To make that go away, add a conditional around the loop in the list view:&lt;/p&gt;
&lt;pre&gt;
	&amp;lt;% for category in @categories %&amp;gt;	
		&amp;lt;% unless category.links.empty? %&amp;gt;
			&amp;lt;h2&amp;gt;&amp;lt;%=h category.title %&amp;gt;&amp;lt;/h2&amp;gt;	
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Redirecting Navigation&lt;/h2&gt;
&lt;p&gt;Now we have our Resources page being created from the database, and admin pages to add categories and links. Our last task is to connect it up the the navigation buttons.&lt;/p&gt;
&lt;p&gt;So far, our Resources page is a text page in our &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;. We&amp;rsquo;d like the Resources button to go to our list of links (/links/list), but the &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; doesn&amp;rsquo;t currently give us a way to do that. We want to keep using the page model to control navigation buttons, but allow page content to come from another controller, rather than from the page viewer.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s many different ways to tackle this problem. The one we&amp;rsquo;ve chosen here, as the simplest to implement, is to add attributes to the Page model so any page can be specified as a &amp;ldquo;redirect&amp;rdquo; page, which should not be rendered by the viewer but instead by another controller and action.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a migration to add these elements to the model:&lt;/p&gt;
&lt;pre&gt;
script/generate migration PageRedirect&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;up&lt;/code&gt; method adds three attributes:&lt;/p&gt;
&lt;pre&gt;
def self.up
  add_column :pages, :redirect, :boolean
  add_column :pages, :action_name, :string
  add_column :pages, :controller_name, :string
end
&lt;/pre&gt;
&lt;p&gt;And what up giveth, down taketh away:&lt;/p&gt;
&lt;pre&gt;
def self.down
  remove_column :pages, :redirect
  remove_column :pages, :action_name
  remove_column :pages, :controller_name
end
&lt;/pre&gt;
&lt;p&gt;Now make the changes to the database:&lt;/p&gt;
&lt;pre&gt;
rake db:migrate&lt;/pre&gt;
&lt;h2&gt;Updating the Page form&lt;/h2&gt;
&lt;p&gt;And now we just need to add the new fields to views/pages/_form.html.erb:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Redirect?&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.check_box :redirect %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Action&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.text_field :action_name %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Controller&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.text_field :controller_name %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;h2&gt;Acting Upon Redirect Pages&lt;/h2&gt;
&lt;p&gt;Now that we have this redirect information in the page model, we need to use it!&lt;/p&gt;
&lt;p&gt;We replace the link_to that generates the nav buttons, in the application layout, to:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% if page.redirect? %&amp;gt;
  &amp;lt;%= link_to page.navlabel, :action =&amp;gt; page.action_name, :controller =&amp;gt; page.controller_name, :name =&amp;gt; page.name %&amp;gt;
&amp;lt;% else %&amp;gt;
  &amp;lt;%= link_to page.navlabel, view_page_path(page.name) %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We pass the page name as a parameter so the action to which we&amp;rsquo;ve redirected can load the appropriate page object to get the page title and control the tab highlighting. So in the list action in the links controller, we add:&lt;/p&gt;
&lt;pre&gt;
	@page = Page.find_by_name(params[:name])
	@pagetitle = @page.title
&lt;/pre&gt;
&lt;p&gt;Now we need to edit the Resources page&amp;rsquo;s entry in the &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; to set it to redirect to the list action and the links controller, and voila! Our Resources button now takes us to the database-generated page.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:37:00</itunes:duration>
        </item>
        
        <item>
          <title>16: Clean-Up</title>
          <description>In this lesson we're taking a break from adding features to do a little cleanup, including improving how we handle page titles, fixing up the main and secondary navigation, and giving the login form field immediate focus.</description>
          <pubDate>Thu, 24 Jul 2008 08:00:54 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79341-clean-up</guid>
          <link>http://www.buildingwebapps.com/podcasts/79341-clean-up</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-16.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson we&amp;#8217;re taking a break from adding features to do a little cleanup:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Get the page title logic out of the application layout&lt;/li&gt;
	&lt;li&gt;Add page titles for admin and login pages&lt;/li&gt;
	&lt;li&gt;Make navigation buttons indicate which is the current page&lt;/li&gt;
	&lt;li&gt;Add a &amp;#8216;back to previous&amp;#8217; navigation link on subpages&lt;/li&gt;
	&lt;li&gt;Add a little styling to subnav links&lt;/li&gt;
	&lt;li&gt;Set the focus for the login field&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please note that, while we&amp;#8217;ve tried to make these notes complete, they aren&amp;#8217;t the full tutorial; that&amp;#8217;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 15. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_15.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 15&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_16.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 16&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Fix up Page Title Handling&lt;/h2&gt;
&lt;p&gt;Several lessons ago, as we were building the core of our content management system, we put a quick hack in the application layout (views/layouts/application.html.erb) that put this logic in the wrong place; we want to keep logic out of our views as much as practical. So let&amp;#8217;s replace this line:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;title&amp;gt;&amp;lt;%= @pagetitle || (@page &amp;amp;&amp;amp; @page.title) || 'Learning Rails Sample Application' %&amp;gt;&amp;lt;/title&amp;gt;
&lt;/pre&gt;
&lt;p&gt;with the much simpler:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;title&amp;gt;&amp;lt;%= @pagetitle %&amp;gt;&amp;lt;/title&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now we need to set this instance variable appropriately for each view. First, in the viewer_controller show method, insert the line (after @page is set):&lt;/p&gt;
&lt;pre&gt;
@pagetitle = @page.title
&lt;/pre&gt;
&lt;p&gt;That takes care of all pages that come from the content management system. Now we need to take care of the admin and login pages. Add to users_controller:&lt;/p&gt;
&lt;pre&gt;
before_filter :set_pagetitle

def set_pagetitle
  @pagetitle = 'User Administration'
end
&lt;/pre&gt;
&lt;p&gt;This before filter will run before every action, so the page title will be set (to the same thing) for all of them.&lt;/p&gt;
&lt;p&gt;In page controller, we already made a very similar addition in a previous lesson, but we called it &lt;code&gt;set_metadata&lt;/code&gt;, so for consistency we&amp;#8217;ll rename it to &lt;code&gt;set_pagetitle&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Finally, the sessions controller needs some attention. Add to the (empty) &lt;code&gt;new&lt;/code&gt; action in sessions_controller:&lt;/p&gt;
&lt;pre&gt;@pagetitle = 'Please Log In'&lt;/pre&gt;
&lt;p&gt;And after the &lt;code&gt;else&lt;/code&gt; in the sessions_controller&amp;#8217;s &lt;code&gt;create&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;@pagetitle = &quot;Login was not successful&quot;&lt;/pre&gt;
&lt;p&gt;You could do more to customize page titles for the various admin pages, but this is enough for us.&lt;/p&gt;
&lt;h2&gt;Highlight Current Nav Button&lt;/h2&gt;
&lt;p&gt;Next problem: make the appropriate nav button highlight to indicate the current page.&lt;/p&gt;
&lt;p&gt;First, we need to identify which nav button to highlight by using some Ruby code to conditionally insert an ID. We&amp;#8217;ll insert the following code in the application layout, in the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; tag that begins each nav button:&lt;/p&gt;
&lt;pre&gt;&amp;lt;li &amp;lt;%= &quot;id = 'current'&quot; if @page &amp;amp;&amp;amp; @page == page %&amp;gt;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Now we need a &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; rule, in public/stylesheets/learningrails.css, to style the button for the current page:&lt;/p&gt;
&lt;pre&gt;
#navbar #current a {
    background-color: #000; 
}
&lt;/pre&gt;
&lt;p&gt;Now the navigation button for the current page is highlighted.&lt;/p&gt;
&lt;h2&gt;Provide a Link Back to Parent Page&lt;/h2&gt;
&lt;p&gt;When we added subpages in the previous lesson, we didn&amp;#8217;t provide any indication when you&amp;#8217;re on a subpage as to what the parent page is. There&amp;#8217;s several things we might do about this; here&amp;#8217;s two possibilities:&lt;/p&gt;
&lt;p&gt;We could use the subnav div area to show a &amp;#8220;Return to About Us&amp;#8221; link, for example, on subpages of About Us. To do so, replace the code at the top of views/viewer/show.html.erb with the following:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% if !@subpages.empty? %&amp;gt;
  &amp;lt;div id='subnav'&amp;gt;
    &amp;lt;ul&amp;gt;
      &amp;lt;% for page in @subpages %&amp;gt;
        &amp;lt;li&amp;gt;&amp;lt;%= link_to page.navlabel, view_page_path(page.name) %&amp;gt;&amp;lt;/li&amp;gt;
      &amp;lt;% end %&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;% elsif @page.parent %&amp;gt;
  &amp;lt;div id='subnav'&amp;gt;
    &amp;lt;ul&amp;gt;
      &amp;lt;li&amp;gt;&amp;lt;%= link_to &quot;Return to #{@page.parent.navlabel}&quot;,
              view_page_path(@page.parent.name) %&amp;gt;
      &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;If there are subpages, then this code displays the subpage nav. If not, then if there is a parent page, it displays a link back to the parent page. (Note that you&amp;#8217;d want to do something a little different if you had multiple levels of subpages.)&lt;/p&gt;
&lt;p&gt;Now the subpages of About Us show the link back.&lt;/p&gt;
&lt;h2&gt;Add a Little Style&lt;/h2&gt;
&lt;p&gt;The subnav lists are pretty ugly, so let&amp;#8217;s style them a little to make them look like buttons. Add the following to public/styles/learningrails.css:&lt;/p&gt;
&lt;pre&gt;
#subnav {
	width: 160px;
	float: left;
	margin: 0 20px 50px -10px;
}
#subnav ul {
    list-style: none;
    font-weight: bold;
    font-size: 13px;
	margin: 0;
	padding: 0;
}
#subnav ul li {
	background-color: #999;
	border-bottom: 1px solid #333;
	border-top: 1px solid #333;
}
#subnav ul li a {
	padding: 5px 10px;
	display:block;
	color:white;
	text-decoration: none;
}
#subnav ul li a:hover {
    background-color: #333;
    color: #fff;
}
&lt;/pre&gt;
&lt;h2&gt;Retain Parent Button Highlight On Subpages&lt;/h2&gt;
&lt;p&gt;Another way we could indicate the parent page would be to keep its navigation button highlighted. We can do this with a small change to the current page id logic in the application layout, adding a test for the parent of the current page:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;li &amp;lt;%= &quot;id = current&quot; if @page &amp;amp;&amp;amp; (@page == page or @page.parent == page) %&amp;gt;&amp;gt;&amp;lt;%= link_to page.navlabel, view_page_path(page.name) %&amp;gt;&amp;lt;/li&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now when you&amp;#8217;re viewing one of the subpages of the About Us page, the About Us button is highlighted.&lt;/p&gt;
&lt;p&gt;Note that we&amp;#8217;ve let some logic creep back into our application controller here, but it is really presentational logic, so it doesn&amp;#8217;t feel too bad.&lt;/p&gt;
&lt;h2&gt;Set Form Field Focus&lt;/h2&gt;
&lt;p&gt;One last bit of cleanup. On our login page, it&amp;#8217;s annoying that you can&amp;#8217;t just begin typing; neither of the form fields have focus until you click in one of them. We can fix that by adding a little bit of JavaScript to the bottom of views/sessions/new.html.erb:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= javascript_tag &quot;$('login').focus()&quot; %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And now you can start typing as soon as the login page is displayed.&lt;/p&gt;
&lt;h2&gt;Moving On&lt;/h2&gt;
&lt;p&gt;We could go on for several more lessons tuning up our little content management system, but it&amp;#8217;s time to move on. Next lesson, we&amp;#8217;ll create the resources database and use that to drive the Resources page.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:17:00</itunes:duration>
        </item>
        
        <item>
          <title>15: Pages and Subpages</title>
          <description>In this lesson we're adding a hierarchy to our pages. Instead of a single pool of pages with a navigation button for each, we want to have subpages as well, which don't appear in the top navigation bar but are listed in second-level navigation on their parent page.</description>
          <pubDate>Thu, 24 Jul 2008 08:00:54 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79340-pages-and-subpages</guid>
          <link>http://www.buildingwebapps.com/podcasts/79340-pages-and-subpages</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-15.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson we&amp;#8217;re adding a hierarchy to our pages. Instead of a single pool of pages with a navigation button for each, we want to have subpages as well, which don&amp;#8217;t appear in the top navigation bar but are listed in second-level navigation on their parent page.&lt;/p&gt;
&lt;p&gt;Please note that, while we&amp;#8217;ve tried to make these notes complete, they aren&amp;#8217;t the full tutorial; that&amp;#8217;s in the screencast, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 14. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_14.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 14&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_15.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 15&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Model association&lt;/h2&gt;
&lt;p&gt;To associate subpages with their parent pages, we could create a subpage model, and then we could write in the page.rb model:&lt;/p&gt;
&lt;pre&gt;has_many :subpages&lt;/pre&gt;
&lt;p&gt;And in the subpage.rb model:&lt;/p&gt;
&lt;pre&gt;belongs_to :page&lt;/pre&gt;
&lt;p&gt;But to do it this way creates a lot of duplication, since the subpage model would need to behave just like the page model. So we use what&amp;#8217;s called a self-referential association: a page object has many page objects, and a page can have (belong to) a parent. This requires a more complex declaration in the page.rb model, as we&amp;#8217;ll see, but once that&amp;#8217;s done, the self-referential model works the same as it would if subpage was a separate model.&lt;/p&gt;
&lt;h2&gt;Extending the Page table&lt;/h2&gt;
&lt;p&gt;We need to add some fields to the Page model. As with any change to the database structure, we create new migration, with whatever name we&amp;#8217;d like:&lt;/p&gt;
&lt;pre&gt;script/generate migration AddSubpages&lt;/pre&gt;
&lt;p&gt;These three lines in the &amp;#8220;up&amp;#8221; method create the new fields:&lt;/p&gt;
&lt;pre&gt;
def self.up
  add_column :pages, :parent_id, :integer
  add_column :pages, :navlabel, :string
  add_column :pages, :position, :integer
end
&lt;/pre&gt;
&lt;p&gt;And the corresponding three lines in the &amp;#8220;down&amp;#8221; method allow us to set the database back to its prior condition, should we want to roll back the database:&lt;/p&gt;
&lt;pre&gt;
def self.down
  remove_column :pages, :parent_id
  remove_column :pages, :navlabel
  remove_column :pages, :position
end
&lt;/pre&gt;
&lt;p&gt;Once we&amp;#8217;ve created and saved the migration file, we apply the migration:&lt;/p&gt;
&lt;pre&gt;rake db:migrate&lt;/pre&gt;
&lt;h2&gt;Defining the association&lt;/h2&gt;
&lt;p&gt;In the Page class, we need to specify the relationship between parent pages and subpages. We have a field, parent_id, that we created in the previous migration to serve as the foreign key for the association. Since this is a self-referential association, the default naming schemes don&amp;#8217;t apply, and we need to explicitly specify the class name and foreign key field name:&lt;/p&gt;
&lt;pre&gt;has_many :subpages, :class_name =&amp;gt; 'Page', :foreign_key =&amp;gt; 'parent_id'&lt;/pre&gt;
&lt;p&gt;The has_many declaration allows us to then write, typically in our controllers, &lt;code&gt;page.subpages&lt;/code&gt;, to retrieve all the pages that have the current page as their parent.&lt;/p&gt;
&lt;p&gt;Since this is a self-referential association, the &amp;#8220;belongs_to&amp;#8221; side of the relationship also goes in the page model:&lt;/p&gt;
&lt;pre&gt;belongs_to :parent, :class_name =&amp;gt; 'Page', :foreign_key =&amp;gt; 'parent_id'&lt;/pre&gt;
&lt;p&gt;This declaration allows us to then write &lt;code&gt;page.parent&lt;/code&gt; to find the parent page, if there is one.&lt;/p&gt;
&lt;h2&gt;Writing Custom Finders&lt;/h2&gt;
&lt;p&gt;Until now, we&amp;#8217;ve mostly used standard find methods directly in our controllers. It&amp;#8217;s a better design practice, however, to push logic for finding into the model. By writing a custom method to serve as a special kind of find, we can encapsulate more of how the page model works in that single file.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a method to provide the complete set of navigation tabs:&lt;/p&gt;
&lt;pre&gt;
def self.find_main
  Page.find(:all, :conditions =&amp;gt; ['parent_id IS NULL'], :order =&amp;gt; 'position')
end
&lt;/pre&gt;
&lt;p&gt;And here&amp;#8217;s a variant that only shows tabs for site visitors (i.e., no pages that have their &amp;#8220;admin&amp;#8221; attribute set):&lt;/p&gt;
&lt;pre&gt;
def self.find_main_public
  Page.find(:all, :conditions =&amp;gt; [&quot;parent_id IS NULL and admin != ?&quot;, true], :order =&amp;gt; 'position')
end
&lt;/pre&gt;
&lt;h2&gt;Creating main navigation tabs&lt;/h2&gt;
&lt;p&gt;Now we need to update the method that tells the layout what tabs to display. We created this method in an earlier lesson and put it in controllers/application.rb, which is &amp;#8220;mixed in&amp;#8221; to every other controller. Let&amp;#8217;s modify get_pages_for_tabs in application_controller to use the new finds:&lt;/p&gt;
&lt;pre&gt;
def get_pages_for_tabs
  if logged_in?
    @tabs = Page.find_main
  else
    @tabs = Page.find_main_public
  end
end
&lt;/pre&gt;
&lt;h2&gt;Using the navlabel text&lt;/h2&gt;
&lt;p&gt;We have a new attribute in the page model for the navigation button text, so let&amp;#8217;s change the line of code in views/layouts/application.rhtml.erb from:&lt;/p&gt;
&lt;pre&gt;&amp;lt;li&amp;gt;&amp;lt;%= link_to page.title, view_page_path(page.name) %&amp;gt;&amp;lt;/li&amp;gt;&lt;/pre&gt;
&lt;p&gt;to use the new attribute:&lt;/p&gt;
&lt;pre&gt;&amp;lt;li&amp;gt;&amp;lt;%= link_to page.navlabel, view_page_path(page.name) %&amp;gt;&amp;lt;/li&amp;gt;&lt;/pre&gt;
&lt;h2&gt;Providing access to the new attributes&lt;/h2&gt;
&lt;p&gt;We need to update the admin forms for the Page scaffold to let us set and modify the new attributes.
Instead of changing both new and edit views (in views/pages), we create a form partial that is used for both the new and edit views.&lt;/p&gt;
&lt;p&gt;Copy the guts out of either the new or edit view:&lt;/p&gt;
&lt;pre&gt;
	&amp;lt;p&amp;gt;
	  &amp;lt;b&amp;gt;Name&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
	  &amp;lt;%= f.text_field :name %&amp;gt;
	&amp;lt;/p&amp;gt;

	&amp;lt;p&amp;gt;
	  &amp;lt;b&amp;gt;Title&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
	  &amp;lt;%= f.text_field :title %&amp;gt;
	&amp;lt;/p&amp;gt;

	&amp;lt;p&amp;gt;
	  &amp;lt;b&amp;gt;Body&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
	  &amp;lt;%= f.text_area :body %&amp;gt;
	&amp;lt;/p&amp;gt;

	&amp;lt;p&amp;gt;
	  &amp;lt;b&amp;gt;Admin?&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
	  &amp;lt;%= f.check_box :admin %&amp;gt;
	&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Paste this into a new file in views/pages, called &amp;#8220;_form.rhtml.erb&amp;#8221;. The underscore identifies it as a partial.&lt;/p&gt;
&lt;p&gt;Now, in both the new and edit views, all this text can be replaced with:&lt;/p&gt;
&lt;pre&gt;&amp;lt;%= render :partial =&amp;gt; 'form', :locals =&amp;gt; {:f =&amp;gt; f} %&amp;gt;&lt;/pre&gt;
&lt;p&gt;To create the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; pop-up menu for choosing the parent page, we use the collection_select method:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
	&amp;lt;b&amp;gt;Parent Page&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
	&amp;lt;%= f.collection_select :parent_id, Page.find(:all), :id, :title, :include_blank =&amp;gt; true %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Add a field to specify the position:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Position&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.text_field :position, :size =&amp;gt; '3' %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And a field for the nav label:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Nav Label&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.text_field :navlabel %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;h2&gt;Creating subpages&lt;/h2&gt;
&lt;p&gt;Now we can use the page admin interface to set the navlabel and position for each of the existing pages.&lt;/p&gt;
&lt;p&gt;Then let&amp;#8217;s create some subpages. For our example we create two pages, Services and Products, that have About Us as their parent page.&lt;/p&gt;
&lt;p&gt;The main navbar should still show only the main pages, labeled and sorted according to our new navlabel and position attributes.&lt;/p&gt;
&lt;h2&gt;Creating second-level navigation links&lt;/h2&gt;
&lt;p&gt;To create the second-level menu, we need to find the subpages in the viewer controller&amp;#8217;s show method, by adding the following between the two existing lines:&lt;/p&gt;
&lt;pre&gt;@subpages = @page.subpages&lt;/pre&gt;
&lt;p&gt;At the top of views/viewer/show, we&amp;#8217;ll add a simple list of the any subpages:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% unless @subpages.empty? %&amp;gt;
	&amp;lt;div id='subnav'&amp;gt;
		&amp;lt;ul&amp;gt;
			&amp;lt;% for page in @subpages %&amp;gt;
				&amp;lt;li&amp;gt;&amp;lt;%= link_to page.navlabel, view_page_path(page.name) %&amp;gt;&amp;lt;/li&amp;gt;
			&amp;lt;% end %&amp;gt;
		&amp;lt;/ul&amp;gt;
	&amp;lt;/div&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And some minimal styling for this div, to put in the stylesheet:&lt;/p&gt;
&lt;pre&gt;
#subnav {
	width: 200px;
	float: left;
	border-right: 1px solid black;
	margin-right: 20px;
}
&lt;/pre&gt;
&lt;p&gt;The About Us page now shows links for its two subpages, and clicking on those links displays those pages.&lt;/p&gt;
&lt;p&gt;Bugfix: there&amp;#8217;s been a spurious &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag after the navigation links in the application layout, which we&amp;#8217;ve deleted in the code for this lesson.&lt;/p&gt;
&lt;h2&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;We now have a usable two-level page structure. Before putting this into real use, we&amp;#8217;d want better styling for the level-two navigation links, and some indication of what the parent page is when we&amp;#8217;re on a subpage.&lt;/p&gt;
&lt;p&gt;In our next lesson, we&amp;#8217;ll take are of a few of these lingering details, preparing to move on to the contact form and resources page in later lessons.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:26:00</itunes:duration>
        </item>
        
        <item>
          <title>14: Using Textile Markup, plus In-Place Editing with Ajax</title>
          <description>&lt;p&gt;In this lesson we're going to add two features to our content-management system: Textile markup and in-place editing. Both are, in principle, very simple to implement, thanks to a couple of Rails gems and plugins, as well as the Prototype and Scriptaculous JavaScript libraries.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:53 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79339-using-textile-markup-plus-in-place-editing</guid>
          <link>http://www.buildingwebapps.com/podcasts/79339-using-textile-markup-plus-in-place-editing</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-14.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson we&amp;rsquo;re going to add two features to our content-management system: Textile markup and in-place editing. Both are, in principle, very simple to implement, thanks to a couple of Rails gems and plugins, as well as the &lt;a href=&quot;/topic/24332-the-prototype-javascript-library&quot;&gt;Prototype&lt;/a&gt; and &lt;a href=&quot;/topic/24333-the-scriptaculous-javascript-effects-library&quot;&gt;Scriptaculous&lt;/a&gt; JavaScript libraries. The reality turns out to be just as simple as we&amp;rsquo;d hope in the first example, and rather more complex in the second.&lt;/p&gt;
&lt;p&gt;Please note that, while we&amp;rsquo;ve tried to make these notes complete, &lt;em&gt;they aren&amp;rsquo;t the full tutorial;&lt;/em&gt; that&amp;rsquo;s in the &lt;strong&gt;screencast&lt;/strong&gt;, which you can access via the link on the left.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 12. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_13.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 13&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_14.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 14&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Using Textile markup&lt;/h3&gt;
&lt;p&gt;We don&amp;rsquo;t want our administrative users to have to enter &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; code, so we&amp;rsquo;ll use a simple markup language called &lt;a href=&quot;/topic/24246-using-textile-markup-in-ruby-on&quot;&gt;Textile&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s two pieces of Ruby code we use to implement this. The first is the gem RedCloth, which you already have if you&amp;rsquo;re on Leopard. This is the code that translates Textile into &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;. The second is a Rails plugin called &amp;ldquo;acts_as_textiled&amp;rdquo;, which makes it trivially easy to add Textile markup to our content blocks.&lt;/p&gt;
&lt;p&gt;Run &amp;ldquo;gem list&amp;rdquo; to see if you already have RedCloth. If not:&lt;/p&gt;
&lt;pre&gt;
sudo gem install RedCloth&lt;/pre&gt;
&lt;p&gt;To add the plugin, open a terminal window at the root of your application and enter the following command:&lt;/p&gt;
&lt;pre&gt;
script/plugin install svn://errtheblog.com/svn/plugins/acts_as_textiled&lt;/pre&gt;
&lt;p&gt;Add to the Page model:&lt;/p&gt;
&lt;pre&gt;
acts_as_textiled :body&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it. This plugin is smart enough to automatically display the Textile markup source when you&amp;rsquo;re displaying the body in a form field, as we are in the admin pages, but to render it into &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; anywhere else you use the body.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll need to stop and restart the server before the plugin will function.&lt;/p&gt;
&lt;p&gt;Now you can edit any of the pages in the content management system, such as the admin page, to convert the markup to Textile. Note that the page list view shows the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; created by RedCloth &amp;mdash; that&amp;rsquo;s because the acts_as_textiled plugin automatically renders the Textile content into &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; anyplace except in a form field.&lt;/p&gt;
&lt;h2&gt;In-place editing&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/topic/24251-implementing-an-in-place-editor-in-ruby&quot;&gt;In-place editing&lt;/a&gt; is a common feature of modern web applications, and there&amp;rsquo;s good support for it built in to Prototype. There&amp;rsquo;s also a Rails helper that wraps the Prototype method so we don&amp;rsquo;t even have to touch the JavaScript code.&lt;/p&gt;
&lt;p&gt;In Rails 1.2.x, the in-place editor helper was part of the framework. In Rails 2.0, however, it was split out as a plugin, in theory so it could be separately maintained. Unfortunately, it has not been maintained (as of this writing in early May 2008), so not only do we need to install the plug-in, we&amp;rsquo;re going to have to seek out and install a couple of patches before we have everything working.&lt;/p&gt;
&lt;h3&gt;Installing the plugin&lt;/h3&gt;
&lt;p&gt;Install the in_place_editing plugin by entering the following in a console at the root of your application:&lt;/p&gt;
&lt;pre&gt;
script/plugin install http://svn.rubyonrails.org/rails/plugins/in_place_editing&lt;/pre&gt;
&lt;h3&gt;Modifying our code to use the plugin&lt;/h3&gt;
&lt;p&gt;The readme file provides basic installation instructions. We need to make two small changes to our code. In the file views/viewer/show.html.erb, replace the one line of text that is now in that file with the following:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= in_place_editor_field :page, 'body' %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Then add this line to the top of the class in controllers/viewer_controller.rb:&lt;/p&gt;
&lt;pre&gt;
in_place_edit_for :page, :body&lt;/pre&gt;
&lt;p&gt;And finally, we need to tell our application to load the JavaScript libraries. Add to the head section in views/layouts/application.html.erb:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= javascript_include_tag :defaults %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Now restart the server, since we&amp;rsquo;ve installed a plugin, and everything should work as before. But now, when you click on any page text, a little edit box comes up!&lt;/p&gt;
&lt;p&gt;Try editing the text and click OK. Unfortunately, the save fails. To get a hint of what&amp;rsquo;s happening, view the page using Firefox with &lt;a href=&quot;/topic/24276-debugging-ruby-on-rails-applications-using&quot;&gt;Firebug&lt;/a&gt; installed, and take a look at the console when you click the OK button. Scroll through the response and you&amp;rsquo;ll see that there&amp;rsquo;s an issue with the authenticity token.&lt;/p&gt;
&lt;h3&gt;The &lt;span class=&quot;caps&quot;&gt;CSRF&lt;/span&gt; protection bug&lt;/h3&gt;
&lt;p&gt;The authenticity token is a feature added to Rails 2.0 to improve protection against cross-site request forgery (&lt;span class=&quot;caps&quot;&gt;CSRF&lt;/span&gt;) attempts. Unfortunately, the team didn&amp;rsquo;t update the in-place editor plugin correspondingly, so this security feature trips it up.&lt;/p&gt;
&lt;p&gt;Try a google search on &amp;ldquo;in place editing &lt;span class=&quot;caps&quot;&gt;CSRF&lt;/span&gt;&amp;rdquo;. The first result is a ticket in the Rails Trac titled &amp;ldquo;in_place_editing plugin does not work with &lt;span class=&quot;caps&quot;&gt;CSRF&lt;/span&gt; protection&amp;rdquo;! Look at the patch suggested; focus on the forgery protection, grab the four lines of code and paste them into vendor/plugins/in_place_editing/lib/in_place_macros_helper.rb (see the screencast for details).&lt;/p&gt;
&lt;p&gt;After adding these lines restart the server, reload the web page, click on some text to edit it, and click OK to save. Now it works!&lt;/p&gt;
&lt;p&gt;A minor correction to the screencast discussion of the JavaScript code: in the audio, we referred to Ajax.InPlaceEditor as a Scriptaculous method. In fact, the Ajax object is part of the Prototype library, and the InPlaceEditor method is added by Scriptaculous.&lt;/p&gt;
&lt;h3&gt;Providing a larger text entry area&lt;/h3&gt;
&lt;p&gt;Next we want to provide a larger text entry field. Add the rows and columns options to the helper invocation:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= in_place_editor_field :page, 'body', {}, 
{:rows =&amp;gt; 20, :cols =&amp;gt; 80} %&amp;gt;&lt;/pre&gt;
&lt;p&gt;Refresh the browser, click on the text, and you should now see a decent size text area.&lt;/p&gt;
&lt;h3&gt;Displaying Textile source instead of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Next problem: It is displaying the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; markup, not the Textile source.&lt;/p&gt;
&lt;p&gt;By default, the in_place_editor_field helper pulls the text to be edited from the page itself, not from the server, so naturally it sees the rendered &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;. To fix this, we need to set an option to tell it to fetch the source from the server, and then we need to create the controller code to respond to that request.&lt;/p&gt;
&lt;p&gt;The option we need is called load_text_url. With this added to the helper invocation, we now have the following code in the view file:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= in_place_editor_field :page, 'body', {}, 
{:rows =&amp;gt; 20, :cols =&amp;gt; 80, 
 :load_text_url =&amp;gt; {:controller =&amp;gt; 'viewer', :action =&amp;gt; 'get_unformatted_text', :id =&amp;gt; @page.id}} %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This tells the Scriptaculous method to make an XMLHttp request (the workhorse of Ajax applications) to retrieve the unformatted text.&lt;/p&gt;
&lt;p&gt;Now we need to add the get_unformatted_text action to viewer_controller.rb:&lt;/p&gt;
&lt;pre&gt;
def get_unformatted_text
  @page = Page.find(params[:id])
  render :text =&amp;gt; @page.body(:source)
end
&lt;/pre&gt;
&lt;p&gt;Take a look at the acts_as_textile readme to find the (:source) option that enables us to access the markup source, rather than the rendered &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Reload the page, and it now displays Textile, just as we wanted.&lt;/p&gt;
&lt;h3&gt;Do we want visitors to be able to edit the site?&lt;/h3&gt;
&lt;p&gt;One small problem &amp;mdash; unless our goal is to provide a wiki, we probably don&amp;rsquo;t want any visitor to be able to edit our site&amp;rsquo;s contents. So we need to use the in-place editor only if someone is logged in. Simple enough, just change the view code to:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% if logged_in? %&amp;gt;

  &amp;lt;%= in_place_editor_field :page, 'body', {}, 
  {:rows =&amp;gt; 20, :cols =&amp;gt; 80, 
   :load_text_url =&amp;gt; {:controller =&amp;gt; 'viewer', :action =&amp;gt; 'get_unformatted_text', :id =&amp;gt; @page.id}} %&amp;gt;

&amp;lt;% else %&amp;gt;

  &amp;lt;%= @page.body %&amp;gt;

&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Refresh the browser, and now in-place edit is available only to logged-in users.&lt;/p&gt;
&lt;h3&gt;Adding an external control&lt;/h3&gt;
&lt;p&gt;One more problem: in admin mode, we can&amp;rsquo;t access links on the page, because clicking anywhere in the page text takes us into edit mode. So our admin dashboard is now useless. This would also be a problem if any of the regular pages had links and we wanted to be be able to exercise them in admin mode.&lt;/p&gt;
&lt;p&gt;Looking back at the in-place editor helper file, we see an option for externalControl, so let&amp;rsquo;s try that. Add one more option to our in_place_editor_field invocation:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= in_place_editor_field :page, 'body', {}, 
{:rows =&amp;gt; 20, :cols =&amp;gt; 80, :external_control =&amp;gt; 'edit', 
 :load_text_url =&amp;gt; {:controller =&amp;gt; 'viewer', :action =&amp;gt; 'get_unformatted_text', :id =&amp;gt; @page.id}
} %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And create an edit link at the top of the page to trigger this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;a href='#' id='edit'&amp;gt;Edit This Page&amp;lt;/a&amp;gt;&lt;/pre&gt;
&lt;p&gt;Refresh the page, and give the edit link a try. It works! Unfortunately, clicking on the text also triggers the edit control, so we need to somehow prevent that.&lt;/p&gt;
&lt;h3&gt;Making &lt;strong&gt;only&lt;/strong&gt; the external control activate the edit mode&lt;/h3&gt;
&lt;p&gt;What we need is a way to have only the external control activate the in-place editor. Searching the web, we find confusing and contradictory results. But in the excellent book &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1934356018/buildicom-20&quot;&gt;Prototype and Scriptaculous&lt;/a&gt;, we read up on the in-place editor options, and find a reference to an option &lt;code&gt;externalControlOnly&lt;/code&gt;. Alas, the Rails helper doesn&amp;rsquo;t support this, so it&amp;rsquo;s back to patching the code.&lt;/p&gt;
&lt;p&gt;In the helper, we find the line:&lt;/p&gt;
&lt;pre&gt;
js_options['externalControl'] = &amp;quot;'#{options[:external_control]}'&amp;quot; if options[:external_control]&lt;/pre&gt;
&lt;p&gt;So let&amp;rsquo;s try duplicating this line in the helper, changing &lt;code&gt;externalControl&lt;/code&gt; to &lt;code&gt;externalControlOnly&lt;/code&gt; in the duplicate line, and then we change our view code to set this option to true:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= in_place_editor_field :page, 'body', {}, 
{:rows =&amp;gt; 20, :cols =&amp;gt; 80, :external_control =&amp;gt; 'edit', :external_control_only =&amp;gt; true,
 :load_text_url =&amp;gt; {:controller =&amp;gt; 'viewer', :action =&amp;gt; 'get_unformatted_text', :id =&amp;gt; @page.id}
} %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;And presto, now it behaves as we want!&lt;/p&gt;
&lt;p&gt;Life in the open-source world is sometimes not as clean as we&amp;rsquo;d like it to be. Someone will no doubt update the in-place editor plugin soon, which will cut out more than half the effort of this exercise.&lt;/p&gt;
&lt;h2&gt;Coming Up&lt;/h2&gt;
&lt;p&gt;In our next lesson, we&amp;rsquo;re going to improve the navigation model for our content management system generated pages, so we can have sub-pages as well as main pages, and so the navigation button text can be different from the page title.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:40:00</itunes:duration>
        </item>
        
        <item>
          <title>13: Admin Pages</title>
          <description>In this lesson, we implement the actual administrative dashboard using improvements we make to the mini-CMS we are building. We finish up with an improvement to our navigation code so we can build the tabbed interface more dynamically.</description>
          <pubDate>Thu, 24 Jul 2008 08:00:53 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79338-admin-pages</guid>
          <link>http://www.buildingwebapps.com/podcasts/79338-admin-pages</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-13.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we implement the actual administrative dashboard using improvements we make to the mini-&lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; we are building. We finish up with an improvement to our navigation code so we can build the tabbed interface more dynamically.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 12. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_12.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 12&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_13.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 13&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Admin Pages&lt;/h2&gt;
&lt;p&gt;Of course, it is tiresome to keep typing the URLs manually to get to our administrative pages. Let&amp;#8217;s create an admin dashboard page that connects us to these sub-pages. Let&amp;#8217;s also make the admin page easy to reach when we are appropriately logged in.&lt;/p&gt;
&lt;h2&gt;Make the Admin page attribute&lt;/h2&gt;
&lt;p&gt;If we are going to use our baby-&lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; to implement this page, what is missing? We need to know when a page is an admin type page so we can protect it properly.&lt;/p&gt;
&lt;p&gt;Make a migration to add an admin attribute to pages, and then set some default values in the migration to keep things tidy.&lt;/p&gt;
&lt;pre&gt;
class AddAdminPageAttribute &amp;lt; ActiveRecord::Migration
  def self.up
    add_column :pages, :admin, :boolean
    
    @pages = Page.find(:all)
    @pages.each do |page|
      page.update_attribute(:admin, false)
    end
    
  end

  def self.down
    remove_column :pages, :admin
  end
end
&lt;/pre&gt;
&lt;p&gt;Now, we need to update the Page Admin html so we can see/edit the new admin attribute:&lt;/p&gt;
&lt;p&gt;First, index.html.erb gets a couple of new table entries:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;h1&amp;gt;Listing pages&amp;lt;/h1&amp;gt;

&amp;lt;table&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;th&amp;gt;Name&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Title&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Body&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Admin?&amp;lt;/th&amp;gt;
  &amp;lt;/tr&amp;gt;

&amp;lt;% for page in @pages %&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=h page.name %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=h page.title %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%=h page.body %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= page.admin? ? &quot;TRUE&quot; : &quot;FALSE&quot; %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to 'Show', page %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to 'Edit', edit_page_path(page) %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to 'Destroy', page, :confirm =&amp;gt; 'Are you sure?', :method =&amp;gt; :delete %&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;% end %&amp;gt;
&amp;lt;/table&amp;gt;

&amp;lt;br /&amp;gt;

&amp;lt;%= link_to 'New page', new_page_path %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Then add a snippet to show.html.erb to see the Admin value:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
   &amp;lt;b&amp;gt;Admin?&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
   &amp;lt;%= @page.admin? ? &quot;TRUE&quot; : &quot;FALSE&quot; %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Update both edit.html.erb and new.html.erb with a snippet to use a check box for the state of the admin attribute (put this in before the submit):&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Admin?&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;
  &amp;lt;%= f.check_box :admin %&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We should be all set. Check it out and create a page with the admin bit set. Can you see it when you are logged in? What about when you aren&amp;#8217;t? Oops!&lt;/p&gt;
&lt;h2&gt;Update the viewer controller to handle special pages&lt;/h2&gt;
&lt;p&gt;Of course, we don&amp;#8217;t filter in anyway for admin pages, so anyone can see a page marked with the Admin bit. Let&amp;#8217;s fix that by protecting admin viewable pages by updating the viewer controller:&lt;/p&gt;
&lt;pre&gt;
def show
  @page = Page.find_by_name(params[:name])
  login_required if @page.admin?
end
&lt;/pre&gt;
&lt;p&gt;We are leveraging the login_required function provided to us by the restful_authentication plugin. If the requested page has the admin value set to true, we&amp;#8217;ll check to see if the user is logged in with login_required.&lt;/p&gt;
&lt;h2&gt;Add an admin dashboard page in the DB&lt;/h2&gt;
&lt;p&gt;Finally, we can create a page using the mini-CMS&amp;#8217; Page Admin. Make one now and we&amp;#8217;ll call it &amp;#8220;admin&amp;#8221;. Make the page contents as follows:&lt;/p&gt;
&lt;pre&gt;
	&amp;lt;a href=&quot;/pages&quot;&amp;gt;&quot;Page Admin&quot;&amp;lt;/a&amp;gt;
	&amp;lt;br&amp;gt;
	&amp;lt;a href=&quot;/users&quot;&amp;gt;&quot;User Admin&quot;&amp;lt;/a&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Test it. Check it logged in and logged out. It works!&lt;/p&gt;
&lt;h2&gt;Make layout dynamic&lt;/h2&gt;
&lt;p&gt;It is getting really tiresome to keep updating our simple navigator, since we need to access the admin pages regularly, let&amp;#8217;s take this opportunity to make a new tab appear for each page automatically.&lt;/p&gt;
&lt;p&gt;Update the application layout to support rendering tabs dynamically. Here is the new navbar div:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;div id='navbar'&amp;gt;
	&amp;lt;ul&amp;gt;
		&amp;lt;% @tabs.each do |page| -%&amp;gt;
			&amp;lt;li&amp;gt;&amp;lt;%= link_to page.title, view_page_path(page.name) %&amp;gt;&amp;lt;/li&amp;gt;
		&amp;lt;% end -%&amp;gt;
		&amp;lt;li&amp;gt;&amp;lt;% if logged_in? %&amp;gt;
					&amp;lt;%= link_to &quot;Log Out&quot;, logout_path %&amp;gt;
				&amp;lt;% else %&amp;gt;
					&amp;lt;%= link_to &quot;Log In&quot;, login_path %&amp;gt;
				&amp;lt;% end %&amp;gt;
		&amp;lt;/li&amp;gt;
	&amp;lt;/ul&amp;gt;
&amp;lt;div&amp;gt;
&lt;/pre&gt;
&lt;p&gt;We need to add a before_filter to application.rb to load up pages into that @tabs variable:&lt;/p&gt;
&lt;pre&gt;
before_filter :get_pages_for_tabs

def get_pages_for_tabs
  if logged_in?
    @tabs = Page.find(:all)
  else
    @tabs = Page.find(:all, :conditions =&amp;gt; [&quot;admin != ?&quot;, true])
  end
end
&lt;/pre&gt;
&lt;p&gt;This won&amp;#8217;t deal well with lots of pages, so in the future we&amp;#8217;ll improve this solution with the notion of page groups, sub-navigation, and other tricks.&lt;/p&gt;
&lt;h2&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Try out the new navigation at localhost:3000. You may want to tweak the titles of the pages to make the tabs look better. We are reusing the same data as is used for the page titles in the title bar of the browser. A better solution over time may be to add a separate attribute so we can keep &lt;span class=&quot;caps&quot;&gt;SEO&lt;/span&gt; friendly titles.&lt;/p&gt;
&lt;p&gt;We finally have support for &amp;#8220;administrative&amp;#8221; pages in our simple &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;, so we can create the dashboard using our own technology!&lt;/p&gt;
&lt;h2&gt;Coming up&lt;/h2&gt;
&lt;p&gt;Next time, we&amp;#8217;ll add the ability to use Textile markup in our &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt; pages (via a plugin) and start playing with &lt;span class=&quot;caps&quot;&gt;AJAX&lt;/span&gt; to make the UI a little easier to use.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:21:00</itunes:duration>
        </item>
        
        <item>
          <title>12: User Management</title>
          <description>In this lesson, we work towards implementing an administrative dashboard by expanding the user controller generated by restful_authentication to give us full abilities to manage user data.</description>
          <pubDate>Thu, 24 Jul 2008 08:00:53 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79337-user-management</guid>
          <link>http://www.buildingwebapps.com/podcasts/79337-user-management</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-12.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we work towards implementing an administrative dashboard by expanding the user controller generated by restful_authentication to give us full abilities to manage user data.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 11. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_11.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 11&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_12.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Clean up session create with a notice if user incorrectly enters credentials&lt;/h2&gt;
&lt;p&gt;Before diving in to the core work in this lesson, let&amp;#8217;s continue to do some small changes to improve the experience our application provides. One pain point occurs when you try to log in and type the wrong credentials.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s put a notice in the create failure path, before re-rendering the edit dialog&lt;/p&gt;
&lt;pre&gt;
flash[:notice] = &quot;Try entering your credentials again&quot;
&lt;/pre&gt;
&lt;h2&gt;Create a default admin user (migration)&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s use a migration called a &amp;#8220;data migration&amp;#8221;. It doesn&amp;#8217;t change the structure of the database. Instead it loads data, in this case, a default user account.&lt;/p&gt;
&lt;pre&gt;
script/generate migration AddDefaultUser
&lt;/pre&gt;

&lt;pre&gt;
self.up
  if !User.find_by_login('admin')
    User.create(:login =&amp;gt; 'admin', :email =&amp;gt; 'admin@sample.com', 
                :password =&amp;gt; 'changeme', :password_confirmation =&amp;gt; 'changeme')
  end
end
&lt;/pre&gt;
&lt;p&gt;We aren&amp;#8217;t creating a down migration in this case. We don&amp;#8217;t know if we were the ones who created this account for sure, so we won&amp;#8217;t delete it when this migration is run in reverse.&lt;/p&gt;
&lt;p&gt;Run the migration in the terminal:&lt;/p&gt;
&lt;pre&gt;
rake db:migrate
&lt;/pre&gt;
&lt;h2&gt;Add a user list page&lt;/h2&gt;
&lt;p&gt;The &amp;#8220;restful_authentication&amp;#8221; plugin&amp;#8217;s generate creates a RESTful controller, but it only creates the new and create actions. We need to fill the rest out and can use the Pages controller as a model.&lt;/p&gt;
&lt;p&gt;Add an index action to users controller.&lt;/p&gt;
&lt;pre&gt;
def index
  @users = User.find(:all)
end
&lt;/pre&gt;
&lt;p&gt;Create users/index view in the users directory (index.html.erb). Also prepare by adding links to show, edit, and delete. Put a link at the bottom to create new users.&lt;/p&gt;
&lt;pre&gt;
&amp;lt;h1&amp;gt;Listing Users&amp;lt;/h1&amp;gt;

&amp;lt;table&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;th&amp;gt;Login&amp;lt;/th&amp;gt;
    &amp;lt;th&amp;gt;Email&amp;lt;/th&amp;gt;
  &amp;lt;/tr&amp;gt;

  &amp;lt;% for user in @users %&amp;gt;
    &amp;lt;tr&amp;gt;
      &amp;lt;td&amp;gt;&amp;lt;%=h user.login %&amp;gt;&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;&amp;lt;%=h user.email %&amp;gt;&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;&amp;lt;%= link_to 'Show', user %&amp;gt;&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;&amp;lt;%= link_to 'Edit', edit_user_path(user) %&amp;gt;&amp;lt;/td&amp;gt;
      &amp;lt;td&amp;gt;&amp;lt;%= link_to 'Delete', user, 
          :confirm =&amp;gt; &quot;Are you sure you want to delete '#{user.login}'?&quot;,
          :method =&amp;gt; :delete %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;/tr&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;/table&amp;gt;

&amp;lt;br /&amp;gt;

&amp;lt;%= link_to 'New User', new_user_path %&amp;gt;

&lt;/pre&gt;
&lt;p&gt;Take a look&amp;#8230;seems to work, but we need to fill out the rest of the actions and the appropriate views.&lt;/p&gt;
&lt;h2&gt;Add show user page&lt;/h2&gt;
&lt;p&gt;Add a show action to the users controller.&lt;/p&gt;
&lt;pre&gt;
def show
  @user = User.find(params[:id])
end
&lt;/pre&gt;
&lt;p&gt;Add the show view (show.html.erb).&lt;/p&gt;
&lt;pre&gt;
&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Login:&amp;lt;/b&amp;gt;
  &amp;lt;%=h @user.login %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Email:&amp;lt;/b&amp;gt;
  &amp;lt;%=h @user.email %&amp;gt;
&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;
  &amp;lt;b&amp;gt;Password:&amp;lt;/b&amp;gt;
  [secret]
&amp;lt;/p&amp;gt;


&amp;lt;%= link_to 'Edit', edit_user_path(@user) %&amp;gt; |
&amp;lt;%= link_to 'Back', users_path %&amp;gt;
&lt;/pre&gt;
&lt;h2&gt;Add a user delete function&lt;/h2&gt;
&lt;p&gt;Add destroy action to users controller.&lt;/p&gt;
&lt;pre&gt;
def destroy
  @user = User.find(params[:id])
  @user.destroy

  redirect_to(users_url)
end
&lt;/pre&gt;
&lt;p&gt;Note the link is already in the index view and uses a javascript alert dialog to confirm the deletion with the user.&lt;/p&gt;
&lt;h2&gt;Add a edit/Update user functions&lt;/h2&gt;
&lt;p&gt;Add edit and update actions to the users controller. New/create and edit/update always work in pairs in the RESTful implementation in Rails 2.&lt;/p&gt;
&lt;pre&gt;
def edit
  @user = User.find(params[:id])
end
  
def update
  @user = User.find(params[:id])

  if @user.update_attributes(params[:user])
    flash[:notice] = 'User was successfully updated.'
    redirect_to(user_path(@user))
  else
    render :action =&amp;gt; 'edit'
  end
end
&lt;/pre&gt;
&lt;p&gt;Create a corresponding view for edit. It is nearly identical to the new view, but we changed the form_for line to take advantage of Rails behavior. By specifying the object on the form_for line, Rails automatically generates the proper &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; to our update action and submits the form using the &amp;#8220;&lt;span class=&quot;caps&quot;&gt;PUT&lt;/span&gt;&amp;#8221; &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; method.&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= error_messages_for :user %&amp;gt;

&amp;lt;% form_for @user do |f| -%&amp;gt;
  &amp;lt;p&amp;gt;&amp;lt;label for=&quot;login&quot;&amp;gt;Login&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;
  &amp;lt;%= f.text_field :login %&amp;gt;&amp;lt;/p&amp;gt;

  &amp;lt;p&amp;gt;&amp;lt;label for=&quot;email&quot;&amp;gt;Email&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;
  &amp;lt;%= f.text_field :email %&amp;gt;&amp;lt;/p&amp;gt;

  &amp;lt;p&amp;gt;&amp;lt;label for=&quot;password&quot;&amp;gt;Password&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;
  &amp;lt;%= f.password_field :password %&amp;gt;&amp;lt;/p&amp;gt;

  &amp;lt;p&amp;gt;&amp;lt;label for=&quot;password_confirmation&quot;&amp;gt;Confirm Password&amp;lt;/label&amp;gt;&amp;lt;br/&amp;gt;
  &amp;lt;%= f.password_field :password_confirmation %&amp;gt;&amp;lt;/p&amp;gt;

  &amp;lt;p&amp;gt;&amp;lt;%= submit_tag 'Update' %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Now test all of the pages together. They work!&lt;/p&gt;
&lt;h2&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Of course, it is tiresome to keep typing the URLs manually to get to these pages. You can navigate directly to the users controller at localhost:3000/users, but it would be a lot easier to have a dashboard that collects all of these links in one easy to access place. Even better, the dashboard should be available from our navigation tags when appropriately logged in.&lt;/p&gt;
&lt;h2&gt;Coming up&lt;/h2&gt;
&lt;p&gt;In our next lesson, we&amp;#8217;ll add support for &amp;#8220;administrative&amp;#8221; pages in our simple &lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;, so we can create the dashboard using our own technology. We&amp;#8217;ll also tweak the tab navigation so it automatically discovers and displays links without us needing to edit code.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:33:00</itunes:duration>
        </item>
        
        <item>
          <title>11: Adding User Authentication</title>
          <description>In this lesson, we add user authentication so only logged-in users can access the page controller and modify the contents of the site.</description>
          <pubDate>Thu, 24 Jul 2008 08:00:52 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79336-adding-user-authentication</guid>
          <link>http://www.buildingwebapps.com/podcasts/79336-adding-user-authentication</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-11.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Goals&lt;/h2&gt;
&lt;p&gt;In this lesson, we add user authentication so only logged-in users can access the page controller and modify the contents of the site.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 10. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_10.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 10&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/learningrails_11.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 11&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Page title cleanup&lt;/h2&gt;
&lt;p&gt;First, we need to take care of a little problem we created for ourselves with the way we handled the page title metadata in the previous lesson.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re going to add a couple more admin controllers in this lesson, and with the approach used in the previous lesson, we&amp;#8217;d need to specifically set the @pagetitle instance variable in each of those controllers. For now, we&amp;#8217;re going to replace the existing setting of the title tag in the application layout with the following:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;title&amp;gt;&amp;lt;%= @pagetitle || (@page &amp;amp;&amp;amp; @page.title) || &quot;Learning Rails Sample Application&quot; %&amp;gt;&amp;lt;/title&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This line sets the pagetitle in one of three ways:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;If there is an instance variable @pagetitle, use that&lt;/li&gt;
	&lt;li&gt;If not, then use @page.title, if there is a @page object&lt;/li&gt;
	&lt;li&gt;If there&amp;#8217;s neither a @pagetitle nor a @page object, use the fixed string&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a little messy, and in a later lesson we&amp;#8217;ll fix it in a more elegant way.&lt;/p&gt;
&lt;h2&gt;Install plugin&lt;/h2&gt;
&lt;p&gt;The plugin we&amp;#8217;re going to use is called restful_authentication. You can find plugins by searching on Google or on various Rails plugin directory sites. One good site is &lt;a href=&quot;http://www.agilewebdevelopment.com&quot;&gt;AgileWebDevelopment&lt;/a&gt;. From this site, you can get the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; for the repository where the plugin code is located.&lt;/p&gt;
&lt;p&gt;To install restful_authentication, enter the following line in a terminal at the root of your application:&lt;/p&gt;
&lt;pre&gt;
script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
&lt;/pre&gt;
&lt;p&gt;You can view the readme in vendor/plugins/restful_authentication to learn more about it.&lt;/p&gt;
&lt;h2&gt;Set up the plugin&lt;/h2&gt;
&lt;p&gt;This plugin provides a generator of its own to help us set things up, so let&amp;#8217;s run it:&lt;/p&gt;
&lt;pre&gt;
script/generate authenticated user sessions
&lt;/pre&gt;
&lt;p&gt;In this command, &amp;#8220;authenticated&amp;#8221; is the name of the generator; &amp;#8220;user&amp;#8221; is the name of the model that will store user names and passwords; and &amp;#8220;sessions&amp;#8221; is the name of the controller that will manage user sessions.&lt;/p&gt;
&lt;p&gt;This generator creates a migration for us, but we need to run the migration:&lt;/p&gt;
&lt;pre&gt;
rake db:migrate
&lt;/pre&gt;
&lt;p&gt;Finally, to make the methods provided by this plugin available in your controllers, you need to add the following line to the file controllers/application.rb:&lt;/p&gt;
&lt;pre&gt;include AuthenticatedSystem&lt;/pre&gt;
&lt;p&gt;The application controller is &amp;#8220;mixed in&amp;#8221; to all other controllers, so any code you put here is available to all controllers. So by putting the &amp;#8220;include&amp;#8221; statement for the authenticated system here, you&amp;#8217;re effectively adding that code to every controller.&lt;/p&gt;
&lt;h2&gt;Creating a user&lt;/h2&gt;
&lt;p&gt;Before we can have log-in, we need to have users, so let&amp;#8217;s add some user management.&lt;/p&gt;
&lt;p&gt;The authenticated generator we ran in the previous section gave us a users controller and a view for creating users, so browse to //localhost:3000/users/new and create a login for yourself.&lt;/p&gt;
&lt;p&gt;The generator also created a sessions controller, which is what handles the actual log in and log out operations. Logging in is creating a new session, and logging out is destroying a session. It&amp;#8217;s convenient to have shortcuts we can use to refer to these, so let&amp;#8217;s add some named routes. Add the following lines to the top of the config/routes.rb file:&lt;/p&gt;
&lt;pre&gt;
map.logout '/logout', :controller =&amp;gt; 'sessions', :action =&amp;gt; 'destroy'
map.login '/login', :controller =&amp;gt; 'sessions', :action =&amp;gt; 'new'
&lt;/pre&gt;
&lt;p&gt;This gives us two things. The text &amp;#8216;/logout&amp;#8217; and &amp;#8216;/login&amp;#8217; makes those simple URLs work. And the words after the &amp;#8220;map.&amp;#8221; provide shortcuts we can refer to anywhere in our code when we want to generate that &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, using either login_path, for example, to generate a relative &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, or login_url, to generate a full, absolute &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s add a log-in button to the navigation bar. Open views/layouts/application.html.erb, and add this code to the end of the list of links that creates the nav bar:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;li&amp;gt;
   &amp;lt;% if logged_in? %&amp;gt;
      &amp;lt;%= link_to &quot;Log Out&quot;, logout_path %&amp;gt;
   &amp;lt;% else %&amp;gt;
      &amp;lt;%= link_to &quot;Log In&quot;, login_path %&amp;gt;
   &amp;lt;% end %&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The restful_authentication plugin provides us with a &amp;#8220;logged_in?&amp;#8221; method that we can use to determine if any user is logged in. If someone is logged in, then we display a log out link; if not, we display a log in link.&lt;/p&gt;
&lt;h2&gt;Using authentication to protect the admin pages&lt;/h2&gt;
&lt;p&gt;Now we have our entire authentication system in place, but we haven&amp;#8217;t actually used it to require login for any pages. We need to invoke the authentication feature for the pages for which we want to require log-in.&lt;/p&gt;
&lt;p&gt;Open the file controllers/pages_controller.rb, and add the following line:&lt;/p&gt;
&lt;pre&gt;
before_filter :login_required
&lt;/pre&gt;
&lt;p&gt;&amp;#8220;login_required&amp;#8221; is another method provided for us by the restful_authentication plugin. The before_filter causes this method to be executed before any action in the controller.&lt;/p&gt;
&lt;p&gt;Now do the same for users_controller.&lt;/p&gt;
&lt;h2&gt;Take care of page titles&lt;/h2&gt;
&lt;p&gt;Just as in the previous lesson, we need to set the @pagetitle instance variable in the user and session controllers, since these pages aren&amp;#8217;t generated from page objects.&lt;/p&gt;
&lt;h2&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Try accessing localhost:3000/pages, and you should be presented with a login screen. Log in with the credentials created in the previous step, and you should see the Log In button in the nav bar change to Log Out.&lt;/p&gt;
&lt;p&gt;Try creating a new user by accessing localhost:3000/users/new. You shouldn&amp;#8217;t be able to create a new user without being logged in. (If you didn&amp;#8217;t create a user before adding the login requirement to the users controller, you can comment that line out temporarily.)&lt;/p&gt;
&lt;h2&gt;Coming up&lt;/h2&gt;
&lt;p&gt;In our next lesson, we&amp;#8217;ll make a variety of small enhancements to add some polish and additional capabilities to our content management system.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:23:00</itunes:duration>
        </item>
        
        <item>
          <title>10: Putting the Page Contents into the Database</title>
          <description>&lt;p&gt;In this lesson, the second screencast in the Learning Rails course, we create our first database table and Rails model. In the previous lesson, we created static pages, with all the contents in the view files. In this lesson, we put the page contents into the database, so we can provide an administrative interface that allows non-technical users to modify the pages.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:52 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79335-putting-the-page-contents-into-the</guid>
          <link>http://www.buildingwebapps.com/podcasts/79335-putting-the-page-contents-into-the</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-10.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>In this lesson, we create our first database table and Rails model.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In the previous lesson, we created static pages, with all the contents in the view files. The problem with this approach is that to change any text, you must modify the code.&lt;/p&gt;
&lt;p&gt;A better approach is to put the page contents into the database, so we can then provide an administrative interface that allows non-technical users to modify the pages. In this lesson, we do just that, creating the core of a simple content management system (&lt;span class=&quot;caps&quot;&gt;CMS&lt;/span&gt;).&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;We begin with the code with which we ended Lesson 9. These zip files contain the beginning and ending states of the code:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_9.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 9&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/learningrails_10.zip&quot;&gt;Learning Rails example app code as of the end of Lesson 10&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a href=&quot;/podcasts/79333-setting-up-your-development-environment/&quot;&gt;Lesson 8&lt;/a&gt; for pointers on setting up your development environment.&lt;/p&gt;
&lt;p&gt;In Lesson 8, we explained how to set up the MySQL database. In this lesson, we use SQLite, which is a little easier to get going (if you&amp;rsquo;re using Leopard, you don&amp;rsquo;t have to do anything to use SQLite). If you want to use MySQL instead, you just need to change the settings in database.yml. In particular, in the development section, replace the code in the sample application with something like this:&lt;/p&gt;
&lt;pre&gt;
  adapter: mysql
  database: learning_rails
  username: root (or other user name)
  password: secretword (whatever your password is; leave blank if none)
  host: localhost
&lt;/pre&gt;
&lt;p&gt;You&amp;rsquo;ll also need to create the database, using the mysql command-line interface or one of the &lt;span class=&quot;caps&quot;&gt;GUI&lt;/span&gt; interfaces (we&amp;rsquo;re partial to &lt;a href=&quot;http://navicat.com&quot;&gt;Navicat&lt;/a&gt;). With sqlite, this is done for you automatically.&lt;/p&gt;
&lt;h2&gt;Lesson Outline&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the coding steps we take in this lesson. Watch the screencast for details and explanations (see link at the top of the left column).&lt;/p&gt;
&lt;h3&gt;1. Delete the four static views in views/pages&lt;/h3&gt;
&lt;h3&gt;2. Create a scaffold for the new Page model with this command:&lt;/h3&gt;
&lt;pre&gt;
script/generate scaffold page name:string title:string body:text&lt;/pre&gt;
&lt;h3&gt;3. Run the migration:&lt;/h3&gt;
&lt;pre&gt;
rake db:migrate&lt;/pre&gt;
&lt;h3&gt;4. Start the server:&lt;/h3&gt;
&lt;pre&gt;
script/server&lt;/pre&gt;
&lt;h3&gt;5. Delete the automatically generated layout file &lt;code&gt;views/layouts/pages.html.erb&lt;/code&gt;&lt;/h3&gt;
&lt;h3&gt;6. Create the four pages (home, about, contact, resources) through the admin interface:&lt;/h3&gt;
&lt;pre&gt;
Browse to http://localhost:3000/pages/new&lt;/pre&gt;
&lt;h3&gt;7. Create a controller and view for the public view of the page:&lt;/h3&gt;
&lt;pre&gt;
script/generate controller viewer show&lt;/pre&gt;
&lt;h3&gt;8. In controllers/viewer_controller.rb, add this line to the show method:&lt;/h3&gt;
&lt;pre&gt;
@page = Page.find_by_name(params[:name])&lt;/pre&gt;
&lt;h3&gt;9. Replace the boilerplate text in views/viewer/show.html.erb with this line:&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;%= @page.body %&amp;gt;&lt;/pre&gt;
&lt;h3&gt;10. You can now access the home page using the explicit &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;:&lt;/h3&gt;
&lt;pre&gt;
http://localhost:3000/viewer/show?name=home&lt;/pre&gt;
&lt;h3&gt;11. Create a route to clean this up. Add this line to config/routes.rb, after the map.resources line:&lt;/h3&gt;
&lt;pre&gt;
map.view_page ':name', :controller =&amp;gt; 'viewer', :action =&amp;gt; 'show'&lt;/pre&gt;
&lt;h3&gt;12. Update the route for the root (home) page (we created this line in Lesson 9):&lt;/h3&gt;
&lt;pre&gt;
map.root :controller =&amp;gt; 'viewer', :action =&amp;gt; 'show', :name =&amp;gt; 'home'&lt;/pre&gt;
&lt;h3&gt;13. Fix the navigation links in views/layouts/application.html.erb:&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;li&amp;gt;&amp;lt;%= link_to 'Home', view_page_path('home') %&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;%= link_to 'Resources', view_page_path('resources') %&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;%= link_to 'About Us', view_page_path('about') %&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;%= link_to 'Contact Us', view_page_path('contact') %&amp;gt;&amp;lt;/li&amp;gt;
&lt;/pre&gt;
&lt;h3&gt;14. Change the title tag line so that the title is pulled from the database:&lt;/h3&gt;
&lt;pre&gt;
&amp;lt;title&amp;gt;&amp;lt;%= @page.title %&amp;gt;&amp;lt;/title&amp;gt;&lt;/pre&gt;
&lt;p&gt;This will work for our normal pages, but it won&amp;rsquo;t work for the admin pages, since there isn&amp;rsquo;t always a valid @page object for those pages. So we need another way to set the page title for those pages. We change the layout to this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;title&amp;gt;&amp;lt;%= @pagetitle || @page.title %&amp;gt;&amp;lt;/title&amp;gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;||&lt;/code&gt; is the Ruby OR operator. If the item before the OR is not false, then the second item is not evaluated, so this expression essential says &amp;ldquo;use @pagetitle, unless it is nil; if it is nil, then use @page.title&amp;rdquo;. This enables us to set the pagetitle with an explicit instance variable in the admin controllers, and still use the @page object in the normal page controller.&lt;/p&gt;
&lt;p&gt;Now we need to set @pagetitle in the pages_controller. We want to set it to &amp;ldquo;Page Administration,&amp;rdquo; regardless of which action is executed. Rather than placing this code in every action, we can use a before filter, which runs the filter action before any other controller action. The code, which goes at the top of pages_controller.rb, is as follows:&lt;/p&gt;
&lt;pre&gt;
before_filter :loadmetadata

def loadmetadata
  @pagetitle = &amp;quot;Page Administration&amp;quot;    
end
&lt;/pre&gt;
&lt;h2&gt;Common Problems&lt;/h2&gt;
&lt;p&gt;Note that the home page route that we set requires that you create a page named home in the database. If you haven&amp;rsquo;t created a page with this name, you&amp;rsquo;ll get an error when browsing to the base &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;. (To create a page in the database, browse to localhost:3000/pages/new)&lt;/p&gt;
&lt;p&gt;Also, the navigation buttons assume there are pages with the names of about, resources, and contact, so if you haven&amp;rsquo;t created pages with those exact names in the database, you&amp;rsquo;ll get an error when you click on the corresponding button.&lt;/p&gt;
&lt;h2&gt;Onward!&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re back to where we started! The site now works just like the one we created in Lesson 9, but now all the page contents are in the database, and we have a simple administrative interface to edit this text.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one big problem with this simple implementation: anyone who can guess the URLs for accessing our admin interface can modify the site! In the next lesson, we&amp;rsquo;ll add a user log-in system to provide authentication for accessing the admin interface.&lt;/p&gt;
&lt;h2&gt;Resources&lt;/h2&gt;
&lt;p&gt;For more on the SQLite database, see our list of &lt;a href=&quot;/topic/24373-sqlite&quot;&gt;SQLite 3 tutorials, software, and FAQs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another &lt;a href=&quot;http://fairleads.blogspot.com/2007/12/rails-20-and-scaffolding-step-by-step.html&quot;&gt;Rails 2.0 scaffolding tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://peepcode.com&quot;&gt;Peepcode&lt;/a&gt; has a two-part introduction to Rails, titled &lt;a href=&quot;http://peepcode.com/products/rails-from-scratch-part-i&quot;&gt;Rails From Scratch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ready to dive deeper into Rails? See our &lt;a href=&quot;/books/list?category=5&quot;&gt;list of Ruby on Rails books&lt;/a&gt;</itunes:summary>
          <itunes:duration>00:35:00</itunes:duration>
        </item>
        
        <item>
          <title>9: The Simplest Possible Rails Application</title>
          <description>&lt;p&gt;This is the first screencast in the Learning Rails course. In this lesson, we build a very simple Ruby on Rails application, with just a few static pages, so we can walk through the files and show how the view system works.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:51 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79334-the-simplest-possible-rails-application</guid>
          <link>http://www.buildingwebapps.com/podcasts/79334-the-simplest-possible-rails-application</link>
          
            <enclosure url="http://s3.amazonaws.com/lr_screencasts/learningrails-9.mov" type="video/mpeg" />
           
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>Welcome to the first screencast in the Learning Rails free online course in Ruby on Rails.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; we created this series in 2008, and the Ruby on Rails world, along with the software that supports it (such as various gems) has evolved quite a bit since then. Check the comments for suggestions on how to overcome various incompatibilities. We hope to have an updated version of the series by the end of 2010.&lt;/p&gt;
&lt;p&gt;If you want to follow along on your own system, you&amp;rsquo;ll need to have a basic Ruby on Rails development environment set up. Check &lt;a href=&quot;/podcasts/79333-setting-up-your-development-environment/&quot;&gt;Lesson 8&lt;/a&gt; for details on how to do that.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;d love to hear any feedback you may have on this screencast. Please add your comment at the bottom of the page.&lt;/p&gt;
&lt;p&gt;In this lesson, we build a very simple Ruby on Rails application, with just a few static pages, so we can walk through the files that make up a Rails application and show how the view system works.&lt;/p&gt;
&lt;p&gt;The simple approach we&amp;rsquo;ve taken here isn&amp;rsquo;t something we would recommend for a production Rails application; it&amp;rsquo;s designed to cut away as much complexity as possible so we can focus on the essentials. In the next lesson, we&amp;rsquo;ll start building a more dynamic site.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s not a lot of code in this first lesson, and we&amp;rsquo;ll be replacing it in the next lesson, but you can &lt;a href=&quot;/learningrails_9.zip&quot;&gt;download the full application&lt;/a&gt; if you&amp;rsquo;d like.&lt;/p&gt;
&lt;p&gt;P.S. We&amp;rsquo;re still refining our production workflow, and the video in lesson is not quite up to our production quality goal. You&amp;rsquo;ll see improvements in future lessons.</itunes:summary>
          <itunes:duration>00:27:00</itunes:duration>
        </item>
        
        <item>
          <title>8: Setting Up Your Development Environment</title>
          <description>&lt;p&gt;Having made it this far in our series, you should have a good overview of the core concepts used in Ruby on Rails. The next step is to start building something! We're going to lead you through that too, with our upcoming screencasts. For you to follow along, you're going to need a development environment set up on your computer, and in this podcast we discuss the steps in doing so.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:51 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79333-setting-up-your-development-environment</guid>
          <link>http://www.buildingwebapps.com/podcasts/79333-setting-up-your-development-environment</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-8.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;p&gt;To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;The heart of the lesson is the audio; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; we created this series in 2008, and the Ruby  on Rails world, along with the software that supports it (such as  various gems) has evolved quite a bit since then. Check the comments for  suggestions on how to overcome various incompatibilities. We hope to  have an updated version of the series by the end of 2010.&lt;/p&gt;
&lt;h2&gt;Detailed Ruby on Rails Development Environment Installation Instructions&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/79197-setting-up-rails-on-leopard-mac&quot;&gt;Mac OS X 10.5 Leopard&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/79198-setting-up-rails-on-tiger-mac&quot;&gt;Mac OS X 10.4 Tiger&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/79200-setting-up-rails-on-windows-vista&quot;&gt;Windows Vista&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/articles/79199-setting-up-rails-on-windows-xp&quot;&gt;Windows XP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</itunes:summary>
          <itunes:duration>00::00</itunes:duration>
        </item>
        
        <item>
          <title>7: Testing Rails Code</title>
          <description>&lt;p&gt;Ruby on Rails incorporates tools that facilitate best practices when it comes to testing your code. Whether you leverage the built-in Test::Unit framework or add one of many more advanced testing tools, you can begin to build a &amp;quot;quality safety net&amp;quot; through a collection of unit, functional, and integration tests. We'll walk through how to get started writing and using tests, touch on some testing methodologies such as TDD and BDD, and get you familiar with the tools that will help maintain the quality of your application.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:51 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79332-testing-rails-code</guid>
          <link>http://www.buildingwebapps.com/podcasts/79332-testing-rails-code</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-7.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;p&gt;To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;h2&gt;Code Examples&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s an example of using asserts. Suppose you have a test that searches for a non-existent podcast episode; you&amp;rsquo;d want to assert that the result was nil. The test case code would read:&lt;/p&gt;
&lt;pre&gt;
def test_podcast_does_not_exist
  podcast = Podcast.find_by_title('Intro')
  assert_nil podcast
end
&lt;/pre&gt;
&lt;p&gt;Another example checking to see if the test database contains three podcasts loaded from fixtures might read:&lt;/p&gt;
&lt;pre&gt;
def test_three_podcasts_exist
  assert_equal, Podcast.find(:all), 3
end
&lt;/pre&gt;
&lt;p&gt;Here&amp;rsquo;s an example of a fixture, illustrating how fixtures can use model associations. An entry in the podcast.yml file might read:&lt;/p&gt;
&lt;pre&gt;
episodeone:
  name: Introductory Podcast
  listeners: anne, bob, charlie
&lt;/pre&gt;
&lt;p&gt;and entries in the listeners.yml file would read:&lt;/p&gt;
&lt;pre&gt;
anne:
  name: Anne
  podcast: episodeone

bob:
  name: Bob 
  podcast: episodeone

charlie:
  name: Charlie
  podcast: episodeone
&lt;/pre&gt;
&lt;h2&gt;Links to More Resources&lt;/h2&gt;
&lt;p&gt;See the following sections of the site for links to resources on testing:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24261-testing-ruby-on-rails-applications-unit&quot;&gt;Testing in general&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24275-using-test-driven-development-tdd-for-web&quot;&gt;Test-driven development&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24263-unit-tests-for-ruby-on-rails&quot;&gt;Unit testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24264-ruby-on-rails-functional-testing-for&quot;&gt;Functional testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24265-ruby-on-rails-integration-testing&quot;&gt;Integration testing&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24273-test-fixtures-for-ruby-on-railss&quot;&gt;Test fixtures&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24269-tools-for-testing-ruby-on-rails&quot;&gt;Testing Toolsl&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24262-using-behavior-driven-development-bdd-for-web&quot;&gt;Behavior-Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</itunes:summary>
          <itunes:duration>00:20:00</itunes:duration>
        </item>
        
        <item>
          <title>6: Tools for Rails Developers</title>
          <description>&lt;p&gt;The Ruby on Rails approach to application development goes beyond just your code itself; there's a variety of tools and practices that are a nearly integral part of it. These include keeping all your source code in a version control system (typically Subversion); the Rake automation tool; ri and rdoc documentation tools; and the Capistrano deployment tool; logging facilities; and the ruby-debug debugger.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:51 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79331-tools-for-rails-developers</guid>
          <link>http://www.buildingwebapps.com/podcasts/79331-tools-for-rails-developers</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-6.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;p&gt;To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;h2&gt;Lesson Notes&lt;/h2&gt;
&lt;p&gt;For links to more information about the various tools mentioned in this lesson, refer to following parts of the BuildingWebApps site:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24404-ides-integrated-development-environments-for-web&quot;&gt;IDEs&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24410-programming-editors-tools-to-make-your&quot;&gt;Editors&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24204-ruby-gems-and-libraries-modules-of&quot;&gt;Gems&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24400-automation-for-web-application-development-and&quot;&gt;Automation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24197-using-and-creating-plug-ins-for-ruby&quot;&gt;Plugins&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24423-version-control-source-code-control-for&quot;&gt;Source Code (Version) Control&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24318-deployment-techniques-for-ruby-on-rails&quot;&gt;Deployment&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24306-documentation-generation-with-ruby-on-rails&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24381-using-and-managing-system-and-custom&quot;&gt;Logging&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24213-debugging-ruby-and-ruby-on-rails&quot;&gt;Debugging&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;/topic/24261-testing-ruby-on-rails-applications-unit&quot;&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</itunes:summary>
          <itunes:duration>00:30:00</itunes:duration>
        </item>
        
        <item>
          <title>5: Rails Form Processing</title>
          <description>&lt;p&gt;Ruby on Rails provides a variety of facilities to simplify the use of forms to enter and update database information, which is one of the most common tasks for any web application. These include form helpers, which generate the HTML code for the form, validation methods for use in model classes that make it easy to check entered information for errors, and helpers to display those errors. We'll describe how all these features work together.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:51 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79330-rails-form-processing</guid>
          <link>http://www.buildingwebapps.com/podcasts/79330-rails-form-processing</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-5.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;h2&gt;Lesson Notes&lt;/h2&gt;
&lt;p&gt;&lt;span class=&quot;caps&quot;&gt;CRUD&lt;/span&gt; is the acronym for the four main things you do with database records:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Create&lt;/li&gt;
    &lt;li&gt;Read&lt;/li&gt;
    &lt;li&gt;Update&lt;/li&gt;
    &lt;li&gt;Delete&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These notes illustrate the code described in the podcast. See the transcript for more details.&lt;/p&gt;
&lt;p&gt;For more details about forms processing with Rails, see the &lt;a href=&quot;/topic/24227-creating-forms-with-ruby-on-rails&quot;&gt;forms&lt;/a&gt; page in our topics section. You&amp;rsquo;ll find some great screencasts listed there that will go into much more depth than this podcast.&lt;/p&gt;
&lt;p&gt;For a database of podcast episodes, with a title and a description field for each, the basic form code looks like this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% form_for @podcast do |form| %&amp;gt;
    &amp;lt;%= form.text_field :title %&amp;gt;
    &amp;lt;%= form.text_area :description %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The minimal code for the controller&amp;rsquo;s create action is:&lt;/p&gt;
&lt;pre&gt;
Podcast.create params[:podcast]
&lt;/pre&gt;
&lt;p&gt;The create method takes the parameters from the params[:podcast] hash, uses them to initialize a new object, and then saves that object to the database.&lt;/p&gt;
&lt;p&gt;This line to the podcast model ensures that podcasts can&amp;rsquo;t be saved with a blank title:&lt;/p&gt;
&lt;pre&gt;
validates_presence_of :title
&lt;/pre&gt;
&lt;p&gt;In the controller, the create action tests the value returned from the Podcast.create call, and if it is not false, it knows the save succeeded. If it is false, then the form is rendered again.&lt;/p&gt;
&lt;pre&gt;
if Podcast.create params[:podcast]
    redirect_to (wherever you want to go after a successful save)
else
    render :action =&amp;gt; :new
end
&lt;/pre&gt;
&lt;p&gt;To display the error messages, the form view just includes a call to the error_messages_for helper:&lt;/p&gt;
&lt;pre&gt;
error_messages_for :podcast
&lt;/pre&gt;
&lt;p&gt;To make this an Ajax form, we can simply change the form_for helper to remote_form_for:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% remote_form_for @podcast do |form| %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The rest of the form remains the same. The controller and views must be modified to return just an &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; or JavaScript snipped, rather than an entire page, after a create or update action.</itunes:summary>
          <itunes:duration>00:18:00</itunes:duration>
        </item>
        
        <item>
          <title>4: Rails Models</title>
          <description>&lt;p&gt;Rails provides an elegant set of tools for creating your database and accessing it. Migrations are simple Ruby files that let you create your database tables without SQL. You access the database through the model objects you create, which inherit a rich set of capabilities from Active Record. You can define associations between models that enable you to easily access related data that is spread across multiple tables.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:50 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79329-rails-models</guid>
          <link>http://www.buildingwebapps.com/podcasts/79329-rails-models</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-4.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;h2&gt;Resources for Further Study&lt;/h2&gt;
&lt;p&gt;Any Ruby on Rails book will explain how migrations, models, and associations work. The classic Agile Web Development with Rails does a good job explaining them.&lt;/p&gt;
&lt;p&gt;Note that Rails 2.0 provides a slightly simpler syntax for migrations, which we&amp;rsquo;ve used in our examples, so in most books you&amp;rsquo;ll see the Rails 1.2 style.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://wiki.rubyonrails.org/rails/pages/UnderstandingMigrations&quot;&gt;Rails wiki&lt;/a&gt; has an explanation of migrations, but as of this writing it has not been updated for Rails 2.0. The &lt;a href=&quot;http://api.rubyonrails.org/classes/ActiveRecord/Migration.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; document&lt;/a&gt; provides a less readable but more complete and up-to-date description.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a &lt;a href=&quot;http://www.netbeans.org/kb/60/ruby/model.html&quot;&gt;hand-on tutorial using NetBeans 6.0&lt;/a&gt; that shows how to create migrations and models using the NetBeans &lt;span class=&quot;caps&quot;&gt;IDE&lt;/span&gt;.&lt;/p&gt;
&lt;h2&gt;Code Examples&lt;/h2&gt;
&lt;p&gt;The user requirements for the example we discuss in this podcast are:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;A visitor to the site sees a list of podcasts with their title, description, and a link to an MP3 file&lt;/li&gt;
    &lt;li&gt;If there is an associated show note for that podcast, a link appears that goes to a page displaying it.&lt;/li&gt;
    &lt;li&gt;Each podcast is tagged with one or more topic categories which the visitor can see next to the podcast&amp;rsquo;s other information&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s a schematic drawing of the required objects:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; src=&quot;/LR_episode_4.jpg&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The migration that creates the podcast database table reads something like this:&lt;/p&gt;
&lt;pre&gt;
create_table &amp;quot;podcasts&amp;quot; do |t|
    t.string &amp;quot;title&amp;quot;
    t.string &amp;quot;description&amp;quot;
    t.string &amp;quot;filename&amp;quot;
end
&lt;/pre&gt;
&lt;p&gt;The create_table line begins a code block that defines the table. This line provides the shortcut name t, which is referenced in the lines that define the table.&lt;/p&gt;
&lt;p&gt;To create a new podcast object, you use a very simple Podcast class and simply type:&lt;/p&gt;
&lt;pre&gt;
episode = Podcast.new
&lt;/pre&gt;
&lt;p&gt;And now you have an instance of the Podcast class, which you&amp;rsquo;ve named episode. Now, to set its attributes, you can simply write:&lt;/p&gt;
&lt;pre&gt;
episode.title = &amp;quot;Learning Ruby on Rails&amp;quot;
episode.filename = &amp;quot;learningrails-1.mp3&amp;quot;
episode.description = &amp;quot;This episode covers...&amp;quot;
&lt;/pre&gt;
&lt;p&gt;When this code is executed, you&amp;rsquo;ve created the episode object and filled it with data. Now it takes one more line of code, &lt;code&gt;episode.save&lt;/code&gt;, to write the data to the database.&lt;/p&gt;
&lt;p&gt;To find an episode by name, you can simply write:&lt;/p&gt;
&lt;pre&gt;
episode = Podcast.find_by_title('Learning Ruby on Rails')
&lt;/pre&gt;
&lt;p&gt;and you&amp;rsquo;ll get back a podcast object, called episode, with all the information about that podcast.&lt;/p&gt;
&lt;p&gt;What about the show notes? We need another migration to define that table, the core of which is simply:&lt;/p&gt;
&lt;pre&gt;
t.text &amp;quot;body&amp;quot;
t.integer &amp;quot;podcast_id&amp;quot;
&lt;/pre&gt;
&lt;p&gt;The body field is where we store the text of the show notes. (The column type of &amp;ldquo;text&amp;rdquo; instead of &amp;ldquo;string&amp;rdquo; tells the database to allow a potentially large amount of text.)&lt;/p&gt;
&lt;p&gt;The podcast_id field is how Rails knows what podcast a particular show_notes object is associated with.&lt;/p&gt;
&lt;p&gt;To set up the association, you add one line of code to each of the associated models&amp;rsquo; classes. The podcast class gets a line that reads:&lt;/p&gt;
&lt;pre&gt;
has_one :show_notes
&lt;/pre&gt;
&lt;p&gt;and the show_notes model gets a line that reads:&lt;/p&gt;
&lt;pre&gt;
belongs_to :podcast
&lt;/pre&gt;
&lt;p&gt;With these two simple additions, you can now write episode.show_notes to access the show notes for a particular episode.&lt;/p&gt;
&lt;p&gt;To associate podcasts with categories, we need a join table, whose field definitions are:&lt;/p&gt;
&lt;pre&gt;
t.integer podcast_id
t.integer category_id
&lt;/pre&gt;
&lt;p&gt;With the join table created and the &lt;span class=&quot;caps&quot;&gt;HABTM&lt;/span&gt; declarations in the two model files, you can simply write&lt;/p&gt;
&lt;pre&gt;
episode.categories
&lt;/pre&gt;
&lt;p&gt;and you&amp;rsquo;ll get back an array of category objects, one for each category that is associated with that particular episode.</itunes:summary>
          <itunes:duration>00::00</itunes:duration>
        </item>
        
        <item>
          <title>3: Rails Views -- How Rails Renders Pages</title>
          <description>&lt;p&gt;Rails creates web pages through a combination of layouts, templates, and partials. We'll explore how they work together to create a powerful mechanism for laying out web pages. We'll also touch on the Ajax support that is built in to Rails.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:50 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79328-rails-views-how-rails-renders</guid>
          <link>http://www.buildingwebapps.com/podcasts/79328-rails-views-how-rails-renders</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-3.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;p&gt;To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;h2&gt;Code Examples&lt;/h2&gt;
&lt;p&gt;In this podcast, we mention several bits of code that are hard to visualize in audio, so we&amp;rsquo;ve included them here. Refer to the &lt;a href=&quot;/podcasts/79328-rails-views-how-rails-renders/24794-transcript&quot;&gt;transcript&lt;/a&gt; to see these examples in context.&lt;/p&gt;
&lt;p&gt;For links to additional resources, scroll down past the code examples.&lt;/p&gt;
&lt;h3&gt;Embedded Ruby&lt;/h3&gt;
&lt;p&gt;Ruby code in a view template is preceded by &lt;code&gt;&amp;lt;%&lt;/code&gt; and followed by &lt;code&gt;%&amp;gt;&lt;/code&gt;. The enclosed text is what is called &amp;ldquo;embedded Ruby,&amp;rdquo; or ERb.&lt;/p&gt;
&lt;p&gt;If the Ruby code is preceded by just &lt;code&gt;&amp;lt;%&lt;/code&gt;, then the code is executed, but its output is not inserted into the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; stream. For example, you might have Ruby code that says something like &amp;ldquo;if podcast title is not blank&amp;rdquo;. In real code, this would be:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% if !podcast.title.blank? %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;For example, if we had a variable named title and we wanted its value to be inserted into the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, we&amp;rsquo;d write&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= title %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Last episode, we gave as an example a page listing all the episodes of this podcast. In this example, the variable that would be passed to the view would be an array of podcast objects.&lt;/p&gt;
&lt;p&gt;The code to do so looks like this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% for podcast in podcasts %&amp;gt;
    &amp;lt;h2&amp;gt;&amp;lt;%= podcast.title %&amp;gt;&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;&amp;lt;%= podcast.description %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;h3&gt;Partials&lt;/h3&gt;
&lt;p&gt;A partial is just a small view template that is meant to be included in another template, or in a layout. The statement that goes in the controller is:&lt;/p&gt;
&lt;pre&gt;
render :partial =&amp;gt; 'partial_name'
&lt;/pre&gt;
&lt;p&gt;You can also use a partial when you want to repeatedly insert the same bit of markup, but using data from a series of objects. For example, consider our listing of podcast episodes. We can use a partial that displays the information for a single podcast. You could simply put that partial in a loop that executes it once for each podcast object, like this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;% for podcast in podcasts %&amp;gt;
    &amp;lt;%= render :partial =&amp;gt; 'podcast' %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;(For simplicity, we&amp;rsquo;re ignoring here some details about how the podcast variable is passed to the partial.)&lt;/p&gt;
&lt;p&gt;But Rails gives us a shortcut that makes this even simpler; in the &amp;ldquo;render partial&amp;rdquo; statement, we can refer to the array of podcast objects (which the controller provided), and the partial will automatically be repeated for each podcast in the array. Here&amp;rsquo;s the code:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= render :partial =&amp;gt; 'podcast', :collection =&amp;gt; podcasts %&amp;gt;
&lt;/pre&gt;
&lt;h3&gt;Rails Helpers&lt;/h3&gt;
&lt;p&gt;Instead of writing:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;a href = 'some_URL'&amp;gt;Text to be linked&amp;lt;/a&amp;gt;
&lt;/pre&gt;
&lt;p&gt;you can use the Rails link_to helper, like this:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= link_to 'Text to be linked', 'some_URL' %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The link_to helper is more interesting when you use it to help you generate the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;, instead of specifying it explicitly. For example, you can specify the controller and action you want the link to invoke, and any parameters that you want to pass to it, and let link_to generate the &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;. Dynamic generation of links is really preferable when it comes to flexibility and maintenance of your code. For example, you could write:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= link_to 'View Transcript', 
    :controller =&amp;gt; 'podcast', 
    :action =&amp;gt; 'view_transcript', 
    :id =&amp;gt; podcast %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Another common helper is image_tag. Instead of the usual&lt;/p&gt;
&lt;pre&gt;
&amp;lt;img src = '/images/filename'&amp;gt;
&lt;/pre&gt;
&lt;p&gt;you can write Ruby code that reads&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= image_tag 'filename' %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Rails assumes, by default, that all images are in a directory called images, so you don&amp;rsquo;t need to include the directory as part of the filename. You can also add additional parameters, such as alt text and image dimensions, using Ruby instead of &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; code, such as:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= image_tag 'filename', 
    :alt =&amp;gt; 'Alt text goes here', 
    :height =&amp;gt; 50, :width =&amp;gt; 125 %&amp;gt;
&lt;/pre&gt;
&lt;h3&gt;&lt;span class=&quot;caps&quot;&gt;DHTML&lt;/span&gt; with Rails&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s a simplified version of the code to observe the shipping adddress checkbox and call as JavaScript function when it is checked:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= observe_field 'shipping_address', 
    :function =&amp;gt; 'show_shipping_address();' %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;(We haven&amp;rsquo;t shown here the code that defines the JavaScript function show_shipping_address(), which you could write in conventional JavaScript.)&lt;/p&gt;
&lt;p&gt;With &lt;span class=&quot;caps&quot;&gt;RJS&lt;/span&gt; (Ruby JavaScript), you can write something like:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= observe_field 'shipping_address', 
    :function =&amp;gt; update_page {|page| page[:shipping_address].show} %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;There&amp;rsquo;s a bit of Ruby syntax there that we haven&amp;rsquo;t explained, but hopefully you get the idea. We&amp;rsquo;ve also ignored, for simplicity, the need to hide the shipping address if the box is unchecked.&lt;/p&gt;
&lt;h3&gt;Ajax with Rails&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s the observe_field statement that makes an Ajax call to the server to get the address:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;%= observe_field 'address_chooser',
    :update =&amp;gt; 'shipping_address',
    :url =&amp;gt; {:controller =&amp;gt; 'user', :action =&amp;gt; 'get_address'},
    :with =&amp;gt; 'address_chooser' %&amp;gt;
&lt;/pre&gt;
&lt;h2&gt;Resources for Further Learning&lt;/h2&gt;
&lt;p&gt;See the &lt;a href=&quot;/learningrails/1&quot;&gt;Lesson Page for lesson 1&lt;/a&gt; for links to Ruby and Rails books and other  resources.&lt;/p&gt;
&lt;p&gt;If you want to get deep into the Ajax aspects of Rails, there&amp;rsquo;s one book devoted to that subject: &lt;a href=&quot;http://www.amazon.com/gp/product/0596527446?ie=UTF8&amp;amp;tag=buildicom-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596529864&quot;&gt;Ajax on Rails&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To learn more about the JavaScript frameworks included in Rails, visit their sites:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://prototypejs.org&quot;&gt;Prototype&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://script.aculo.us/&quot;&gt;Scriptaculous&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</itunes:summary>
          <itunes:duration>00:22:00</itunes:duration>
        </item>
        
        <item>
          <title>2: Anatomy of a Web Application</title>
          <description>&lt;p&gt;In this episode, we look at just what happens when a user enters a URL in their browser, and how this is translated into a request for a specific file in a static site or a typical PHP site. In a Rails application, it instead becomes a request to execute a particular action in a particular controller, which will use model objects to request data from the database and then pass that information, in the form of a variable, to the view, where it will be rendered into a page.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:50 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79327-anatomy-of-a-web-application</guid>
          <link>http://www.buildingwebapps.com/podcasts/79327-anatomy-of-a-web-application</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-2.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;h2&gt;Examples used in the audio program&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s some of the examples we use in the show, which may be easier to grasp in printed form:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;If the user types www.BuildingWebApps.com/podcast.html into their browser, they&amp;rsquo;re asking the server at BuildingWebApps.com to find a file called podcast.html and send the contents of that file to the browser.&lt;/li&gt;
    &lt;li&gt;In a Rails application, the request would be written as www.BuildingWebApps.com/podcast, in which podcast is the name of the controller to be invoked&lt;/li&gt;
    &lt;li&gt;A Rails &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; such as www.BuildingWebApps.com/podcast/show/17 invokes the show action in the podcast controller and passes it the parameter of 17 (presumably the ID for a podcast episode).&lt;/li&gt;
    &lt;li&gt;To request all the podcast objects, the controller would execute a statement such as &lt;code&gt;podcasts = Podcast.find(:all)&lt;/code&gt;. (Don&amp;rsquo;t worry about the odd punctuation for now.&lt;/li&gt;
    &lt;li&gt;To find a particular podcast episode according to its episode number, the show action might execute a statement such as &lt;code&gt;podcast = Podcast.find_by_episode(2)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;For More Information&lt;/h2&gt;
&lt;p&gt;See the notes for &lt;a href=&quot;/podcasts/79326-why-you-should-learn-ruby-on/24793-show-notes&quot;&gt;Lesson 1&lt;/a&gt; for pointers to online resources and books about Ruby and Ruby on Rails.</itunes:summary>
          <itunes:duration>00:17:00</itunes:duration>
        </item>
        
        <item>
          <title>1: Why You Should Learn Ruby on Rails</title>
          <description>&lt;p&gt;Ruby on Rails is one of the fastest-growing web development platforms. In this inaugural Learning Rails podcast, we explain what Ruby and Rails are, the huge &amp;quot;sweet spot&amp;quot; for Rails applications, and why it is worth investing your time to learn the platform.&lt;/p&gt;</description>
          <pubDate>Thu, 24 Jul 2008 08:00:49 GMT</pubDate>
          <guid>http://www.buildingwebapps.com/podcasts/79326-why-you-should-learn-ruby-on</guid>
          <link>http://www.buildingwebapps.com/podcasts/79326-why-you-should-learn-ruby-on</link>
           
          
            <enclosure  url="http://www.buildingwebapps.com/learningrails-1.mp3" type="audio/mpeg"  />
          
          <itunes:explicit>No</itunes:explicit>
          <itunes:summary>&lt;h2&gt;Welcome to the Learning Rails Online Course&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;ve read this far, you probably already have an interest in building web applications with Ruby on Rails. But just in case you&amp;rsquo;re unsure if Rails is worth learning, in this lesson we explore the reasons for the success of Ruby on Rails and the benefits that can result from using it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The heart of the lesson is the audio&lt;/strong&gt;; these notes are supplementary. So please listen to the audio, or read the transcript, before making use of these notes.&lt;/p&gt;
&lt;p&gt;To listen to the lesson, click the Play button on the left. You can also right-click on the download link to save the mp3 file, or you can subscribe in iTunes (just search for Learning Rails).&lt;/p&gt;
&lt;p&gt;To read a transcript of the lesson, click the Transcript link on the left.&lt;/p&gt;
&lt;h2&gt;Web resources&lt;/h2&gt;
&lt;p&gt;Keep in mind the distinction between Ruby and Ruby on Rails:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Ruby is a programming language&lt;/li&gt;
    &lt;li&gt;Ruby on Rails (often called simply &amp;ldquo;Rails&amp;rdquo;) is a framework for building web applications with Ruby&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The central web resources for Ruby and Rails, respectively, are:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.ruby-lang.org&quot;&gt;Ruby Language&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.rubyonrails.com&quot;&gt;Ruby on Rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to do some more preparation for your Ruby on Rails education, we highly recommend that you begin learning Ruby, the programming language, without regard to Rails (at first). You don&amp;rsquo;t need an extensive knowledge of Ruby, but you need to learn the basics. We&amp;rsquo;ll talk about Ruby a little more in later lessons, but you can get started now learning it on your own.&lt;/p&gt;
&lt;p&gt;If you have experience with another programming language, much of Ruby will seem very natural. If you don&amp;rsquo;t have any experience with object-oriented programming, you may want to read up on Ruby objects &amp;mdash; in Ruby, everything is an object, and you&amp;rsquo;ll work with them constantly.&lt;/p&gt;
&lt;p&gt;Ruby uses one unusual construct, the code block, which is unfamiliar to most programmers and merits some study. Code blocks are used extensively in Rails.&lt;/p&gt;
&lt;p&gt;Ruby-lang.org has a &lt;a href=&quot;http://www.ruby-lang.org/en/documentation/quickstart/&quot;&gt;good introductory tutorial&lt;/a&gt; and a &lt;a href=&quot;http://www.ruby-doc.org/docs/ruby-doc-bundle/Tutorial/&quot;&gt;longer introduction to Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.techotopia.com/index.php/Ruby_Essentials&quot;&gt;Ruby Essentials&lt;/a&gt; is a short online ebook on ruby.&lt;/p&gt;
&lt;p&gt;And for those of you who are more graphically inclined, check out &lt;a href=&quot;http://mislav.uniqpath.com/poignant-guide/&quot;&gt;Why&amp;rsquo;s Poignant Guide to Ruby&lt;/a&gt;, it even has foxes!&lt;/p&gt;
&lt;p&gt;You can begin experimenting with Ruby right in your browser, without having to install anything. Just browse to &lt;a href=&quot;http://tryruby.hobix.com/&quot;&gt;tryruby.hobix.com&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Introductory books&lt;/h2&gt;
&lt;p&gt;You need to learn about both Ruby and Rails, and you&amp;rsquo;ll want separate books for each of them.&lt;/p&gt;
&lt;p&gt;For beginning Ruby, these are both good introductory books:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0596529864/buildicom-20&quot;&gt;Learning Ruby&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1590597664/buildicom-20&quot;&gt;Beginning Ruby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are several other valuable references and advanced guides for Ruby, which you&amp;rsquo;ll want to pick up if you get serious about your Ruby programming; see &lt;a href=&quot;/books/list?category=6&quot;&gt;our Ruby bookstore&lt;/a&gt; for an extensive list.&lt;/p&gt;
&lt;p&gt;For learning Ruby on Rails, the current selection of books is a little problematic. Two years ago, there were only a few books; now there are dozens, which makes it more confusing to pick one. And alas, most of them are written for Rails 1.2.6, and the ones that are the most up-to-date are not well suited for beginners.&lt;/p&gt;
&lt;p&gt;Although it is not the most accessible book for a novice programmer, and is written for Rails 1.2.x, &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0977616630/buildicom-20&quot;&gt;Agile Web Development with Rails&lt;/a&gt; remains the classic Rails book. But if you&amp;rsquo;re using Rails 2, which we recommend you do, parts of this book will be confusing due to changes in the framework.&lt;/p&gt;
&lt;p&gt;The most up-to-date and in-depth book on Ruby on Rails is &lt;strong&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0321445619/buildicom-20&quot;&gt;The Rails Way&lt;/a&gt;&lt;/strong&gt;. It isn&amp;rsquo;t written as an introductory book, so while we highly recommend it as a reference, you&amp;rsquo;ll probably want to start with another book to get your bearings first. The Agile book mentioned above is a good place to start, especially if you have a programming background. If you&amp;rsquo;re looking for a gentler introduction, some of the available books include:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1590597524/buildicom-20&quot;&gt;Rails Solutions: Ruby on Rails Made Easy&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0975841955/buildicom-20&quot;&gt;Build Your Own Ruby on Rails Web Applications&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1590596862/buildicom-20&quot;&gt;Beginning Rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other books provide a lot of example code that provide useful guides for how to implement various features. Books of this type include:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1590598415/buildicom-20&quot;&gt;Practical Rails Social Networking Sites&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0321480791/buildicom-20&quot;&gt;RailsSpace: Building a Social Networking Website with Ruby on Rails&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/1590597362/buildicom-20&quot;&gt;Beginning Ruby on Rails E-Commerce&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0596527314/buildicom-20&quot;&gt;Rails Cookbook&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0977616606/buildicom-20&quot;&gt;Rails Recipes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See our &lt;a href=&quot;/books/list?category=5&quot;&gt;complete list of Ruby and Ruby on Rails Books&lt;/a&gt; for more.&lt;/p&gt;</itunes:summary>
          <itunes:duration>00:22:00</itunes:duration>
        </item>
    
    
  </channel>
</rss>