Wednesday, April 29, 2009

Ruby Exceptions

Raising An Exception



An exception is a special kind of object, an instance of the class Exception or a descendant of that class that represents some kind of exceptional condition; it indicates that something has gone wrong. When this occurs, an exception is raised (or thrown). By default, Ruby programs terminate when an exception occurs. But it is possible to declare exception handlers. An exception handler is a block of code that is executed if an exception occurs during the execution of some other block of code. Raising an exception means stopping normal execution of the program and transferring the flow-of-control to the exception handling code where you either deal with the problem that's been encountered or exit the program completely. Which of these happens - dealing with it or aborting the program - depends on whether you have provided a rescue clause (rescue is a fundamental part of the Ruby language). If you haven't provided such a clause, the program terminates; if you have, control flows to the rescue clause.



Ruby has some predefined classes - Exception and its children - that help you to handle errors that can occur in your program. The following figure shows the Ruby exception hierarchy.



Exception Hierarchy



Reference: The above figure is from the Programming Ruby book.



The chart above shows that most of the subclasses extend a class known as StandardError. These are the "normal" exceptions that typical Ruby programs try to handle. The other exceptions represent lower-level, more serious, or less recoverable conditions, and normal Ruby programs do not typically attempt to handle them.



The following method raises an exception whenever it's called. Its second message will never be printed. Program p043raise.rb










The output is:










The raise method is from the Kernel module. By default, raise creates an exception of the RuntimeError class. To raise an exception of a specific class, you can pass in the class name as an argument to raise. Refer program p044inverse.rb









The output is:









Remember, methods that act as queries are often named with a trailing ?. is_a? is a method in the Object class and returns true or false. The unless modifier when tacked at the end of a normal statement means execute the preceding expression unless condition is true.



Defining new exception classes: To be even more specific about an error, you can define your own Exception subclass:










Handling an Exception



To do exception handling, we enclose the code that could raise an exception in a begin-end block and use one or more rescue clauses to tell Ruby the types of exceptions we want to handle. It is to be noted that the body of a method definition is an implicit begin-end block; the begin is omitted, and the entire body of the method is subject to exception handling, ending with the end of the method.



The program p045handexcp.rb illustrates this:










The output is:









Observe that the code interrupted by the exception never gets run. Once the exception is handled, execution continues immediately after the begin block that spawned it.



If you write a rescue clause with no parameter list, the parameter defaults to StandardError. Each rescue clause can specify multiple exceptions to catch. At the end of each rescue clause you can give Ruby the name of a local variable to receive the matched exception. The parameters to the rescue clause can also be arbitrary expressions (including method calls) that return an Exception class. If we use raise with no parameters, it re-raises the exception.



You can stack rescue clauses in a begin/rescue block. Exceptions not handled by one rescue clause will trickle down to the next:










For each rescue clause in the begin block, Ruby compares the raised Exception against each of the parameters in turn. The match will succeed if the exception named in the rescue clause is the same as the type of the currently thrown exception, or is a superclass of that exception. The code in an else clause is executed if the code in the body of the begin statement runs to completion without exceptions. If an exception occurs, then the else clause will obviously not be executed. The use of an else clause is not particularly common in Ruby.



If you want to interrogate a rescued exception, you can map the Exception object to a variable within the rescue clause, as shown in the program p046excpvar.rb










The output is:









The Exception class defines two methods that return details about the exception. The message method returns a string that may provide human-readable details about what went wrong. The other important method is backtrace. This method returns an array of strings that represent the call stack at the point that the exception was raised.



If you need the guarantee that some processing is done at the end of a block of code, regardless of whether an exception was raised then the ensure clause can be used. ensure goes after the last rescue clause and contains a chunk of code that will always be executed as the block terminates. The ensure block will always run.



Some common exceptions are:

RuntimeError (this is the default exception raised by the raise method), NoMethodError, NameError, IOError, TypeError and ArgumentError.



An Example: Let's modify program p027readwrite.rb to include exception handling as shown in example p046xreadwrite.rb below.










Improper error messages can provide critical information about an application which may aid an attacker in exploiting the application. The most common problem occurs when detailed internal error messages such as stack traces, database dumps, and error codes are displayed to the user. Security analysts view logging and error handling as potential areas of risk. It is recommended that production applications should not use, for example, a puts e.backtrace.inspect call unless it is being directly committed into a log that is not viewable to the end user.



Validation example



Here's an example from the Ruby Cookbook, showing how one can do validation of user's inputs.









The Name class keeps track of peoples' first and last names. It uses setter methods to enforce two somewhat parochial rules: everyone must have both a first and a last name, and everyone's first name must begin with a capital letter. The Name class has been written in such a way, that the rules are enforced both in the constructor and after the object has been created. Sometimes you don't trust the data coming in through the setter methods. That's when you can define your own methods to stop bad data before it infects your objects. Within a class, you have direct access to the instance variables. You can simply assign to an instance variable and the setter method won't be triggered. If you do want to trigger the setter method, you'll have to call it explicitly. Note how, in the Name#initialize method above, we call the first= and last= methods instead of assigning to @first and @last. This makes sure the validation code gets run for the initial values of every Name object. We can't just say first = first, because first is a variable name in that method.



Note: The Ruby Logo is Copyright (c) 2006, Yukihiro Matsumoto. I have made extensive references to information, related to Ruby, available in the public domain (wikis and the blogs, articles of various Ruby Gurus), my acknowledgment and thanks to all of them. Much of the material on ruby--on--rails blog is drawn primarily from the Programming Ruby book, available from The Pragmatic Bookshelf.

Wednesday, April 15, 2009

What is Variable Scope?


Scope defines where in a program a variable is accessible. Ruby has four types of variable scope, local, global, instance and class. In addition, Ruby has one constant type. Each variable type is declared by using a special character at the start of the variable name as outlined in the following table.











Name Begins WithVariable Scope
$ A global variable

@
An instance variable

[a-z] or _
A local variable

[A-Z]
A constant

@@
A class variable


In addition, Ruby has two pseudo-variables which cannot be assigned values. These are nil which is assigned to uninitialized variables and self which refers to the currently executing object. In the remainder of this chapter we will look at each of these variable scopes in turn.

Detecting the Scope of a Ruby Variable


Obviously, you can tell the scope of a variable by looking at the name. Sometimes, however, you need to find out the scope programmatically. A useful technique to find out the scope of a variable is to use the defined? method. defined? will return the scope of the variable referenced, or nil if the variable is not defined in the current context:



x = 10
=> 10
defined? x
=> "local-variable"

$x = 10
=> 10
defined? $x
=> "global-variable"

Ruby Local Variables



Local variables are local to the code construct in which they are declared. For example, a local variable declared in a method or within a loop cannot be accessed outside of that loop or method. Local variable names must begin with either an underscore or a lower case letter. For example:


loopcounter = 10
_LoopCounter = 20

Ruby Global Variables


Global variables in Ruby are accessible from anywhere in the Ruby program, regardless of where they are declared. Global variable names are prefixed with a dollar sign ($). For example:


$welcome = "Welcome to Ruby Essentials"


Use of global variables is strongly discouraged. The problem with global variables is that, not only are they visible anywhere in the code for a program, they can also be changed from anywhere in the application. This can make tracking bugs difficult.
It is useful to know, however, that a number of pre-defined global variables are available to you as a Ruby developer to obtain information about the Ruby environment. A brief summary of each of these variables is contained in the following table.



Variable Name

Variable Value



$@

The location of latest error



$_

The string last read by gets



$.

The line number last read by interpreter



$&

The string last matched by regexp



$~

The last regexp match, as an array of subexpressions



$n

The nth subexpression in the last match (same as $~[n])



$=

The case-insensitivity flag




$/

The input record separator



$\

The output record separator



$0

The name of the ruby script file currently executing



$*

The command line arguments used to invoke the script



$$

The Ruby interpreter's process ID



$?

The exit status of last executed child process






For example we can execute the gets method to take input from the keyboard, and then reference the $_ variable to retrieve the value entered:


irb(main):005:0> gets
hello
=> "hello\n"
irb(main):006:0> $_
=> "hello\n"


Alternatively we could find the process ID of the Ruby interpreter:


irb(main):007:0> $$
=> 17403

Ruby Class Variables



A class variable is a variable that is shared amongst all instances of a class. This means that only one variable value exists for all objects instantiated from this class. This means that if one object instance changes the value of the variable, that new value will essentially change for all other object instances.
Another way of thinking of thinking of class variables is as global variables within the context of a single class.
Class variables are declared by prefixing the variable name with two @ characters (@@). Class variables must be initialized at creation time. For example:


@@total = 0

Ruby Instance Variables


Instance variables are similar to Class variables except that their values are local to specific instances of an object. For example if a class contains an instance variable called @total, if one instance of the object changes the current value of @total the change is local to only the object that made the change. Other objects of the same class have their own local copies of the variable which are independent of changes made in any other objects.

Instance variables are declared in Ruby by prefixing the variable name with a single @ sign:


@total = 10

Ruby Constant Scope


Ruby constants are values which, once assigned a value, should not be changed. I say should because Ruby differs from most programming languages in that it allows a constant value to be changed after it has been declared, although the interpreter will protest slightly with a warning message.
Constants declared within a class or module are available anywhere within the context of that class or module. Constants declared outside of a class or module are assigned global scope.

Tuesday, April 14, 2009

ROR - Plugins

Ruby provides many useful plug-ins which you can use in your Rails applications. Here are few scripts which help you to deal with pkug-ins.












PluginDescription
script/plugin discoverDiscover plugin repositories
script/plugin listList all available plugins
script/plugin install whereInstall the "where" plugin
script/plugin install -x whereInstall the "where" plugin as SVN external
script/plugin updateUpdate installed plugins
script/plugin sourceAdd a source repository
script/plugin unsourceRemoves a source repository
script/plugin sourcesLists source repositories

ROR - Scripts

Ruby provides many useful scripts which you use during your project implementation. Here are few scripts which you will use most frequently.













ScriptDescription
script/aboutGives information about environenment
script/breakpointerStarts the breakpoint server
script/consoleinteractive Rails Console
script/destroyDeletes files created by generators
script/generateUsed by generators
script/runnerExecutes a task in the rails context
script/serverLaunches the development server
script/performance/profileProfile an expansive method
script/performance/benchmarkerbenchmark different methods

Thursday, April 9, 2009

Gem Commands for RubyGems

The gem command is one of the most used Ruby-related commands, but most users don't take the time to learn anything past gem install and gem search. Learning the gem command well is an essential Ruby skill.

The gem command-line utility is split into a number of commands. Among these are the familiar install and search, but other useful commands exist such as spec and sources. However, you should start with the help command.

The gem command has integrated help. By running the command gem help, you can get a basic help screen. To get a list of commands available, run the gem help commands command. To get further help about a specific command, here, for example, the purge command, run the gem help purge command. Another useful help screen is the examples screen, accessible by the gem help examples command.

Most commands work on a gem repository, either local (the gems you have installed), or remote. Though, by default, it's the local repository. To specify the repository you intend , add either --remote or --local to the end of the command. For example, to search the remote repository for gems with the word "twitter" in them, you would run gem search twitter --remote. Specify both remote and local repositories by using the --both switch.

When running any gem command, the name can be shortened as long as it doesn't become ambiguous. To run a gem dependency command, you can simply run a gem dep command.

Below is a list of the commands and an explanation of their function.


build - Given the source code for a gem and a .gemspec file, this will build a .gem file suitable for uploading to a gem repository or installing on another computer with the gem command. A .gemspec file holds information about a gem including name, author, version and dependencies.

cert - Manages certificates for cryptographically signed gems. If you're worried that a malicious user is going to compromise the gems you install, you can cryptographically sign them to prevent this. Keys may be added or deleted from your list of acceptable keys, as well as a few other crypto key related functions.

check - Performs a number of actions, including running any unit tests, checking the checksum of installed gems and looking for unmanaged files in the gem repository. The type of check you wish to run must be added to the end of the gem command.

cleanup - Removes old versions of installed gems from your local repository. If you frequently upgrade gems, you can have old versions hanging around that you don't need anymore.

contents - Shows the contents of an installed gem. This is a list of files the gem installed and where they are on the filesystem.

dependency - Shows all the gems the listed gem depends upon, as well as the versions of the gem it depends upon. For example, running gem dep twitter tells me the twitter gem relies on hpricot, activesupport, httparty and echoe. This is useful when packaging your applications for deployment.

environment - Displays various information about the RubyGems environment, including the version installed, where it's installed, where the gem repository is, etc.

fetch - Fetches a gem and saves the .gem file in the current directory. This is useful for transferring gems to be deployed on other servers, without them needing to download the gem themselves.


generate_index - Generates an index for a gem server. This is only useful if you're running a gem repository.

install - Downloads a gem from the specified repository (--local or --remote) and install it. Also, downloads any dependencies and installs them as well. To install a specific version of a gem, use the --version switch.

list - Displays a list of gems in the repository. Note that doing this with --remote will generate quite a large list. Save this list to a file for fast searching.

lock - Generates a Ruby script that requires the exact version of all dependencies of a certain gem. This ensures that the gem versions tested during development will be installed, not future or past versions which may have bugs the developers cannot account for.

mirror - Mirrors an entire gem repository. Note that trying to mirror the RubyGems repository is a huge task. Do not do so unless you need to run a local mirror for other clients.

outdated - Displays a list of installed gems that have newer versions on the remote repository.

pristine - Returns gems to their original state. This means unpacking all gems from the local cache, overwriting any changes made to the gems in the local gem repository. This can be used to repair a broken gem.

rdoc - Generates rdoc documentation for an installed gem. This rdoc documentation can then be viewed with a web browser.

search - Searches the names of all gems and returns a list of gems whose name contains a string. For example, to search for all gems containing the word twitter in the name, run gem search twitter.

server - Starts a web server that will act as a gem repository and serves RDoc documentation for all installed gems. This is most useful for the documentation feature.

sources - Manages the list of sources for remote repositories. By default, only http://gems.rubyforge.org is in the list, but more can be added or removed.

specification - Displays the gemspec of a gem. This will tell you all the information about a gem, including author, dependencies, etc.

stale - Displays a list of installed gems, as well as the access times (the last time the gem was included). This can help you weed out gems you no longer user to uninstall them.

uninstall - Uninstalles a gem. If there are any installed gems that depend on this gem, you will be prompted whether you want to uninstall this gem. If you do, any gems that depended on this gem will be broken until it is reinstalled.

unpack - Unpacks an install gem into the current directory. This can be used to "freeze" gems to your project directory.

update - Checks if there are new versions of the specified gem in the remote repository. If there are, download and install the newest version.

which - Finds the exact location of the .rb file to include. This can be useful for getting a path for requiring a gem without requiring the rubygems library.

Tuesday, April 7, 2009

Rails version 2.3 release notes!

Rails 2.3 is finally done and out the door. This is one of the most substantial upgrades to Rails in a very long time. A brief rundown of the top features:

* Templates: Allows your new skeleton Rails application to be built your way with your default stack of gems, configs, and more.
* Engines: Share reusable application pieces complete with routes that Just Work, models, view paths, and the works.
* Rack: Rails now runs on Rack which gives you access to all the middleware goodness.
* Metal: Write super fast pieces of optimized logic that routes around Action Controller.
* Nested forms: Deal with complex forms so much easier.

And that’s just the tip of the iceberg. We’ve put together a complete guide for the Rails 2.3 release notes with much more information. Be sure to checkout the section on what was deprecated when you’re ready to upgrade your application.

You install 2.3 with (the final version is marked 2.3.2):
gem install rails

If you’re running on Passenger, be sure to upgrade to 2.1.2 as well. Rails 2.3 doesn’t run on older versions of Passenger!

A quick Review on rails version 2.0

Action Pack: Resources

This is where the bulk of the action for 2.0 has gone. We’ve got a slew of improvements to the RESTful lifestyle. First, we’ve dropped the semicolon for custom methods instead of the regular slash. So /people/1;edit is now /people/1/edit. We’ve also added the namespace feature to routing resources that makes it really easy to confine things like admin interfaces:

map.namespace(:admin) do |admin|
admin.resources :products,
:collection => { :inventory => :get },
:member => { :duplicate => :post },
:has_many => [ :tags, :images, :variants ]
end

Which will give you named routes like inventory_admin_products_url and admin_product_tags_url. To keep track of this named routes proliferation, we’ve added the “rake routes” task, which will list all the named routes created by routes.rb.

We’ve also instigated a new convention that all resource-based controllers will be plural by default. This allows a single resource to be mapped in multiple contexts and still refer to the same controller. Example:


# /avatars/45 => AvatarsController#show
map.resources :avatars

# /people/5/avatar => AvatarsController#show
map.resources :people, :has_one => :avatar

Action Pack: Multiview

Alongside the improvements for resources come improvements for multiview. We already have #respond_to, but we’ve taken it a step further and made it dig into the templates. We’ve separated the format of the template from its rendering engine. So show.rhtml now becomes show.html.erb, which is the template that’ll be rendered by default for a show action that has declared format.html in its respond_to. And you can now have something like show.csv.erb, which targets text/csv, but also uses the default ERB renderer.

So the new format for templates is action.format.renderer. A few examples:

* show.erb: same show template for all formats
* index.atom.builder: uses the Builder format, previously known as rxml, to render an index action for the application/atom+xml mime type
* edit.iphone.haml: uses the custom HAML template engine (not included by default) to render an edit action for the custom Mime::IPHONE format

Speaking of the iPhone, we’ve made it easier to declare “fake” types that are only used for internal routing. Like when you want a special HTML interface just for an iPhone. All it takes is something like this:


# should go in config/initializers/mime_types.rb
Mime.register_alias "text/html", :iphone

class ApplicationController < ActionController::Base
before_filter :adjust_format_for_iphone

private
def adjust_format_for_iphone
if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(iPhone|iPod)/]
request.format = :iphone
end
end
end

class PostsController < ApplicationController
def index
respond_to do |format|
format.html # renders index.html.erb
format.iphone # renders index.iphone.erb
end
end
end

You’re encouraged to declare your own mime-type aliases in the config/initializers/mime_types.rb file. This file is included by default in all new applications.

Action Pack: Record identification

Piggy-backing off the new drive for resources are a number of simplifications for controller and view methods that deal with URLs. We’ve added a number of conventions for turning model classes into resource routes on the fly. Examples:


# person is a Person object, which by convention will
# be mapped to person_url for lookup
redirect_to(person)
link_to(person.name, person)
form_for(person)

Action Pack: HTTP Loving

As you might have gathered, Action Pack in Rails 2.0 is all about getting closer with HTTP and all its glory. Resources, multiple representations, but there’s more. We’ve added a new module to work with HTTP Basic Authentication, which turns out to be a great way to do API authentication over SSL. It’s terribly simple to use. Here’s an example (there are more in ActionController::HttpAuthentication):


class PostsController < ApplicationController
USER_NAME, PASSWORD = "dhh", "secret"

before_filter :authenticate, :except => [ :index ]

def index
render :text => "Everyone can see me!"
end

def edit
render :text => "I'm only accessible if you know the password"
end

private
def authenticate
authenticate_or_request_with_http_basic do |user_name, password|
user_name == USER_NAME && password == PASSWORD
end
end
end

We’ve also made it much easier to structure your JavaScript and stylesheet files in logical units without getting clobbered by the HTTP overhead of requesting a bazillion files. Using javascript_include_tag(:all, :cache => true) will turn public/javascripts/.js into a single public/javascripts/all.js file in production, while still keeping the files separate in development, so you can work iteratively without clearing the cache.

Along the same lines, we’ve added the option to cheat browsers who don’t feel like pipelining requests on their own. If you set ActionController::Base.asset_host = “assets%d.example.com”, we’ll automatically distribute your asset calls (like image_tag) to asset1 through asset4. That allows the browser to open many more connections at a time and increases the perceived speed of your application.

Action Pack: Security

Making it even easier to create secure applications out of the box is always a pleasure and with Rails 2.0 we’re doing it from a number of fronts. Most importantly, we now ship we a built-in mechanism for dealing with CRSF attacks. By including a special token in all forms and Ajax requests, you can guard from having requests made from outside of your application. All this is turned on by default in new Rails 2.0 applications and you can very easily turn it on in your existing applications using ActionController::Base.protect_from_forgery (see ActionController::RequestForgeryProtection for more).

We’ve also made it easier to deal with XSS attacks while still allowing users to embed HTML in your pages. The old TextHelper#sanitize method has gone from a black list (very hard to keep secure) approach to a white list approach. If you’re already using sanitize, you’ll automatically be granted better protection. You can tweak the tags that are allowed by default with sanitize as well. See TextHelper#sanitize for details.

Finally, we’ve added support for HTTP only cookies. They are not yet supported by all browsers, but you can use them where they are.

Action Pack: Exception handling

Lots of common exceptions would do better to be rescued at a shared level rather than per action. This has always been possible by overwriting rescue_action_in_public, but then you had to roll out your own case statement and call super. Bah. So now we have a class level macro called rescue_from, which you can use to declaratively point certain exceptions to a given action. Example:


class PostsController < ApplicationController
rescue_from User::NotAuthorized, :with => :deny_access

protected
def deny_access
...
end
end

Action Pack: Cookie store sessions

The default session store in Rails 2.0 is now a cookie-based one. That means sessions are no longer stored on the file system or in the database, but kept by the client in a hashed form that can’t be forged. This makes it not only a lot faster than traditional session stores, but also makes it zero maintenance. There’s no cron job needed to clear out the sessions and your server won’t crash because you forgot and suddenly had 500K files in tmp/session.

This setup works great if you follow best practices and keep session usage to a minimum, such as the common case of just storing a user_id and a the flash. If, however, you are planning on storing the nuclear launch codes in the session, the default cookie store is a bad deal. While they can’t be forged (so is_admin = true is fine), their content can be seen. If that’s a problem for your application, you can always just switch back to one of the traditional session stores (but first investigate that requirement as a code smell).

Action Pack: New request profiler

Figuring out where your bottlenecks are with real usage can be tough, but we just made it a whole lot easier with the new request profiler that can follow an entire usage script and report on the aggregate findings. You use it like this:


$ cat login_session.rb
get_with_redirect '/'
say "GET / => #{path}"
post_with_redirect '/sessions', :username => 'john', :password => 'doe'
say "POST /sessions => #{path}"
$ ./script/performance/request -n 10 login_session.rb

And you get a thorough breakdown in HTML and text on where time was spent and you’ll have a good idea on where to look for speeding up the application.

Action Pack: Miscellaneous

Also of note is AtomFeedHelper, which makes it even simpler to create Atom feeds using an enhanced Builder syntax. Simple example:


# index.atom.builder:
atom_feed do |feed|
feed.title("My great blog!")
feed.updated((@posts.first.created_at))

for post in @posts
feed.entry(post) do |entry|
entry.title(post.title)
entry.content(post.body, :type => 'html')

entry.author do |author|
author.name("DHH")
end
end
end
end

We’ve made a number of performance improvements, so asset tag calls are now much cheaper and we’re caching simple named routes, making them much faster too.

Finally, we’ve kicked out in_place_editor and autocomplete_for into plugins that live on the official Rails SVN.

Active Record: Performance

Active Record has seen a gazillion fixes and small tweaks, but it’s somewhat light on big new features. Something new that we have added, though, is a very simple Query Cache, which will recognize similar SQL calls from within the same request and return the cached result. This is especially nice for N+1 situations that might be hard to handle with :include or other mechanisms. We’ve also drastically improved the performance of fixtures, which makes most test suites based on normal fixture use be 50-100% faster.

Active Record: Sexy migrations

There’s a new alternative format for declaring migrations in a slightly more efficient format. Before you’d write:

create_table :people do |t|
t.column, "account_id", :integer
t.column, "first_name", :string, :null => false
t.column, "last_name", :string, :null => false
t.column, "description", :text
t.column, "created_at", :datetime
t.column, "updated_at", :datetime
end

Now you can write:

create_table :people do |t|
t.integer :account_id
t.string :first_name, :last_name, :null => false
t.text :description
t.timestamps
end

Active Record: Foxy fixtures

The fixtures in Active Record has taken a fair amount of flak lately. One of the key points in that criticism has been the work with declaring dependencies between fixtures. Having to relate fixtures through the ids of their primary keys is no fun. That’s been addressed now and you can write fixtures like this:


# sellers.yml
shopify:
name: Shopify

# products.yml
pimp_cup:
seller: shopify
name: Pimp cup

As you can see, it’s no longer necessary to declare the ids of the fixtures and instead of using seller_id to refer to the relationship, you just use seller and the name of the fixture.

Active Record: XML in, JSON out

Active Record has supported serialization to XML for a while. In 2.0 we’ve added deserialization too, so you can say Person.new.from_xml(“David“) and get what you’d expect. We’ve also added serialization to JSON, which supports the same syntax as XML serialization (including nested associations). Just do person.to_json and you’re ready to roll.

Active Record: Shedding some weight

To make Active Record a little leaner and meaner, we’ve removed the acts_as_XYZ features and put them into individual plugins on the Rails SVN repository. So say you’re using acts_as_list, you just need to do ./script/plugin install acts_as_list and everything will move along like nothing ever happened.

A little more drastic, we’ve also pushed all the commercial database adapters into their own gems. So Rails now only ships with adapters for MySQL, SQLite, and PostgreSQL. These are the databases that we have easy and willing access to test on. But that doesn’t mean the commercial databases are left out in the cold. Rather, they’ve now been set free to have an independent release schedule from the main Rails distribution. And that’s probably a good thing as the commercial databases tend to require a lot more exceptions and hoop jumping on a regular basis to work well.

The commercial database adapters now live in gems that all follow the same naming convention: activerecord-XYZ-adapter. So if you gem install activerecord-oracle-adapter, you’ll instantly have Oracle available as an adapter choice in all the Rails applications on that machine. You won’t have to change a single line in your applications to take use of it.

That also means it’ll be easier for new database adapters to gain traction in the Rails world. As long as you package your adapter according to the published conventions, users just have to install the gem and they’re ready to roll.

Active Record: with_scope with a dash of syntactic vinegar

ActiveRecord::Base.with_scope has gone protected to discourage people from misusing it in controllers (especially in filters). Instead, it’s now encouraged that you only use it within the model itself. That’s what it was designed for and where it logically remains a good fit. But of course, this is all about encouraging and discouraging. If you’ve weighed the pros and the cons and still want to use with_scope outside of the model, you can always call it through .send(:with_scope).

ActionWebService out, ActiveResource in

It’ll probably come as no surprise that Rails has picked a side in the SOAP vs REST debate. Unless you absolutely have to use SOAP for integration purposes, we strongly discourage you from doing so. As a naturally extension of that, we’ve pulled ActionWebService from the default bundle. It’s only a gem install actionwebservice away, but it sends an important message none the less.

At the same time, we’ve pulled the new ActiveResource framework out of beta and into the default bundle. ActiveResource is like ActiveRecord, but for resources. It follows a similar API and is configured to Just Work with Rails applications using the resource-driven approach. For example, a vanilla scaffold will be accessible by ActiveResource.

ActiveSupport

There’s not all that much new in ActiveSupport. We’ve a host of new methods like Array#rand for getting a random element from an array, Hash#except to filter down a hash from undesired keys and lots of extensions for Date. We also made testing a little nicer with assert_difference. Short of that, it’s pretty much just fixes and tweaks.

Action Mailer

This is a very modest update for Action Mailer. Besides a handful of bug fixes, we’ve added the option to register alternative template engines and assert_emails to the testing suite, which works like this:

1. Assert number of emails delivered within a block: assert_emails 1 do post :signup, :name => ‘Jonathan’ end

Rails: The debugger is back

To tie it all together, we have a stream of improvements for Rails in general. My favorite amongst these is the return of the breakpoint in form of the debugger. It’s a real debugger too, not just an IRB dump. You can step back and forth, list your current position, and much more. It’s all coming from the gracious note of the ruby-debug gem. So you’ll have to install that for the new debugger to work.

To use the debugger, you just install the gem, put “debugger” somewhere in your application, and then start the server with—debugger or -u. When the code executes the debugger command, you’ll have it available straight in the terminal running the server. No need for script/breakpointer or anything else. You can use the debugger in your tests too.

Rails: Clean up your environment

Before Rails 2.0, config/environment.rb files every where would be clogged with all sorts of one-off configuration details. Now you can gather those elements in self-contained files and put them under config/initializers and they’ll automatically be loaded. New Rails 2.0 applications ship with two examples in form of inflections.rb (for your own pluralization rules) and mime_types.rb (for your own mime types). This should ensure that you need to keep nothing but the default in config/environment.rb.

Rails: Easier plugin order

Now that we’ve yanked out a fair amount of stuff from Rails and into plugins, you might well have other plugins that depend on this functionality. This can require that you load, say, acts_as_list before your own acts_as_extra_cool_list plugin in order for the latter to extend the former.

Before, this required that you named all your plugins in config.plugins. Major hassle when all you wanted to say was “I only care about acts_as_list being loaded before everything else”. Now you can do exactly that with config.plugins = [ :acts_as_list, :all ].

And hundreds upon hundreds of other improvements

What I’ve talked about above is but a tiny sliver of the full 2.0 package. We’ve got literally hundreds of bug fixes, tweaks, and feature enhancements crammed into Rails 2.0. All this coming off the work of tons of eager contributors working tirelessly to improve the framework in small, but important ways.

I encourage you to scourger the CHANGELOGs and learn more about all that changed.

So how do I upgrade?

If you want to move your application to Rails 2.0, you should first move it to Rails 1.2.6. That’ll include deprecation warnings for most everything we yanked out in 2.0. So if your application runs fine on 1.2.6 with no deprecation warnings, there’s a good chance that it’ll run straight up on 2.0. Of course, if you’re using, say, pagination, you’ll need to install the classic_pagination plugin. If you’re using Oracle, you’ll need to install the activerecord-oracle-adapter gem. And so on and so forth for all the extractions.

So how do I install?

To install through gems, do:

gem install rails -y

...if you’re having trouble with that (gem not found), just grab gems from our own repository in the meanwhile:

gem install rails -y --source http://gems.rubyonrails.org

To try it from an SVN tag, use (you may need to run this command twice depending on your current Rails version):

rake rails:freeze:edge TAG=rel_2-0-1

Note: It’s 2.0.1 because we found a small issue just after we pushed 2.0.0.