In association with heise online

Cross-Site-Scripting Protection By Default

In past versions of Rails, you had to manually implement content escaping when creating your views. This was usually done with the #h method, as in <%= h(@post.body) %> (a "blacklist" approach – "this stuff is bad"). In Rails 3, the default behaviour is to automatically escape all output, unless explicitly marked with #html_safe (a whitelist approach – "everything's bad unless I say otherwise"). For example:

<!-- Rails 2.3 -->
<%= h(@post.body) %>
<!--
escaped and safe:

&lt;script type=&quot;text/javascript&quot;&gt;
alert('lol, u got hacked');
&lt;/script&gt;

-->
<%= @post.body %>
<!--
result:

<script type="text/javascript">
alert('lol, u got hacked');
</script>

* not escaped, vulnerable to cross-site-scripting attack!
-->

<!-- Rails 3 -->
<%= @post.body %>
<!--
escaped and safe

&lt;script type=&quot;text/javascript&quot;&gt;
alert('lol, u got hacked');
&lt;/script&gt;

-->

<%= @post.body.html_safe %>
<!--
result:

<script type="text/javascript">
alert('lol, u got hacked');
</script>

* not escaped, vulnerable to cross-site-scripting attack!
-->

Marking strings as #html_safe should be done sparingly, only in situations where it is absolutely needed, and has no possibility of having tainted input. In modern web applications such situations are fairly rare, though still possible.

Other Notable Changes

* No more script/* - just use rails [command] [arguments] now. For example, rails server will start the development server, rails new /path/to/my/app creates a new Rails project from the default template, and rails generate model my_model would create a new model.

* Named Scopes have been changed so that the keyword is now simply scope, not named_scope. The syntax has changed as well:

class Article < ActiveRecord::Base
scope :unpublished, where(:published => false)
end

Bundler is now used for gem (dependency) management.

Bundler is a tool for managing gem dependencies in your Rails (or other Ruby) project, and is now the default method for managing gem dependencies in a Rails 3.x application. Using Bundler requires that your Rails application has a file named 'Gemfile' (no extension) at the directory root of your application. Though it has no extension, code inside Gemfile is evaluated as Ruby code, and is executed by the "bundle" executable that's made available when you install Bundler.

Setting up a Rails application to use Bundler is pretty straightforward. Start by installing Bundler as a gem:

$ gem install bundler

Tip: Rubygems will usually install RI and RDoc documentation by default. If you want to disable this behaviour, as it usually takes a while to generate all that documentation, create a .gemrc file in your home directory, and add the following code:

gem: --no-ri --no-rdoc

Alternatively, you can specify '--no-ri --no-rdoc' each time you issue the gem install ... command.

Once you have Bundler installed, either open the existing Gemfile in your Rails application, or if you don't have one, issue the following command:

$ bundle init

This will create a Gemfile with some sample code that looks like this:

# A sample Gemfile
source "http://rubygems.org"

# gem "rails"

As you can see, the syntax is just like that of Ruby, and code inside a Gemfile will be executed as Ruby code. (Just in case you were thinking about putting other application start-up code here, don't. That stuff belongs in an initializer instead.)

Next, you can add all your gem dependencies to the Gemfile. An example Gemfile may look something like this:

gem 'rails', '3.0.10' # Specify exact Rails version to use
gem 'pg' # Use latest available PostgreSQL gem

group :development, :test do
gem "rspec-rails'"
gem "nifty-generators"
gem "faker"
# ... and so on, for your dev/test gems
end

platforms :mri_19 do
# Use the ruby 1.9 debugger
gem "ruby-debug19",
:require => 'ruby-debug' if RUBY_VERSION < "1.9.3"
end

This Gemfile example shows many useful features of Bundler:

Specifying a gem version can be done in a one-line statement, as with the first line in the above example. This tells Bundler specifically to use Rails version 3.0.9. When the Rails development team releases a new version, you can simply change the version line and run bundle update (more on this below). Alternatively, you can use the latest stable version of a gem by not specifying any version information. That could be a bad idea, however; Rubyists are well-known for not being all that concerned with backwards compatibility, and "upgrades" will often break things that worked before. This is why it's a good idea to lock your application down to specific gem versions.

Groups are one of the best features of Bundler. Using a group block as above, you can specify – in a Rails application – gems to be loaded only under those specific environments. In this example, we're telling Bundler to load the listed gems only when the application is running in development or test mode. In the past, this may have been done by adding a "config.gem" line to the appropriate environment file (e.g. config/environments/test.rb). Now, we can simplify the process by including it in a group block. This is useful from a performance perspective, as you will never need to load development or test gems in a production environment, so confining those gems to the environments in which they're specifically needed avoids the performance hit on memory and startup time when the application is deployed in a production environment.

Platforms are another very useful feature. Multiple Ruby platforms exist in today's modern open source environment, including JRuby (built on the Java Virtual Machine), Rubinius, and MRI ("Matz Ruby Interpreter") versions 1.8.7 and 1.9.2, among others. Using the platforms feature as in the above example, you can specify which gems are loaded using which platform. This is useful if, for example, you build an application using MRI on your local machine, but want to deploy using JRuby. In this hypothetical situation, you would use a different database adapter than with MRI, and would want your application to be able to install the right gem for its particular Ruby implementation.

Finally, when you need to update your bundle (of gems), the process is simple: first, edit the Gemfile to reflect the new version information for the gems you want to update, then issue the following command:

$ bundle update gemname

Specifying the name of the gem to update tells Bundler to update only that gem to the information listed in Gemfile, but not to touch the other gem versions. If you want to update all gems, whether their version has changed or not, simply issue "bundle update" without any further arguments.

More information on Bundler can be found at the project's official web site, gembundler.com.

For More Information

More information about the changes in Rails 3 can be found in a variety of places, some of which are linked below for your convenience:

This completes our overview of the changes introduced into version 3.0 of Rails since 2.3. In the second of these two articles we will look at the new features and improvements due in version 3.1, expected on 30 August.

J. Austin Hughey (@jaustinhughey) is a web applications engineer from Texas (United States). After building web applications in PHP/MySQL for six years, in 2007 he made the switch to Ruby and hasn't really looked back.

Print Version | Permalink: http://h-online.com/-1285884
  • Twitter
  • Facebook
  • submit to slashdot
  • StumbleUpon
  • submit to reddit
 


  • July's Community Calendar





The H Open

The H Security

The H Developer

The H Internet Toolkit