<feed version="0.3" xml:lang="en-US" xmlns="http://purl.org/atom/ns#">
  <title>Hieraki recent changes</title>
  <tagline mode="escaped" type="text/html"/>
  <id>tag:manuals.rubyonrails.com,2004:Hieraki</id>
  <generator url="http://www.hieraki.org">Hieraki</generator>
  <link href="http://127.0.0.1:15101/" rel="alternate" type="text/html"/>
  <modified>2007-05-24T06:33:32+00:00</modified>
  <entry>
    <author>
      <name>rabble</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-727</id>
    <issued>2007-05-24T06:33:32+00:00</issued>
    <modified>2007-05-24T06:33:32+00:00</modified>
    <title>rabble: Blogs</title>
    <link href="http://127.0.0.1:15101/read/chapter/123#page338" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;There are many places you can get more information about testing rails.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://blog.testingrails.com/"&gt;rabble&amp;#8217;s testing rails&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://glu.ttono.us/"&gt;kevin clark&amp;#8217;s gluttonous&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://therailsway.com/"&gt;the rails way&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://nubyonrails.com/"&gt;nuby on rails&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;zen test&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;</content>
  </entry>
  <entry>
    <author>
      <name>rabble</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-726</id>
    <issued>2007-05-24T06:29:57+00:00</issued>
    <modified>2007-05-24T06:29:57+00:00</modified>
    <title>rabble: Blogs</title>
    <link href="http://127.0.0.1:15101/read/chapter/123#page338" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;There are many places you can get more information about testing rails.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://blog.testingrails.com/"&gt;rabble&amp;#8217;s testing rails&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://glu.ttono.us/"&gt;kevin clark&amp;#8217;s gluttonous&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="&lt;/li"&gt;zen test&lt;/a&gt;&gt;
	&lt;/ul&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Sascha Ebach</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-725</id>
    <issued>2007-03-18T18:57:50+00:00</issued>
    <modified>2007-03-18T18:57:50+00:00</modified>
    <title>Sascha Ebach: Translating Rails Apps</title>
    <link href="http://127.0.0.1:15101/read/chapter/105#page298" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;h1&gt;Using Gettext To Translate Your Rails Application&lt;/h1&gt;


	&lt;p style="color: red;"&gt;The version of this document is optimized for Ruby-GetText 1.9.0 and Rails 1.2.&lt;/p&gt;


	&lt;h2&gt;Introduction&lt;/h2&gt;


	&lt;h3&gt;Stand on the shoulders of Giants&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://www.gnu.org/software/gettext/"&gt;Gettext&lt;/a&gt; is a great tool for translating user interfaces of applications into different languages. It has been around for a long time and is very well established for this task. Gettext helps you to open up your application to a much wider user base than you would normaly reach in only one language. Since it is used in many open source projects it has a lot of useful tools you can use to your own advantage. It would be possible to &amp;#8220;roll your own&amp;#8221; solution, but this would consume a large amount of time. Time you would lose for the development of your app. And this is not something you would want, right?&lt;/p&gt;


	&lt;p&gt;So in this tutorial I am going to show you how to effectively use Gettext for all your translation needs in your Ruby on Rails application.&lt;/p&gt;


	&lt;h3&gt;What can Gettext do for you?&lt;/h3&gt;


	&lt;p&gt;Here is a quick explanation of Gettext for those of you who haven&amp;#8217;t worked with it, yet. Gettext is a set of tools that provide help when translating strings in your software. It gives you (straight from the &lt;a href="http://www.gnu.org/software/gettext/manual/html_node/gettext_2.html#SEC2"&gt;gettext manual&lt;/a&gt;):&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;A set of conventions about how programs should be written to support message catalogs.&lt;/li&gt;
		&lt;li&gt;A directory and file naming organization for the message catalogs themselves.&lt;/li&gt;
		&lt;li&gt;A runtime library supporting the retrieval of translated messages.&lt;/li&gt;
		&lt;li&gt;A few stand-alone programs to massage in various ways the sets of translatable strings, or already translated strings.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The only thing you have to do to your program sources is wrap all translatable strings with a method call: &lt;code&gt;gettext(text)&lt;/code&gt; or shorter &lt;code&gt;_(text)&lt;/code&gt;. Example:&lt;/p&gt;


	&lt;p&gt;Without gettext:&lt;/p&gt;


&lt;pre&gt;notice = 'Thank you for buying our product.'&lt;/pre&gt;

	&lt;p&gt;With gettext:&lt;/p&gt;


&lt;pre&gt;notice = _('Thank you for buying our product.')&lt;/pre&gt;

	&lt;p&gt;If you have wrapped everything between the method call Gettext will provide you with the tools to extract these messages (called a harvester) from your source code and save the results to a portable file format. A runtime library will allow you to display a translated message whenever _() is called.
In essence this is what Gettext does. It can do a couple of more things (like update / merge message catalogs, handling plurals, ...) but essentially it tries to make it as easy and as unobtrusive as possible to translate the language strings in your source code and then get out of your way.&lt;/p&gt;


	&lt;h2&gt;Preperation is everything&amp;#8212;use &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 everywhere&lt;/h2&gt;


	&lt;h3&gt;Edit your files with &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 only&lt;/h3&gt;


	&lt;p&gt;The &lt;span class="caps"&gt;W3C&lt;/span&gt; has an awesome page with all you need to know about character sets (choosing, declaring, serving, editing, ...) and other important stuff concerning internationalization on their site called &lt;a href="http://www.w3.org/International/resource-index.html"&gt;W3C &lt;span class="caps"&gt;I18N &lt;/span&gt;Topic Index&lt;/a&gt;. There you will find a lot of good help and suggestions on everything you need to know about general internationalization topics. You really want to spend at least a couple of hours reading through the resources they offer or link to.&lt;/p&gt;


	&lt;p&gt;If you happen to use &lt;span class="caps"&gt;VIM&lt;/span&gt; like I do you can put these two lines in your &lt;code&gt;.vimrc&lt;/code&gt; and it will from then on treat your files as &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 and convert everything to &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 whenever you save a file:&lt;/p&gt;


&lt;pre&gt;set encoding=utf8
set fileencoding=utf8&lt;/pre&gt;

	&lt;p&gt;If your editor of choice doesn&amp;#8217;t provide support for &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 it is probably time to get a new one ;)&lt;/p&gt;


	&lt;h3&gt;Feed your database with &lt;span class="caps"&gt;UTF&lt;/span&gt;-8&lt;/h3&gt;


	&lt;p&gt;If I need a database I usually go for MySQL. At least most of the time. Since version 4.1.x MySQL has very good support for different character sets. Please read the extensive &lt;a href="http://www.quepublishing.com/articles/printerfriendly.asp?p=328641&amp;#38;rl=1"&gt;MySQL Character Set Support&lt;/a&gt; article. It will give you a very good idea about the kind of support MySQL has to offer.&lt;/p&gt;


	&lt;p&gt;Here is a table definition I use in a current project:&lt;/p&gt;


&lt;pre&gt;CREATE TABLE `pages` (
 `id` int(10) unsigned NOT NULL auto_increment,
 `title` varchar(255) default NULL,
 `keywords` varchar(255) default NULL,
 `description` varchar(255) default NULL,
 `block1` text,
 `block2` text,
 `block3` text,
 `block4` text,
 `block5` text,
 `lang` varchar(10) NOT NULL default 'en_EN',
 `category` varchar(255) default NULL,
 `path` varchar(255) default '/',
 `updated_at` datetime default NULL,
 `created_at` datetime default NULL,
 `published_at` datetime default NULL,
 `layout` varchar(255) default 'main.rhtml',
 `template` varchar(255) default NULL,
 `access` tinyint(3) unsigned default '3',
 `version` int(10) unsigned default '1',
 `is_published` tinyint(3) unsigned default '0',
 PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;&lt;/pre&gt;

	&lt;p&gt;There is nothing really special about it except the &lt;code&gt;DEFAULT CHARSET=utf8&lt;/code&gt; in the last line. It will make MySQL use &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 for every field that holds text like &lt;code&gt;varchar&lt;/code&gt; and &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Add the following line to your &lt;code&gt;database.yml&lt;/code&gt; to connect with &lt;span class="caps"&gt;UTF&lt;/span&gt;-8.&lt;/p&gt;


&lt;pre&gt;encoding: UTF8&lt;/pre&gt;

	&lt;p&gt;If you use another maybe more mature and feature rich database like PostgreSQL &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 support should also be available. Just make sure you configure everything upfront, because it might save you time later on.&lt;/p&gt;


	&lt;p&gt;If you still think you are going to tack on support for &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 later you might reconsider after reading David&amp;#8217;s and Jamis&amp;#8217; experiences: &lt;a href="http://www.loudthinking.com/arc/000415.html"&gt;Forty-four grueling hours (or Welcome to 37s!) by David Heinemeier Hansson&lt;/a&gt; and &lt;a href="http://weblog.jamisbuck.org/2005/3/5/on-the-job"&gt;On the job by Jamis Buck&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;If for any reason you need to use anything other than &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 you might want to know that you can use the Iconv module to convert between different character sets. This module should be installed by default on most distributions. If it is not it is usually easy to get. Just be sure to get it if you need charcter set conversion. On Debian you might need a &lt;code&gt;apt-get install libiconv-ruby&lt;/code&gt; to get started. Here is a little example stolen from &lt;a href="http://pragmaticprogrammer.com/titles/ruby/"&gt;Pickaxe 2&lt;/a&gt; page 686:&lt;/p&gt;


	&lt;p&gt;Example: Convert &lt;em&gt;ol&amp;eacute;&lt;/em&gt; from &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 to &lt;span class="caps"&gt;ISO&lt;/span&gt;-8859-1&lt;/p&gt;


&lt;pre&gt;$ irb -riconv
&amp;gt;&amp;gt; Iconv.conv('ISO-8859-1', 'UTF-8', "ol\303\251")
=&amp;gt; "ol\351"&lt;/pre&gt;

	&lt;h3&gt;Installing Ruby-GetText&lt;/h3&gt;


	&lt;p&gt;After everything in your setup will accept &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 we can go ahead and install Gettext support in Ruby. We will use the  &lt;a href="http://gettext.rubyforge.org/"&gt;Ruby-GetText-Package&lt;/a&gt; which is a Ruby implementation of the Gettext interface that also has some c-bindings for the Locale.&lt;/p&gt;


	&lt;p&gt;If you have rubygems, you can easily install Ruby-GetText:&lt;/p&gt;


&lt;pre&gt;$ gem install gettext
Select which gem to install for your platform (...)
 1. gettext 1.9.0 (ruby)
 2. gettext 1.9.0 (mswin32)
 ...
&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;Be sure to choose option 2 if you want Ruby-GetText to work on native Windows (with &lt;a href="http://rubyforge.org/projects/rubyinstaller/"&gt;One-Click Ruby Installer&lt;/a&gt;) as you are most likely not able to compile otherwise. For all other platforms use 1.&lt;/p&gt;


	&lt;p&gt;Alternative: If you need the source you can get it from the author&amp;#8217;s site: &lt;a href="http://gettext.rubyforge.org/"&gt;Ruby-GetText-Package&lt;/a&gt;. Besides &lt;a href="http://ponx.s5.xrea.com/hiki/ruby-gettext.html#Install"&gt;installation instructions&lt;/a&gt; you will find a small &lt;a href="http://ponx.s5.xrea.com/hiki/ruby-gettext-howto.html"&gt;HOWTO&lt;/a&gt;, &lt;a href="http://ponx.s5.xrea.com/hiki/ruby-gettext-api.html"&gt;API Reference&lt;/a&gt; and documentation on &lt;a href="http://ponx.s5.xrea.com/hiki/ruby-gettext-tools.html"&gt;how to use provided tools&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Check the sample Rails application that is delivered with Ruby-GetText. If you installed via RubyGems it is most likely here: /usr/lib/ruby/gems/1.8/gems/gettext-1.9.0/samples/rails/, but it could be somewhere else depending on where your Ruby is installed. Later I will call that path $RUBYGETTEXT_RAILS_SAMPLE. So keep this in mind when you read.&lt;/p&gt;


	&lt;h3&gt;Create the &amp;#8220;po&amp;#8221; directory structure&lt;/h3&gt;


	&lt;p&gt;Create a &lt;code&gt;po&lt;/code&gt; dir right in your $RAILS_ROOT. In it you will create a subdir for every language/dialect combination (actually the second part of this abbreviation stands for &amp;#8220;geographic region&amp;#8221;, but I will just call it dialect throughout this document). If you don&amp;#8217;t know the right code for your language you can seek help at the &lt;a href="http://www.w3.org/International/resource-index.html#lang"&gt;Language section of the &lt;span class="caps"&gt;W3C I18N &lt;/span&gt;Topic Index&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Ultimately your directory structure is going to look like this:&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/po:
$ d -T
/home/simplepages/rails/po/:
 |-myapp.pot
 |-de_DE/:
 |    `-myapp.po
 |-en_GB/:
 |    `-myapp.po
 |-en_US/:
 |    `-myapp.po
 |-fr_FR/:
 |    `-myapp.po
 |-fr_CH/:
 |    `-myapp.po
 `-ja/:
      `-myapp.po&lt;/pre&gt;

	&lt;p&gt;The &lt;code&gt;myapp.pot&lt;/code&gt; file is the original file created by the &lt;code&gt;rgettext&lt;/code&gt; script introduced later. The po files will contain the translation messages that your application is going to use depending on the language that is requested.&lt;/p&gt;


	&lt;h3&gt;Convert pofiles to mofiles&lt;/h3&gt;


	&lt;p&gt;After creating pofiles, you need to convert them to mofiles.
If you haven&amp;#8217;t yet, please read the the &lt;a href="http://www.gnu.org/software/gettext/manual/html_node/gettext_5.html#SEC5"&gt;GNU Gettext manual with the explanation of what mo and po stands for&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Add the code below to Rakefile:&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/Rakefile
require 'gettext/utils'
desc "Create mo-files for L10n" 
task :makemo do
 GetText.create_mofiles(true, "po", "locale")
end&lt;/pre&gt;

	&lt;p&gt;Then,&lt;/p&gt;


&lt;pre&gt;$ rake makemo&lt;/pre&gt;

	&lt;p&gt;It will create locale directories and subdirectroies such as:&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/locale:
$ d -T
/home/simplepages/rails/locale/:
 |-de_DE/:
 |   `-LC_MESSAGES/:
 |       |-myapp.mo
 |-en_GB/:
 |   `-LC_MESSAGES/:
 |       |-myapp.mo
 |-en_US/:
 |   `-LC_MESSAGES/:
 |       |-myapp.mo
 |-fr_FR/:
 |   `-LC_MESSAGES/:
 |       |-myapp.mo
 |-fr_CH/:
 |   `-LC_MESSAGES/:
 |       |-myapp.mo
 `-ja/:
     `-LC_MESSAGES/:
         |-myapp.mo&lt;/pre&gt;

	&lt;p&gt;These files are used by Ruby-GetText. You don&amp;#8217;t need to touch these files.&lt;/p&gt;


	&lt;h2&gt;Tools of trade&lt;/h2&gt;


	&lt;h3&gt;Gettext&lt;/h3&gt;


	&lt;p&gt;You will need to install Gettext. On Debian I would do &lt;code&gt;apt-get install gettext&lt;/code&gt; to do that. It contains a couple of tools that will be handy later on, most importantly &lt;code&gt;msgmerge&lt;/code&gt; which can merge different po files so updating your message files will be a snap and &lt;code&gt;msginit&lt;/code&gt;which can set default values to the header of pofile in your locale.&lt;/p&gt;


	&lt;h3&gt;Ruby-GetText and rgettext&lt;/h3&gt;


	&lt;p&gt;After you have installed Ruby-GetText and tools you should able to call &lt;code&gt;rgettext&lt;/code&gt; on the command line. rgettext is a replacement for &lt;code&gt;xgettext&lt;/code&gt; which comes with the main Gettext application. Beyond &lt;code&gt;xgettext&lt;/code&gt;, &lt;code&gt;rgettext&lt;/code&gt; supports not only ruby scripts(.rb) but also &lt;span class="caps"&gt;ERB&lt;/span&gt; files (.rhtml), ActiveRecord(.rb) directly.&lt;/p&gt;


h4. ActiveRecord support
&lt;code&gt;rgettext&lt;/code&gt; extracts all the table names and field names within subclasses of ActiveRecord::Base.

	&lt;p&gt;Notice: You need to run your database server and configure the config/database.xml correctly before executing &lt;code&gt;rgettext&lt;/code&gt;.&lt;/p&gt;


	&lt;h3&gt;poEdit&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://www.poedit.net"&gt;poEdit&lt;/a&gt; is a great tool to manage and edit your translations. It gives you a nice graphical frontend to translate all your messages. It is available for many different platforms. A nice side effect about using an easy to use &lt;span class="caps"&gt;GUI&lt;/span&gt; tool is that you can tell non-programmers to install it, open the po file and just start translating. They might have nothing to do with the coding in your project but will be able to help you translate your software. So if your grandma can translate English to Chinese she can maybe help you with your software project :)&lt;/p&gt;


	&lt;h2&gt;Collecting messages&lt;/h2&gt;


	&lt;p&gt;Add the code below to Rakefile:&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/Rakefile
desc "Update pot/po files to match new version." 
task :updatepo do
 MY_APP_TEXT_DOMAIN = "myapp" 
 MY_APP_VERSION     = "myapp 1.1.0" 
 GetText.update_pofiles(YOUR_APP_TEXT_DOMAIN,
                        Dir.glob("{app,lib}/**/*.{rb,rhtml}"),
                        MY_APP_VERSION)
end&lt;/pre&gt;

	&lt;p&gt;Running this task will either create or update your &lt;code&gt;po/myapp.pot&lt;/code&gt; and &lt;code&gt;po/*/myapp.po&lt;/code&gt; files in the relevant directories. It will go through all the important directories of your rails app and harvest all the Gettext strings in files ending in *.rb, *.rhtml.&lt;/p&gt;


&lt;pre&gt;$ rake updatepo&lt;/pre&gt;

	&lt;h3&gt;Translating and compiling with and without poEdit&lt;/h3&gt;


	&lt;p&gt;After you have successfully harvested your files you should have a &lt;code&gt;myapp.po&lt;/code&gt; file in every locale dir. Now you need to translate them. Since the &lt;code&gt;myapp.po&lt;/code&gt; files are mere text files you could just use your favourite text editors to translate them. Given that your text editor can edit in &lt;span class="caps"&gt;UTF&lt;/span&gt;-8 mode and you know the escaping rules of Gettext this is all you actually need. Open the file, translate the text and save it. After you have saved the file compile it. Gettext doesn&amp;#8217;t work with the text files (&lt;code&gt;myapp.po&lt;/code&gt;) directly. It wants a compiled version of it (&lt;code&gt;myapp.mo&lt;/code&gt;). Use the &lt;code&gt;rake makemo&lt;/code&gt; command to compile:&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/po/de_DE:
$ ls
myapp.po

simplepages@colinux: /home/simplepages/rails:
$ rake makemo

simplepages@colinux: /home/simplepages/rails/locale/de_DE/LC_MESSAGES:
$ ls
myapp.mo&lt;/pre&gt;

	&lt;p&gt;However, it is way more comfortable to use an application like poEdit for this. With poEdit you can also easily open up the &lt;code&gt;myapp.po&lt;/code&gt; file. It will give you a nice side by side view your original strings and the translated version, telling what is already translated and what is not. You click on a message and start translating it in a special field. Hit the save button and poEdit will automatically compile the &lt;code&gt;myapp.mo&lt;/code&gt; file for you (check the preferences if it doesn&amp;#8217;t do it by default). That&amp;#8217;s it. With a compiled &lt;code&gt;myapp.mo&lt;/code&gt; you can start to teach your rails app how to translate your user interface.&lt;/p&gt;


	&lt;p&gt;See &lt;a href="http://ponx.s5.xrea.com/hiki/ruby-gettext-translate.html"&gt;Documents for Translators&lt;/a&gt; for more details to translate the po-file.&lt;/p&gt;


	&lt;p&gt;When creating a po file it is useful to include header information at the top of the po file. This adds useful information such as character set, last translator etc. If you are not using poEdit add something similar to the top of the po file.&lt;/p&gt;


&lt;pre&gt;
msgid "" 
msgstr "" 
"POT-Creation-Date: 2007-02-19 17:15-0000\n" 
"PO-Revision-Date: 2003-04-03 10:49--500\n" 
"Last-Translator: Alastair Brunton &amp;lt;alastair@brunton.com&amp;gt;\n" 
"Language-Team: fr_FR &amp;lt;langteam@langteam.com&amp;gt;\n" 
"MIME-Version: 1.0\n" 
"Content-Type: text/plain; charset=UTF-8\n" 
"Content-Transfer-Encoding: 8bit\n" 
&lt;/pre&gt;

	&lt;h2&gt;Implementing Ruby-GetText into your rails app&lt;/h2&gt;


	&lt;p&gt;By now you should have a translated and compiled &lt;code&gt;myapp.mo&lt;/code&gt; in your locale dir. For example my German translation of SimplePages is at &lt;code&gt;$RAILS_ROOT/locale/de_DE/LC_MESSAGES/myapp.mo&lt;/code&gt;.&lt;/p&gt;


	&lt;h3&gt;Including Ruby-GetText&lt;/h3&gt;


	&lt;p&gt;Edit application.rb to bind textdomain to your application.&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/app/controllers/application.rb:
require 'gettext/rails'

class ApplicationController &amp;lt; ActionController::Base
 init_gettext "myapp" 
 #init_gettext "myapp", "UTF-8", "text/html" # &amp;lt;= Also you can set charset and content_type.
end&lt;/pre&gt;

	&lt;p&gt;In this sample, the textdomain name is &amp;#8220;myapp&amp;#8221;. Replace it as you like to fit your application. Maybe you want to have different textdomains for your site and the admin section.&lt;/p&gt;


	&lt;h3&gt;Selecting the scope of your textdomain&lt;/h3&gt;


	&lt;ol&gt;
	&lt;li&gt;If you call &lt;code&gt;bindtextdomain&lt;/code&gt; in ApplicationControler, the textdomain applies to the entire application.&lt;/li&gt;
		&lt;li&gt;If you call &lt;code&gt;bindtextdomain&lt;/code&gt; in any other controller with a different textdomain, this textdomain only applies to this specific controller. For example if you call a different textdomain in &lt;code&gt;myapp_controller.rb&lt;/code&gt; it will only be used in &lt;code&gt;myapp_controller.rb&lt;/code&gt;.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;The textdomains are applied to each controller/view/model.&lt;/p&gt;


	&lt;h3&gt;Choosing the right language on every request&lt;/h3&gt;


	&lt;p&gt;Since we are developing a web application we want to be able to choose the current language by request. Additionally we might want to offer the user the possibilty to choose the language from a menu.&lt;/p&gt;


	&lt;p&gt;Ruby-GetText chooses the current language by following these rules in the given order:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;the first value passed to the &amp;#8216;locale&amp;#8217; parameter of GetText.bindtextdomain method call&lt;/li&gt;
		&lt;li&gt;&amp;#8216;lang&amp;#8217; value of &lt;code&gt;QUERY_STRING&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;&amp;#8216;lang&amp;#8217; value of the Cookie&lt;/li&gt;
		&lt;li&gt;the value of &lt;code&gt;HTTP_ACCEPT_LANGUAGE&lt;/code&gt;&lt;/li&gt;
		&lt;li&gt;or default &amp;#8216;en&amp;#8217; (English).&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;The script &lt;code&gt;$RUBYGETTEXT_RAILS_SAMPLE/vendor/plugins/lang_helper.rb&lt;/code&gt; is a sample that selects locale using the cookie value of the user.&lt;/p&gt;


	&lt;p&gt;It may be useful to implement a simple controller action to change between languages eg.&lt;/p&gt;


&lt;pre&gt;
class CookieController &amp;lt; ApplicationController
 def set_cookie
   code = params[:id]
   cookies[:lang] =
     {
      :value =&amp;gt; code,
      :expires =&amp;gt; Time.now + 1.year,
      :path =&amp;gt; '/'
     }
   redirect_to home_url
 end
end
&lt;/pre&gt;

	&lt;p&gt;So &lt;code&gt;/cookie/set_cookie/fr_FR&lt;/code&gt; would change the language to French.&lt;/p&gt;


	&lt;h3&gt;Using the Locale in your templates&lt;/h3&gt;


	&lt;p&gt;Depending on the selected locale you will want to customize the language and character set in your templates.&lt;/p&gt;


	&lt;p&gt;File: &lt;code&gt;$RAILS_ROOT/app/view/layouts/main.rhtml&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="&amp;lt;%= Locale.get %&amp;gt;" lang="&amp;lt;%= Locale.get %&amp;gt;"&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;&amp;lt;%= @page["title"] %&amp;gt;&amp;lt;/title&amp;gt;
&amp;lt;meta http-equiv="content-type" content="text/html; charset=&amp;lt;%= Locale.charset %&amp;gt;" /&amp;gt;
...
&lt;/pre&gt;

	&lt;h3&gt;Have your own textdomain for plugin applications&lt;/h3&gt;


	&lt;p&gt;If you are a plugin developer and want to have your own textdomain, you need to separate the Class/Module from ActionView::Base/ApplicationController.&lt;/p&gt;


&lt;pre&gt;simplepages@colinux: /home/simplepages/rails/vendor/plugins/gettext/lib/gettext_plugin.rb:
require 'gettext/rails'

module LangHelper
 # If you need to bind yet another textdomain to your plugin.
 # Separate the name space from ActionView::Base/ApplicationController.
 class YetanotherTextDomain
   include GetText::Rails

   def initialize
     # You need to call bindtextdomain in an instance of ActionView::Base.
     # The locale is used a same values which define ApplicationController#init_gettext instead of
     # the textdomain.
     bindtextdomain("gettext_plugin")
   end

   def show_language(actionview)
     langs = ["en"] + Dir.glob(File.join(RAILS_ROOT,"locale/*")).collect{|item| File.basename(item)}
     langs.delete("CVS")
     langs.uniq!
     ret = "&amp;lt;h4&amp;gt;" + _("Select locale") + "&amp;lt;/h4&amp;gt;" 
     langs.sort.each do |lang|
       ret &amp;lt;&amp;lt; actionview.link_to("[#{lang}]", :action =&amp;gt; "cookie_locale", :lang =&amp;gt; lang)
     end
     ret
   end

   def cookie_locale(cookies, flash, params)
     cookies["lang"] = params["lang"]
     flash[:notice] = _('Cookie &amp;amp;quot;lang&amp;amp;quot; is set: %s') % params["lang"]
   end
 end

 # This function shows supported languages with link to set cookie
 # action (cookie_locale).
 def show_language
   YetanotherTextDomain.new.show_language(self)
 end

 # This function is called when the language link is set.
 def cookie_locale
   YetanotherTextDomain.new.cookie_locale(cookies, flash, params)
   redirect_to :action =&amp;gt; 'list'
 end
end&lt;/pre&gt;

	&lt;p&gt;Simply put &lt;code&gt;gettext_plugin.po&lt;/code&gt; into the po directory.&lt;/p&gt;


	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;That&amp;#8217;s it. If you have your translated message catalogs (&lt;code&gt;myapp.mo&lt;/code&gt;) in all the right places your application should show your message strings in your favourite language.&lt;/p&gt;


	&lt;p&gt;You can now easily start to translate your application into all the different languages you want. I hope this guide helps you to get started. There are certainly many more aspects of internationalization that you will have to learn and apply. Remember that this is only one of many possible ways to do it. If you find any mistakes, shortcomings or have good suggestions on how to improve this guide I would be more than happy to hear from you.&lt;/p&gt;


	&lt;p&gt;If you want you can download the &lt;a href="http://www.digitale-wertschoepfung.de/artikel/gettext/gettext.txt"&gt;original Textile document&lt;/a&gt;, make modifications and send them back to me. I will be sure to include you in the credits section.&lt;/p&gt;


	&lt;p&gt;Sascha Ebach
&lt;a href="mailto:se&amp;nbsp;at&amp;nbsp;digitale-wertschoepfung&amp;nbsp;dot&amp;nbsp;de"&gt;se at digitale-wertschoepfung dot de&lt;/a&gt;&lt;/p&gt;


	&lt;h3&gt;Credits&lt;/h3&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.loudthinking.com"&gt;David Heinemeier Hansson&lt;/a&gt; for creating the best web application framework that has ever existed P-E-R-I-O-D&lt;/li&gt;
		&lt;li&gt;Masao Mutoh &amp;#8211; The Author of Ruby-GetText: &lt;a href="mailto:mutoh&amp;nbsp;at&amp;nbsp;highway&amp;nbsp;dot&amp;nbsp;ne&amp;nbsp;dot&amp;nbsp;jp"&gt;mutoh at highway dot ne dot jp&lt;/a&gt;. Thanks to Masao for extending the old version and making it more flexible.&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.simplyexcited.co.uk"&gt;Alastair Brunton&lt;/a&gt; for providing some sorely needed modifications to this article.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Author&lt;/h3&gt;


	&lt;p&gt;Sascha Ebach is the owner and lead developer of a small &lt;a href="http://www.digitale-wertschoepfung.de"&gt;web design and development shop&lt;/a&gt; &lt;a href="http://www.digitale-wertschoepfung.de"&gt;Digitale Wertsch&amp;ouml;pfung&lt;/a&gt; in Cologne, Germany. Together with his two partners he develops and designs complete online solutions for small to medium sized businesses. Up until the surfacing of Rails he used to develop everything in &lt;span class="caps"&gt;PHP&lt;/span&gt; although he has already fallen deeply in love with Ruby since version 1.6.2 came out. For him it is very clear that Rails and Ruby will be &lt;strong&gt;The Future Way&lt;/strong&gt; of developing web applications and he already looks forward to the day when he has ported his last line of &lt;span class="caps"&gt;PHP&lt;/span&gt; to Ruby.&lt;/p&gt;


	&lt;h2&gt;Appendix A: Downloads&lt;/h2&gt;


	&lt;h3&gt;Used files&lt;/h3&gt;


	&lt;p&gt;Download the archive with files and scripts I use and talk about in this guide. The file includes the complete skeleton of files that you need to get started.&lt;/p&gt;


&lt;pre&gt;/home/simplepages/using-gettext-with-rails/:
 |-app/:
 |   `-controllers/:
 |       `-application.rb (the ApplicationController with the .init_gettext method)
 `-po/: (sample directory structure)
     |-de_DE/:
     |-en_GB/:
     `-en_US/:
&lt;/pre&gt;

	&lt;p&gt;&lt;a href="http://www.digitale-wertschoepfung.de/artikel/gettext/using-gettext-with-rails.tgz"&gt;Download using-gettext-with-rails.tgz&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Chris Carter</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-724</id>
    <issued>2006-07-19T04:28:07+00:00</issued>
    <modified>2006-07-19T04:28:07+00:00</modified>
    <title>Chris Carter: The 4 Hashes of the Apocolypse</title>
    <link href="http://127.0.0.1:15101/read/chapter/28#page233" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;After the request has been made by using one of the 5 methods (get, post, etc&amp;#8230;), you
will have 4 Hash objects ready for use.&lt;/p&gt;


	&lt;p&gt;They are (starring in alphabetical order):&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;assigns : any objects that are stored as instance variables in actions for use in views&lt;/li&gt;
		&lt;li&gt;cookies : any objects cookies that are set&lt;/li&gt;
		&lt;li&gt;flash : any objects living in the flash&lt;/li&gt;
		&lt;li&gt;session : any object living in session variables&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;For example, let&amp;#8217;s say we have a &lt;strong&gt;MoviesController&lt;/strong&gt; with an action called &lt;strong&gt;movie&lt;/strong&gt;.
The code for that action might look something like:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;def movie
  @movie = Movie.find(params[:id])
  if @movie.nil?
    flash['message'] = "That movie has been burned." 
    redirect_to :controller =&amp;gt; 'error', :action =&amp;gt; 'missing'
  end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now, to test out if the proper movie is being set, we could have a series of tests that
look like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;# this test proves that fetching a movie works
def test_successfully_finding_a_movie
  get :movie, "id" =&amp;gt; "1" 
  assert_not_nil assigns["movie"]
  assert_equal 1, assigns["movie"].id
  assert flash.empty?
end

# and when we can't find a movie...
def test_movie_not_found
  get :movie, "id" =&amp;gt; "666999" 
  assert_nil assigns["movie"]
  assert flash.has_key?("message")
  assert assigns.empty?
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;As is the case with normal Hash objects, you can access the values by referencing the keys 
by string.  You can also reference them by symbol name&amp;#8230; &lt;strong&gt;except assigns&lt;/strong&gt;.  Check it out:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;flash["gordon"]  flash[:gordon]
session["shmession"]  session[:shmession]
cookies[&amp;#8220;are_good_for_u&amp;#8221;]  cookies[:are_good_for_u]

assigns["something"]  assigns(:something) # because you can&amp;#8217;t use assigns[:something] for historical reasons
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Keep an eye out for that. mmmm kay?&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Chris Carter</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-723</id>
    <issued>2006-07-19T04:26:53+00:00</issued>
    <modified>2006-07-19T04:26:53+00:00</modified>
    <title>Chris Carter: An Anatomy Lesson</title>
    <link href="http://127.0.0.1:15101/read/chapter/28#page72" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;So let&amp;#8217;s take a look at an example of a functional test.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/../test_helper'

# grab our HomeController because we're going to test it
require 'home_controller'

# Raise errors beyond the default web-based presentation
class HomeController; def rescue_action(e) raise e end; end

class HomeControllerTest &amp;lt; Test::Unit::TestCase
  def setup
    @controller = HomeController.new
    @request = ActionController::TestRequest.new
    @response = ActionController::TestResponse.new
  end

  # let's test our main index page
  def test_index
    get :index
    assert_response :success
  end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;The big three&lt;/h3&gt;


	&lt;p&gt;In the setup method, we create 3 objects:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;One of your controllers to be tested (aka. &lt;strong&gt;@controller&lt;/strong&gt;)&lt;/li&gt;
		&lt;li&gt;A &lt;strong&gt;TestRequest&lt;/strong&gt; to simulate a web request (aka. &lt;strong&gt;@request&lt;/strong&gt;)&lt;/li&gt;
		&lt;li&gt;A &lt;strong&gt;TestResponse&lt;/strong&gt; to provide information about the test request (aka. &lt;strong&gt;@response&lt;/strong&gt;)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;99% if not 100% of your functional tests will have these 3 objects in the setup.&lt;/p&gt;


	&lt;h3&gt;Making the moves&lt;/h3&gt;


	&lt;p&gt;In the one test we have called &lt;strong&gt;test_index&lt;/strong&gt;, we are simulating a request on the action called index and making sure the request was successful.&lt;/p&gt;


	&lt;p&gt;The get method kicks off the web request and populates the results into the response.  &lt;strong&gt;get&lt;/strong&gt; method accepts 4 arguments.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The action of the controller you are requesting.  It can be in the form of a string or a symbol.  Cool people use symbols. ;)&lt;/li&gt;
		&lt;li&gt;An optional hash of request parameters to pass into the action (eg. query string parameters or post variables).  &lt;/li&gt;
		&lt;li&gt;An optional hash of session variables to pass along with the request.  &lt;/li&gt;
		&lt;li&gt;An optional hash of flash to stash your goulash.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Example: Calling the &lt;code&gt;:show&lt;/code&gt; action, passing an &lt;code&gt;id&lt;/code&gt; of 12 as the &lt;code&gt;params&lt;/code&gt; and setting &lt;code&gt;user_id&lt;/code&gt; of 5 in the session.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;get :show, {'id' =&amp;gt; "12"}, {'user_id' =&amp;gt; 5}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Another Example: Calling the &lt;code&gt;:view&lt;/code&gt; action, passing an &lt;code&gt;id&lt;/code&gt; of 12 as the &lt;code&gt;params&lt;/code&gt;, this time with &lt;strong&gt;no&lt;/strong&gt; session, but with a flash message.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;get :view, {'id' =&amp;gt; '12'}, nil, {'message' =&amp;gt; 'booya!'}&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Available at your disposal&lt;/h3&gt;


	&lt;p&gt;For those of you familiar with &lt;span class="caps"&gt;HTTP&lt;/span&gt; protocol, you&amp;#8217;ll know that get is a type of request.  There are 5 request types supported in Rails:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;get&lt;/li&gt;
		&lt;li&gt;post&lt;/li&gt;
		&lt;li&gt;put&lt;/li&gt;
		&lt;li&gt;head&lt;/li&gt;
		&lt;li&gt;delete&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;All of request types are methods that you can use, however, you&amp;#8217;ll probably end up using the first two more ofter than the others.&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Chris Carter</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-722</id>
    <issued>2006-07-19T04:25:39+00:00</issued>
    <modified>2006-07-19T04:25:39+00:00</modified>
    <title>Chris Carter: An Anatomy Lesson</title>
    <link href="http://127.0.0.1:15101/read/chapter/28#page72" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;So let&amp;#8217;s take a look at an example of a functional test.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/../test_helper'

# grab our HomeController because we're going to test it
require 'home_controller'

# Raise errors beyond the default web-based presentation
class HomeController; def rescue_action(e) raise e end; end

class HomeControllerTest &amp;lt; Test::Unit::TestCase
  def setup
    @controller = HomeController.new
    @request = ActionController::TestRequest.new
    @response = ActionController::TestResponse.new
  end

  # let's test our main index page
  def test_index
    get :index
    assert_response :success
  end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;The big three&lt;/h3&gt;


	&lt;p&gt;In the setup method, we create 3 objects:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;One of your controllers to be tested (aka. &lt;strong&gt;@controller&lt;/strong&gt;)&lt;/li&gt;
		&lt;li&gt;A &lt;strong&gt;TestRequest&lt;/strong&gt; to simulate a web request (aka. &lt;strong&gt;@request&lt;/strong&gt;)&lt;/li&gt;
		&lt;li&gt;A &lt;strong&gt;TestResponse&lt;/strong&gt; to provide information about the test request (aka. &lt;strong&gt;@response&lt;/strong&gt;)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;99% if not 100% of your functional tests will have these 3 objects in the setup.&lt;/p&gt;


	&lt;h3&gt;Making the moves&lt;/h3&gt;


	&lt;p&gt;In the one test we have called &lt;strong&gt;test_index&lt;/strong&gt;, we are simulating a request on the action called index and making sure the request was successful.&lt;/p&gt;


	&lt;p&gt;The get method kicks off the web request and populates the results into the response.  &lt;strong&gt;get&lt;/strong&gt; method accepts 4 arguments.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The action of the controller you are requesting.  It can be in the form of a string or a symbol.  Cool people use symbols. ;)&lt;/li&gt;
		&lt;li&gt;An optional hash of request parameters to pass into the action (eg. query string parameters or post variables).  &lt;/li&gt;
		&lt;li&gt;An optional hash of session variables to pass along with the request.  &lt;/li&gt;
		&lt;li&gt;An optional hash of flash to stash your goulash.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Example: Calling the &lt;code&gt;:show&lt;/code&gt; action, passing an &lt;code&gt;id&lt;/code&gt; of 12 as the &lt;code&gt;@params&lt;/code&gt; and setting &lt;code&gt;user_id&lt;/code&gt; of 5 in the session.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;get :show, {'id' =&amp;gt; "12"}, {'user_id' =&amp;gt; 5}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Another Example: Calling the &lt;code&gt;:view&lt;/code&gt; action, passing an &lt;code&gt;id&lt;/code&gt; of 12 as the &lt;code&gt;params&lt;/code&gt;, this time with &lt;strong&gt;no&lt;/strong&gt; session, but with a flash message.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;get :view, {'id' =&amp;gt; '12'}, nil, {'message' =&amp;gt; 'booya!'}&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;Available at your disposal&lt;/h3&gt;


	&lt;p&gt;For those of you familiar with &lt;span class="caps"&gt;HTTP&lt;/span&gt; protocol, you&amp;#8217;ll know that get is a type of request.  There are 5 request types supported in Rails:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;get&lt;/li&gt;
		&lt;li&gt;post&lt;/li&gt;
		&lt;li&gt;put&lt;/li&gt;
		&lt;li&gt;head&lt;/li&gt;
		&lt;li&gt;delete&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;All of request types are methods that you can use, however, you&amp;#8217;ll probably end up using the first two more ofter than the others.&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Chris Carter</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-721</id>
    <issued>2006-07-19T04:22:44+00:00</issued>
    <modified>2006-07-19T04:22:44+00:00</modified>
    <title>Chris Carter: Fixtures in Action</title>
    <link href="http://127.0.0.1:15101/read/chapter/26#page68" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Rails makes no assumptions when it comes to fixtures.  You must explicitly load them yourself by using the fixtures method within your TestCase.  For example, a users model unit test might look like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;# allow this test to hook into the Rails framework
require File.dirname(__FILE__) + '/../test_helper'

# we're testing a User, so we need to include it
require 'user'

class UserTest &amp;lt; Test::Unit::TestCase

  fixtures :users

  # count the fixtures
  def test_count_my_fixtures
    assert_equal 5, User.count
  end

end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Using the fixtures method and placing the symbol name of the model, Rails will automatically load up the fixtures for you at the start of each test method.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;fixtures :users
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;What exactly does this line of code do?  It does 3 things:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;it nukes any existing data living in the users table&lt;/li&gt;
		&lt;li&gt;it loads the fixture data (if any) into the users table&lt;/li&gt;
		&lt;li&gt;it dumps the data into a variable in case you want to access it directly&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So, in the above example, if we had another test method, we wouldn&amp;#8217;t have 10 users on the 2nd test because they would be wiped out before being created.&lt;/p&gt;


	&lt;p&gt;You can load multiple fixtures by including them on the same line separated by commas.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;fixtures :users, :losers, :bruisers, :cruisers
&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Chris Carter</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-720</id>
    <issued>2006-07-19T04:21:07+00:00</issued>
    <modified>2006-07-19T04:21:07+00:00</modified>
    <title>Chris Carter: Hashes with Special Powers</title>
    <link href="http://127.0.0.1:15101/read/chapter/26#page69" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Fixtures are basically Hash objects.  As mentioned in point #3 above, you can access the hash object directly because it is automatically setup as a local variable of the test case.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;...
  fixtures :users

  def test_user
    # this will return the Hash for the fixture named david
    users(:david)

    # this will return the property for david called id
    users(:david).id
  end
...
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;But, by there&amp;#8217;s another side to fixtures&amp;#8230; at night, if the moon is full and the wind completely still, fixtures can also transform themselves into the form of the original class!&lt;/p&gt;


	&lt;p&gt;Now you can get at the methods only available to that class.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;...
  fixtures :users

  def test_user
    # using the find method, we grab the "real" david as a User
    david = users(:david).find

    # an now we have access to methods only available to a User class
    email( david.girlfriend.email, david.illegitimate_children )
  end
...
&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <author>
      <name>rabble</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-719</id>
    <issued>2006-04-20T01:31:37+00:00</issued>
    <modified>2006-04-20T01:31:37+00:00</modified>
    <title>rabble: Response-Related Assertions</title>
    <link href="http://127.0.0.1:15101/read/chapter/28#page234" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;There are 3 assertions that deal with the overall response to a request.  They are:&lt;/p&gt;


	&lt;h4&gt;assert_template &lt;code&gt;( expected_template, [msg] )&lt;/code&gt;&lt;/h4&gt;


	&lt;p&gt;Ensures the expected template was responsible for rendering.  For example:&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;assert_template "user/profile" 
&lt;/pre&gt;&lt;/code&gt;

	&lt;p&gt;This code will fail unless the template located at &lt;code&gt;app/views/user/profile.rhtml&lt;/code&gt; was rendered.&lt;/p&gt;


	&lt;h4&gt;assert_response &lt;code&gt;( type_or_code, [msg] )&lt;/code&gt;&lt;/h4&gt;


	&lt;p&gt;Ensures the response type/status code is as expected.  The possible options are:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;:success (status code is 200)&lt;/li&gt;
		&lt;li&gt;:redirect (status code is within 300..399)&lt;/li&gt;
		&lt;li&gt;:missing (status code is 404)&lt;/li&gt;
		&lt;li&gt;:error (status code is within 500..599)&lt;/li&gt;
		&lt;li&gt;any number (to specifically reference a particular status code)&lt;/li&gt;
	&lt;/ul&gt;


&lt;code&gt;&lt;pre&gt;assert_response :success      # page rendered ok
assert_response :redirect     # we've been redirected
assert_response :missing      # not found
assert_response 505           # status code was 505
&lt;/pre&gt;&lt;/code&gt;

	&lt;h4&gt;assert_redirected_to &lt;code&gt;( options={}, [msg] )&lt;/code&gt;&lt;/h4&gt;


	&lt;p&gt;Ensures we&amp;#8217;ve been redirected to a specific place within our application.&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;assert_redirected_to :controller =&amp;gt; 'widget', :action =&amp;gt; 'view', :id =&amp;gt; 555
&lt;/pre&gt;&lt;/code&gt;</content>
  </entry>
  <entry>
    <author>
      <name>rabble</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-718</id>
    <issued>2006-04-20T01:31:24+00:00</issued>
    <modified>2006-04-20T01:31:24+00:00</modified>
    <title>rabble: Response-Related Assertions</title>
    <link href="http://127.0.0.1:15101/read/chapter/28#page234" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;There are 3 assertions that deal with the overall response to a request.  They are:&lt;/p&gt;


	&lt;h4&gt;assert_template &lt;code&gt;( expected_template, [msg] )&lt;/code&gt;&lt;/h4&gt;


	&lt;p&gt;Ensures the expected template was responsible for rendering.  For example:&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;assert_template "user/profile" 
&lt;/pre&gt;&lt;/code&gt;

	&lt;p&gt;This code will fail unless the template located at &lt;code&gt;app/views/user/profile.rhtml&lt;/code&gt; was rendered.&lt;/p&gt;


	&lt;h4&gt;assert_response &lt;code&gt;( type_or_code, [msg] )&lt;/code&gt;&lt;/h4&gt;


	&lt;p&gt;Ensures the response type/status code is as expected.  The possible options are:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;:success (status code is 200)&lt;/li&gt;
		&lt;li&gt;:redirect (status code is within 300..399)&lt;/li&gt;
		&lt;li&gt;:missing (status code is 404)&lt;/li&gt;
		&lt;li&gt;:error (status code is within 500..599)&lt;/li&gt;
		&lt;li&gt;any number (to specifically reference a particular status code)&lt;/li&gt;
	&lt;/ul&gt;


&lt;code&gt;&lt;pre&gt;assert_response :success      # page rendered ok
assert_response :redirect     # we've been redirected
assert_response :missing      # not found
assert_response 505           # status code was 505
&lt;/pre&gt;&lt;/code&gt;

	&lt;h4&gt;assert_redirected_to &lt;code&gt;( options={}, [msg] )&lt;/code&gt;&lt;/h4&gt;


	&lt;p&gt;Ensures we&amp;#8217;ve been redirected to a specific place within our application.&lt;/p&gt;


&lt;code&gt;&lt;pre&gt;assert_redirectd_to :controller =&amp;gt; 'widget', :action =&amp;gt; 'view', :id =&amp;gt; 555
&lt;/pre&gt;&lt;/code&gt;</content>
  </entry>
  <entry>
    <author>
      <name>rabble</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-717</id>
    <issued>2006-04-04T22:48:07+00:00</issued>
    <modified>2006-04-04T22:48:07+00:00</modified>
    <title>rabble: The Assertion Lineup</title>
    <link href="http://127.0.0.1:15101/read/chapter/24#page58" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;By now you&amp;#8217;ve caught a glimpse of some of the assertions that are available.  Assertions are the worker bees of testing.  They are the ones that actually perform the checks to ensure things are going as planned.&lt;/p&gt;


	&lt;p&gt;There are a bunch of different types of assertions you can use.  Here&amp;#8217;s the complete list of assertions that ship with test/unit.  The &lt;strong&gt;[msg]&lt;/strong&gt; is an optional string message you can specify to make your test failure messages clearer.  It&amp;#8217;s not required.&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert* ( boolean, [msg] )&lt;/code&gt; ... ensures the object/expression is true&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_equal* ( obj1, obj2, [msg] )&lt;/code&gt; ... ensures obj1  obj2 is true

@*assert_not_equal* ( obj1, obj2, [msg] )@ ... ensures obj1  obj2 is false&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_same* ( obj1, obj2, [msg] )&lt;/code&gt; ... ensures obj1.equal?(obj2) is true&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_not_same* ( obj1, obj2, [msg] )&lt;/code&gt; ... ensures 
obj1.equal?(obj2) is false&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_nil* ( obj, [msg] )&lt;/code&gt; ... ensures obj.nil? is true&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_not_nil* ( obj, [msg] )&lt;/code&gt; ... ensures obj.nil? is false&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_match* ( regexp, string, [msg] )&lt;/code&gt; ... ensures a string matches the regular expression&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_no_match* ( regexp, string, [msg] )&lt;/code&gt; ... ensures a string doesn&amp;#8217;t matches the regular expression&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_in_delta* ( expecting, actual, delta, [msg] )&lt;/code&gt; ... ensures the numbers expecting and actual are within delta of each other&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_throws* ( symbol, [msg] ){ block }&lt;/code&gt; ... ensures a block throws the symbol&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_raises* ( exceptions ){ block }&lt;/code&gt; ... ensures a block raises one of the comma-separated exceptions&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_nothing_raised* ( exceptions ){ block }&lt;/code&gt; ... a block doesn&amp;#8217;t raise one of the comma-separated exceptions&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_instance_of* ( class, obj, [msg] )&lt;/code&gt; ... ensures obj is the class type&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_kind_of* ( class, obj, [msg] )&lt;/code&gt; ... ensures obj is or descends from class&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_respond_to* ( obj, symbol, [msg] )&lt;/code&gt; ... ensures obj has a method called symbol&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_operator* ( obj1, operator, obj2, [msg] )&lt;/code&gt; ... ensures obj1.operator(obj2) is true&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*assert_send* ( array, [msg] )&lt;/code&gt; ... ensures that executing the method listed in array[ 1 ] on the object in array[ 0 ] with the parameters of array[ 2 and up ] is true.  This one is weird eh?&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;*flunk* ( [msg] )&lt;/code&gt; ...  ensures failure&amp;#8230; like me and high school chemistry exams.&lt;/p&gt;


	&lt;p&gt;Because of the modular nature of the testing framework, it is possible to create your own assertions.  In fact, that&amp;#8217;s exactly what Rails does.  It has some specialized assertions to make your life easier.&lt;/p&gt;


	&lt;p&gt;Creating your own assertions is more of an advanced topic we won&amp;#8217;t cover in this tutorial.&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Jamis Buck</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-716</id>
    <issued>2006-03-15T14:55:19+00:00</issued>
    <modified>2006-03-15T14:55:19+00:00</modified>
    <title>Jamis Buck: Deploying</title>
    <link href="http://127.0.0.1:15101/read/chapter/100#page271" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;The first deployment is a bit tricky with this setup, because you have to do some bootstrapping. The spinner isn&amp;#8217;t running, and you have to &lt;em&gt;get&lt;/em&gt; it running. But we can&amp;#8217;t get it running until we&amp;#8217;ve deployed the application&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Not to worry. We&amp;#8217;ll just create a couple of custom tasks that will get everything set up for us:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Tasks for initial deployment [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;table border='0' cellpadding='0' cellspacing='0'&gt;&lt;tr&gt;&lt;td class='lineno'&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;8&lt;br /&gt;9&lt;br /&gt;10&lt;br /&gt;11&lt;br /&gt;12&lt;br /&gt;13&lt;br /&gt;14&lt;br /&gt;&lt;/td&gt;&lt;td width='100%'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;  &lt;span class="ident"&gt;desc&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Start the spinner daemon&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;task&lt;/span&gt; &lt;span class="symbol"&gt;:spinner&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:roles&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:app&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;run&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{current_path}&lt;/span&gt;/script/spin&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;desc&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Used only for deploying when the spinner isn't running&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;task&lt;/span&gt; &lt;span class="symbol"&gt;:cold_deploy&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;transaction&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;update_code&lt;/span&gt;
      &lt;span class="ident"&gt;symlink&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;spinner&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;The first task only applies to the app servers, and all it does is start the spinner by invoking our custom &lt;code&gt;spin&lt;/code&gt; script.&lt;/p&gt;


	&lt;p&gt;The second task is a more complicated one. It calls the &lt;code&gt;update_code&lt;/code&gt; and &lt;code&gt;symlink&lt;/code&gt; tasks in a &lt;em&gt;transaction&lt;/em&gt;. This means that if either of those tasks fails, they will be rolled back, leaving the system in a consistent state. Once those two tasks finish successfully (executing on all boxes), our new spinner task is invoked (which will only be executed on the app servers, remember).&lt;/p&gt;


	&lt;p&gt;Once that&amp;#8217;s all done, you just have to invoke the &lt;code&gt;cold_deploy&lt;/code&gt; task, and you&amp;#8217;re golden!&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Invoking cold_deploy [shell]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/shell.css' /&gt;&lt;div class='shell'&gt;&lt;pre&gt;  rake remote:exec ACTION=cold_deploy&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Once you&amp;#8217;ve got the spinner running, future deployments can simply use the default &lt;code&gt;deploy&lt;/code&gt; task:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Invoking deploy [shell]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/shell.css' /&gt;&lt;div class='shell'&gt;&lt;pre&gt;  rake deploy&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Jamis Buck</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-715</id>
    <issued>2006-03-15T14:55:03+00:00</issued>
    <modified>2006-03-15T14:55:03+00:00</modified>
    <title>Jamis Buck: Deployment Recipe</title>
    <link href="http://127.0.0.1:15101/read/chapter/100#page267" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;The first thing we need to do is revisit our deployment recipe. The roles, in particular need to be completely revisited, and we can also get rid of our custom &lt;code&gt;restart&lt;/code&gt; task. The complete &lt;code&gt;deploy.rb&lt;/code&gt; file looks like this:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Multi-server deployment recipe [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;table border='0' cellpadding='0' cellspacing='0'&gt;&lt;tr&gt;&lt;td class='lineno'&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;br /&gt;&lt;/td&gt;&lt;td width='100%'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;  &lt;span class="ident"&gt;set&lt;/span&gt; &lt;span class="symbol"&gt;:application&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;flipper&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;set&lt;/span&gt; &lt;span class="symbol"&gt;:repository&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;http://svn.capistrano.com/flipper/trunk&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

  &lt;span class="ident"&gt;role&lt;/span&gt; &lt;span class="symbol"&gt;:web&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;www1.capistrano.com&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;www2.capistrano.com&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;role&lt;/span&gt; &lt;span class="symbol"&gt;:app&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;app1.capistrano.com&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;app2.capistrano.com&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="ident"&gt;role&lt;/span&gt; &lt;span class="symbol"&gt;:db&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;db1.capistrano.com&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:primary&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
  &lt;span class="ident"&gt;role&lt;/span&gt; &lt;span class="symbol"&gt;:db&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt;  &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;db2.capistrano.com&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;We now have two servers (www1 and www2) in the &lt;code&gt;web&lt;/code&gt; role, and two servers (app1 and app2) in the &lt;code&gt;app&lt;/code&gt; role. Fairly self-explanatory.&lt;/p&gt;


	&lt;p&gt;Looking at the &lt;code&gt;db&lt;/code&gt; role, though, we have one server (db1) with the extra information &lt;code&gt;:primary =&amp;gt; true&lt;/code&gt;. This tells Capistrano that some tasks should be executed only on this server, and not on all db servers. (This is useful for things like migrations, where you only want them applied to the primary copy of the data. You could also add &lt;code&gt;:slave =&amp;gt; true&lt;/code&gt; to the db2 server and then define a backup task that only ran on the slave.)&lt;/p&gt;


	&lt;p&gt;We can now run the &lt;code&gt;setup&lt;/code&gt; task again to make sure our directories are all set up on all six machines. Just type:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Running setup [shell]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/shell.css' /&gt;&lt;div class='shell'&gt;&lt;pre&gt;  rake remote:exec ACTION=setup&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Jamis Buck</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-714</id>
    <issued>2006-03-15T14:54:26+00:00</issued>
    <modified>2006-03-15T14:54:26+00:00</modified>
    <title>Jamis Buck: Setup</title>
    <link href="http://127.0.0.1:15101/read/chapter/98#page263" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Okay, now that we&amp;#8217;ve got a basic deployment recipe going, we can try it out by executing the &lt;code&gt;setup&lt;/code&gt; task. This task will set up the basic deployment directory structure on our production box for us.&lt;/p&gt;


	&lt;p&gt;The deployment directory structure is:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Deployment directory structure [chart]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/chart.css' /&gt;&lt;div class='chart'&gt;&lt;pre&gt;[deploy_to]
  +- releases
  |    +- 20050725121411
  |    +- 20050801090107
  |    +- 20050802231414
  |    ...
  |    +- 20050824141402
  |    |   +- Rakefile
  |    |   |  app
  |    |   |  config
  |    |   |  db
  |    |   |  lib
  |    |   |  log --&amp;gt; [deploy_to]/shared/log
  |    |   |  public
  |    |   |    +- ...
  |    |   |       system --&amp;gt; [deploy_to]/shared/system
  |    |   |       ...
  |    |   |  script
  |    |   |  test
  |    |   |  vendor
  |
  +- shared
  |    +- log
  |    +- system
  |
  + current --&amp;gt; [deploy_to]/releases/20050824141402&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;The &lt;code&gt;[deploy_to]&lt;/code&gt; represents the root of your deployment path. By default, Capistrano uses &lt;code&gt;"/u/apps/#{application}"&lt;/code&gt; as the root of the deployment path, but you can specify whatever root you want via the &lt;code&gt;:deploy_to&lt;/code&gt; variable in your recipe file:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Custom deployment root [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;&lt;span class="ident"&gt;set&lt;/span&gt; &lt;span class="symbol"&gt;:deploy_to&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;/var/www/flipper&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Beneath the deployment root are two other directories, &lt;code&gt;releases&lt;/code&gt; and &lt;code&gt;shared&lt;/code&gt;. The &lt;code&gt;releases&lt;/code&gt; directory contains one subdirectory for every released version of your software. Each subdirectory is named for the time (in Universal Standard Time) at which it was deployed.&lt;/p&gt;


	&lt;p&gt;The &lt;code&gt;shared&lt;/code&gt; directory contains directories and files that should be shared between multiple releases, like log files and static system &lt;span class="caps"&gt;HTML&lt;/span&gt; files (like a &amp;#8220;down for maintenance page&amp;#8221;).&lt;/p&gt;


	&lt;p&gt;Finally, the deployment root contains a symlink called &lt;code&gt;current&lt;/code&gt; that points the current release.&lt;/p&gt;


	&lt;p&gt;It isn&amp;#8217;t necessary to build all these directories yourself. You can use the default &lt;code&gt;setup&lt;/code&gt; Capistrano task to do it for you. Just type the following:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Executing the setup task [shell]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/shell.css' /&gt;&lt;div class='shell'&gt;&lt;pre&gt;rake remote:exec ACTION=setup&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;This will prompt you for your server&amp;#8217;s password. (If you don&amp;#8217;t want the password to echo to the screen as you type it, be sure you have the &lt;code&gt;termios&lt;/code&gt; gem installed&amp;#8212;only guaranteed to work in *nix environments.)&lt;/p&gt;


	&lt;p&gt;After you enter the password, Capistrano will go out to your server and build the necessary directories, &lt;code&gt;chmod&lt;/code&gt;-ing them as necessary.&lt;/p&gt;


	&lt;p&gt;Nifty, huh? But this is only the beginning&amp;#8230;&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Sam Joseph</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-713</id>
    <issued>2006-03-09T04:01:26+00:00</issued>
    <modified>2006-03-09T04:01:26+00:00</modified>
    <title>Sam Joseph: Filtering emails in development</title>
    <link href="http://127.0.0.1:15101/read/chapter/64#page337" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Sometimes you want to be somewhere inbetween the :test and :smtp settings.  Say you&amp;#8217;re working on your development site, and you have a few testers working with you.  The site isn&amp;#8217;t in production yet, but you&amp;#8217;d like the testers to be able to receive emails from the site, but no one else.  Here&amp;#8217;s a handy way to handle that situation, add this to your environment.rb or development.rb file&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;class ActionMailer::Base

  def perform_delivery_fixed_email(mail)
    destinations = mail.destinations
    if destinations.nil?
      destinations = ["mymail@me.com"]
      mail.subject = '[TEST-FAILURE]:'+mail.subject
    else
      mail.subject = '[TEST]:'+mail.subject
    end
    approved = ["testerone@me.com","testertwo@me.com"]
    destinations = destinations.collect{|x| approved.collect{|y| (x==y ? x : nil)}}.flatten.compact
    mail.to = destinations
    if destinations.size &amp;gt; 0
      mail.ready_to_send
      Net::SMTP.start(server_settings[:address], server_settings[:port], server_settings[:domain], 
                    server_settings[:user_name], server_settings[:password], server_settings[:authentication]) do |smtp|
        smtp.sendmail(mail.encoded, mail.from, destinations)
      end
    end

  end

end
&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Sam Joseph</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-712</id>
    <issued>2006-03-09T03:47:29+00:00</issued>
    <modified>2006-03-09T03:47:29+00:00</modified>
    <title>Sam Joseph: Functional Testing</title>
    <link href="http://127.0.0.1:15101/read/chapter/64#page336" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Functional testing involves more than just checking that the email body, recipients and so forth are correct.  In functional mail tests we call the mail deliver methods and check that the appropriate emails have been appended to the delivery list.  It is fairly safe to assume that the deliver methods themselves do their job &amp;#8211; what we are probably more interested in is whether our own business logic is sending emails when we expect them to.  For example the password reset operation we used an example in the previous section will probably be called in response to a user requesting a password reset through some sort of controller.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/../test_helper'
require 'my_controller'

# Raise errors beyond the default web-based presentation
class MyController; def rescue_action(e) raise e end; end

class MyControllerTest &amp;lt; Test::Unit::TestCase

  def setup
    @controller = MyController.new
    @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
  end

  def test_reset_password
    num_deliveries = ActionMailer::Base.deliveries.size
    post :reset_password, :email =&amp;gt; 'bob@test.com'

    assert_equal num_deliveries+1, ActionMailer::Base.deliveries.size
  end

end

&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Sam Joseph</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-711</id>
    <issued>2006-03-09T03:00:14+00:00</issued>
    <modified>2006-03-09T03:00:14+00:00</modified>
    <title>Sam Joseph: Unit Testing</title>
    <link href="http://127.0.0.1:15101/read/chapter/64#page162" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;In order to test that your mailer is working as expected, we can use unit tests to compare the actual results of the mailer with pre-writen examples of what should be produced.&lt;/p&gt;


	&lt;h3&gt;revenge of the fixtures&lt;/h3&gt;


	&lt;p&gt;For the purposes of unit testing a mailer, fixtures are used to provide an example of how output &amp;#8220;should&amp;#8221; look.  Because these are example emails, and not Active Record data like the other fixtures, they are kept in their own subdirectory from the other fixtures. Don&amp;#8217;t tease them about it though, they hate that.&lt;/p&gt;


	&lt;p&gt;When you generated your mailer (you did that right?) the generator created stub fixtures for each of the mailers actions. If you didn&amp;#8217;t use the generator you&amp;#8217;ll have to make those files yourself.&lt;/p&gt;


	&lt;h3&gt;The basic test case&lt;/h3&gt;


	&lt;p&gt;Here is an example of what you start with.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/. ./test_helper'
require 'my_mailer'

class MyMailerTest &amp;lt; Test::Unit::TestCase
  FIXTURES_PATH = File.dirname(__FILE__) + '/. ./fixtures'

  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []

    @expected = TMail::Mail.new
  end

  def test_signup
    @expected.subject = 'MyMailer#signup'
    @expected.body    = read_fixture('signup')
    @expected.date    = Time.now

    assert_equal @expected.encoded, MyMailer.create_signup(@expected.date).encoded
  end

  private
    def read_fixture(action)
      IO.readlines("#{FIXTURES_PATH}/my_mailer/#{action}")
    end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The setup method is mostly concerned with setting up a blank slate for the next test.  However it is worth describing what each statement does&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ActionMailer::Base.delivery_method = :test
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;sets the delivery method to test mode so that email will not actually be delivered (useful to avoid spamming your users while testing) but instead it will be appended to an array (ActionMailer::Base.deliveries).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ActionMailer::Base.perform_deliveries = true
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Ensures the mail will be sent using the method specified by ActionMailer::Base.delivery_method, and finally&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;ActionMailer::Base.deliveries = []
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;sets the array of sent messages to an empty array so we can be sure that anything we find there was sent as part of our current test.&lt;/p&gt;


	&lt;p&gt;However often in unit tests, mails will not actually be sent, simply constructed, as in the example above, where the precise content of the email is checked against what it should be.  Dave Thomas suggests an alternative approach, which is just to check the part of the email that is likely to break, i.e. the dynamic content.  The following example assumes we have some kind of user table, and we might want to mail those users new passwords:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/../test_helper'
require 'my_mailer'

class MyMailerTest &amp;lt; Test::Unit::TestCase
  fixtures :users
  FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
  CHARSET = "utf-8" 

  include ActionMailer::Quoting

  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []

    @expected = TMail::Mail.new
    @expected.set_content_type "text", "plain", { "charset" =&amp;gt; CHARSET }
  end

  def test_reset_password
    user = User.find(:first)
    newpass = 'newpass'
    response = MyMailer.create_reset_password(user,newpass)
    assert_equal 'Your New Password', response.subject
    assert_match /Dear #{user.full_name},/, response.body
    assert_match /New Password: #{newpass}/, response.body
    assert_equal user.email, response.to[0]
  end

  private
    def read_fixture(action)
      IO.readlines("#{FIXTURES_PATH}/community_mailer/#{action}")
    end

    def encode(subject)
      quoted_printable(subject, CHARSET)
    end
end

&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;and here we check the dynamic parts of the mail, specifically that we use the users&amp;#8217; correct full name and that we give them the correct password.&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Sam Joseph</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-710</id>
    <issued>2006-03-09T02:52:45+00:00</issued>
    <modified>2006-03-09T02:52:45+00:00</modified>
    <title>Sam Joseph: Unit Testing</title>
    <link href="http://127.0.0.1:15101/read/chapter/64#page162" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;In order to test that your mailer is working as expected, we can use unit tests to compare the actual results of the mailer with pre-writen examples of what should be produced.&lt;/p&gt;


	&lt;h3&gt;revenge of the fixtures&lt;/h3&gt;


	&lt;p&gt;For the purposes of unit testing a mailer, fixtures are used to provide an example of how output &amp;#8220;should&amp;#8221; look.  Because these are example emails, and not Active Record data like the other fixtures, they are kept in their own subdirectory from the other fixtures. Don&amp;#8217;t tease them about it though, they hate that.&lt;/p&gt;


	&lt;p&gt;When you generated your mailer (you did that right?) the generator created stub fixtures for each of the mailers actions. If you didn&amp;#8217;t use the generator you&amp;#8217;ll have to make those files yourself.&lt;/p&gt;


	&lt;h3&gt;The basic test case&lt;/h3&gt;


	&lt;p&gt;Here is an example of what you start with.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;require File.dirname(__FILE__) + '/. ./test_helper'
require 'my_mailer'

class MyMailerTest &amp;lt; Test::Unit::TestCase
  FIXTURES_PATH = File.dirname(__FILE__) + '/. ./fixtures'

  def setup
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []

    @expected = TMail::Mail.new
  end

  def test_signup
    @expected.subject = 'MyMailer#signup'
    @expected.body    = read_fixture('signup')
    @expected.date    = Time.now

    assert_equal @expected.encoded, MyMailer.create_signup(@expected.date).encoded
  end

  private
    def read_fixture(action)
      IO.readlines("#{FIXTURES_PATH}/my_mailer/#{action}")
    end
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The setup method is mostly concerned with setting up a blank slate for the next test.  However it is worth describing what each statement does&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
ActionMailer::Base.delivery_method = :test
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;sets the delivery method to test mode so that email will not actually be delivered (useful to avoid spamming your users while testing) but instead it will be appended to an array (ActionMailer::Base.deliveries).&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
ActionMailer::Base.perform_deliveries = true
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Ensures the mail will be sent using the method specified by ActionMailer::Base.delivery_method, and finally&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
ActionMailer::Base.deliveries = []
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;sets the array of sent messages to an empty array so we can be sure that anything we find there was sent as part of our current test&lt;/p&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Jamis Buck</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-709</id>
    <issued>2006-03-06T05:33:36+00:00</issued>
    <modified>2006-03-06T05:33:36+00:00</modified>
    <title>Jamis Buck: Extension Libraries</title>
    <link href="http://127.0.0.1:15101/read/chapter/122#page335" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Sometimes, you&amp;#8217;ll write methods that you want multiple tasks to share. The methods themselves aren&amp;#8217;t tasks, they are simply lower-level operations, like the &lt;code&gt;run&lt;/code&gt; or &lt;code&gt;put&lt;/code&gt; or &lt;code&gt;delete&lt;/code&gt; methods that Capistrano itself provides.&lt;/p&gt;


	&lt;p&gt;Capistrano allows you to easily distribute and share libraries of these &lt;em&gt;extension&lt;/em&gt; methods, as well as tasks. Simply put your extension methods in a module, register the module with Capistrano, and then package it up and ship it. People can then use your extension methods simply by requiring the file, the same as with task libraries.&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Sample extension library [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;capistrano&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;MyReportingMethods&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;display&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;options&lt;/span&gt;&lt;span class="punct"&gt;={})&lt;/span&gt;
    &lt;span class="punct"&gt;...&lt;/span&gt;
    &lt;span class="ident"&gt;run&lt;/span&gt;&lt;span class="punct"&gt;(...)&lt;/span&gt;
    &lt;span class="punct"&gt;...&lt;/span&gt;
    &lt;span class="ident"&gt;put&lt;/span&gt;&lt;span class="punct"&gt;(...)&lt;/span&gt;
    &lt;span class="punct"&gt;...&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="constant"&gt;Capistrano&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;plugin&lt;/span&gt; &lt;span class="symbol"&gt;:report&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;MyReportingMethods&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;The last line is where your plugin is registered with Capistrano. You simply give it a name (&lt;code&gt;:report&lt;/code&gt;, in this case) and point it at your new module.&lt;/p&gt;


	&lt;p&gt;Once a recipe file loads this extension, it can access your report&amp;#8217;s &lt;code&gt;display&lt;/code&gt; method via &lt;code&gt;report.display(...)&lt;/code&gt;, effectively namespacing your extension methods.&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Using an extension library [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;my_reporting_methods&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

  &lt;span class="ident"&gt;task&lt;/span&gt; &lt;span class="symbol"&gt;:show_general_report&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;report&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;display&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="ident"&gt;task&lt;/span&gt; &lt;span class="symbol"&gt;:show_app_report&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:roles&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="symbol"&gt;:app&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;report&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;display&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <author>
      <name>Jamis Buck</name>
    </author>
    <id>tag:manuals.rubyonrails.com,2004:Hieraki-708</id>
    <issued>2006-03-06T05:32:59+00:00</issued>
    <modified>2006-03-06T05:32:59+00:00</modified>
    <title>Jamis Buck: Using a Task Library</title>
    <link href="http://127.0.0.1:15101/read/chapter/122#page334" rel="alternate" type="text/html"/>
    <content mode="escaped" type="text/html">&lt;p&gt;Now, you (or your friend, or anybody else) can use that library simply by installing it. In your &lt;code&gt;deploy.rb&lt;/code&gt;, you just require the file like you would any other ruby file:&lt;/p&gt;


	&lt;div class='figure'&gt;
&lt;span class='caption'&gt;Using a task library [ruby]&lt;/span&gt;
&lt;div class='body'&gt;&lt;link rel='stylesheet' type='text/css' href='/stylesheets/ruby.css' /&gt;&lt;div class='ruby'&gt;&lt;pre&gt;  &lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;custom-tasks&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;


	&lt;p&gt;Doing &lt;code&gt;cap show_tasks&lt;/code&gt; now ought to list your two custom tasks, along with all the standard ones.&lt;/p&gt;</content>
  </entry>
</feed>
