CSC/ECE 517 Fall 2011/ch2 2f jm

From Expertiza_Wiki
Revision as of 19:00, 20 September 2011 by Jqma (talk | contribs)
Jump to navigation Jump to search

Rails 2 vs. Rails 3

Introduction

There are many changes involved when you migrate your Rails application from Rails 2 to Rails 3. If your application is a based on Rails 2, there are important changes you'll need to make to run your application in Rails 3.<ref name="refone">Carletti, Simone. "The Road to Rails 3: make your Rails 2.3 project more Rails 3 oriented" http://www.simonecarletti.com/blog/2010/07/the-way-to-rails-3/</ref> There are additional changes planned for Rails 3.1 and Rails 3.2 that you should consider now if you're migrating from Rails 2 to Rails 3.<ref name="reftwo">Naik, Pratik. "Active Record Query Interface 3.0" http://m.onkey.org/active-record-query-interface</ref> A variety of these changes, including changes covered in class, are covered in the sections below.

Differences between Rails 2 and Rails 3

The differences between Rails 2 and Rails 3 are probably best understood by the categories of changes required to make your Rails 2 application work in a Rails 3 environment. The following categories address some of these changes.

Prerequisites

In any major version upgrade of software there are likely to be prerequisites. Rails is no different and there are a few items that you'll need to consider. These prerequisites include the following:<ref name="refone"/>

  • Make sure you have unit, functional and integration testing already implemented in your application before porting it to Rails 3.<ref>"Ruby on Rails Guides: A Guide to Testing Rails Applications" http://guides.rubyonrails.org/testing.html></ref>
  • Rails 3 incorporates string escaping. This can break your view helpers, so they will need to be reviewed and tested.<ref name="refone"/>
  • Upgrade your Ruby software to at least version 1.8.7 or skip to 1.9.2. Other versions do not work or do not work properly.<ref>"Ruby on Rails Guides: Ruby on Rails 3.0 Release Notes" http://edgeguides.rubyonrails.org/3_0_release_notes.html</ref>

Mandatory Changes

Even after prerequisites are met there are mandatory changes introduced by updates that obsolete certain features or capabilities. Again Rails 3 is no different in this respect.<ref name="refone"/>

  • The standard for managing Gem dependencies is called Bundler<ref>"Bundler: The Best Way to Manage Ruby Applications" http://gembundler.com/</ref>. This is backwards compatible with Rails 2.3 so you can implement this prior to migrating to Rails 3.<ref>"Using Bundler with Rails 2.3" http://gembundler.com/rails23.html</ref>
  • Rails 3 is JavaScript framework agnostic and is no longer prototype-oriented.<ref name="refone"/> As a result, there are changes that require attention.<ref>Carletti, Simone (June 2010). "Unobtrusive JavaScript in Rails 3" http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/</ref>
  • Object#returning has been removed and you should begin using Object#Tap.<ref name="refone"/>
  • Make sure your YAML files with embedded HTML have a key that ends in _html or the HTML will be escaped.<ref name="refone"/>
  • The Rails Metal feature has been removed.<ref name="refone"/>
  • You can only have ActiveRecord fixtures in the test/fixtures folder.<ref name="refone"/>
  • Rails helpers for input, form, error_messages_for and error_message_on have been removed.<ref name="refone"/>. A plugin called dynamic_form is available to continue using this functionality.<ref>"rails/dynamic_form - GitHub" https://github.com/rails/dynamic_form</ref> However, there is another method by Ryan Bates to accomplish these features without using a plugin.<ref>Bates, Ryan. "Validations in Rails 3" http://railscasts.com/episodes/211-validations-in-rails-3</ref>

Optional Changes

Example Code differences between Rails 2 and Rails 3 (from class)

Deprecated Methods in Active Record Query Interface for Rails 3

At this point you may have discovered some of the great functionalities that come with Rails 3. When you start to switch from Rails 2 to Rails 3, you may start to see warning messages or even errors in some of your existing methods. That is because in Rails 3, all of the internals, especially the ActiveRecord interface, received a massive clean out, which makes the Rails modularity framework much cleaner and more extensible for developers to use. As this result, some of the methods in Rails 2 are now deprecated or even fully removed, which causes warning messages or error when compiling the code. Below will show a list of these deprecated methods.

find([:all | :first | :last]) Method

The find(*args) method in the Active Record interface allows user to retrieve objects from the database table. User can retrieve the first or the last object in the table, or an object by its id, or all the objects at once. These methods followed the syntax of #find(:all), #find(:first) or #find(:last)in Rails 2. However in Rails 3, they are now deprecated and have been converted to #all, #first, and #last alternatives. See the following example for comparison:

# the deprecated version
@categories = Category.find(:all)
@first_category = Category.find(:first)
@last_category = Category.find(:last)

# the good version
@categories = Category.all
@first_category = Category.first
@last_category = Category.last

find(*args, options) Method

In Rails 3.1, ActiveRecord methods that have Options argument are also deprecated and will be removed in Rails 3.2. These passing options hash includes :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock. So what is the replacement for the find(*args, options)method? The answer is inside the new Rails 3 API. The new Rails 3 API has the following finder methods to replace with the find(*args, options)method.

  • where (:conditions)
  • having (:conditions)
  • select
  • group
  • order
  • limit
  • offset
  • joins
  • includes (:include)
  • lock
  • readonly
  • from

For examples, in Rails 2 you do

# deprecated statements
@desert_categories = Category.find(:all, :conditions => {:name => "Desert"})
@two_categories = Category.find(:all, :limit => 2)
@ordered_categories = Category.find(:all, :order => “created_at desc”)

But in Rails 3, you should now do

# correct version
@desert_categories = Category.where(:name=>"Desert")
@two_categories = Category.limit(2)
@ordered_categories = Category.order("created_at desc")

Furthermore, all of the above methods are defined on the Relation object, which gains the ability of chainability. In other word, all the methods can be chained together. This is a very powerful feature because it allows you to define multiple conditions in a find statement using just one line of code, which makes developers’ life so much easier. For example, if you want to return the 10 newest Desert recipes in descendent order based on the creation date, you can do

@recipes = Recipe.where(:category_name => “Desert”). order("created_at desc").limit(10)

named_scope Method

The named_scoped method is deprecated and needed to be renamed to scope in Rails 3. For instance, a definition like :

class Category
	name_scope :desert, :conditions => {:name => “Desert”}
	name_scope :fruit, :condition => {:name => “Fruit”}
end

Will become :

class Category
scope :desert, :conditions => {:name => “Desert”}
scope :fruit, :condition => {:name => “Fruit”}
end 

However, since using options hash is deprecated in Rails 3.1, therefore the new finder methods should be used in this case:

class Category
scope :desert, where {:name => “Desert”}
scope :fruit, where {:name => “Fruit”}
end 

At the end when you call these named scopes, you can simply do

desert = Category.desert
fruit = Category.fruit


The New DSL in Rails 3 Router

The Rails router is used to revognize URLs and dispatch them to a controller’s action. It can also generate paths and URLs, avoiding the need to hardcode strings in the views. <ref "Rails Routing from the Outside In" http://edgeguides.rubyonrails.org/routing.html/> In Rails 3, other than handing basic routes in the old Domain Specific Langauges (DSL), the new DSL has some advanced features that every developer will appreciate.

Comparing with the old DSL in Rails 2, the new DSL takes less keystroke and become more readable. For example, here is how DSL looks in Rails 2: <ref name="Revamped Routes in Rails 3" http://rizwanreza.com/2009/12/20/revamped-routes-in-rails-3/>

map.resources :products, :member => {:short => :post},
:collection => {:long => :get} do |products|
  products.resource :category
end

and now it looks like:

resources :products do
  resource :category
  
  member do
    post :short
  end
  
  collection do
    get :long
  end
end

As you can see, it looks very similar to the Ruby syntax, which becomes much cleaner and easier to understand.

Regular Route

Here is an example of how regular route looks like in Rails 2:

map.connect 'products/:id', :controller => 'catalog', :action => 'view'

Instead of defining keys for controller and action, you can now do:

match 'products/:id' => 'catalog#view'

which is less verbose and much simpler.

Empty Route

Empty route can be used to route to the root of the web site. Rails 2 uses

map.root :controller => "welcome", :action => 'show'

which has been now been simplified to

root :to => 'welcome#show'

RESTful Routes

The new RESTful route is one of the nicest enhancements in Rails 3 for developers. Let’s consider the Photos example <ref name="http://edgeguides.rubyonrails.org/routing.html"/> below. By simply calling

Resources :photos

the basic routes including index, new, create, show, edit, update and destroy will be created automatically for you, and mapped to the PhotosController in this case. Here is a table that can provide you more details about these routes.


References

<references/>