HASHROCKET EXPERTLY CRAFTED WEB

The Rich Get Richer: RAILS 3

PRESENTED BY OBIE FERNANDEZ

Sunday, December 5, 2010 About 20k USD

Sunday, December 5, 2010 About 45k USD

Sunday, December 5, 2010 About 200k USD

Sunday, December 5, 2010 “a few million dollars”

Sunday, December 5, 2010 Sunday, December 5, 2010 HASHROCKET EXPERTLY CRAFTED WEB

OMG RAILS 3 ROCKS SO MUCH MORE THAN RAILS 2!!!

PRESENTED BY OBIE FERNANDEZ

Sunday, December 5, 2010 How is Rails 3 Richer? mainstream adoption maturity performance open-source mindshare

CAUTION: JUST A METAPHOR

Sunday, December 5, 2010 Sunday, December 5, 2010 The Rich Get Richer: RAILS 3 OBIE FERNANDEZ

Presentation Overview

• History and Context • What’s new • ActiveRecord Performance • Impact on Application Development

Sunday, December 5, 2010 Sunday, December 5, 2010 Ezra Zygmuntovich

Sunday, December 5, 2010 [...] clocks in at 17,291 [loc]. Rails clocks in at 47,195. As you can see, it’s a tie.

Sunday, December 5, 2010 Yehuda Katz

Sunday, December 5, 2010 December 23, 2008

Sunday, December 5, 2010 David Heinemeir Hansson

Sunday, December 5, 2010 Tom Mornini

Photo Credit: Sebastian Delmont

Sunday, December 5, 2010 Tom Mornini

Photo Credit: Sebastian Delmont

Sunday, December 5, 2010 Sunday, December 5, 2010 Sunday, December 5, 2010 Q: How do you prevent bloating?

Ryan Sanchez's "Violet Beauregarde" ("Charlie and the Chocolate Factory") Photo by Tera Heater/ MTV News

Sunday, December 5, 2010 A: Decoupling

http://yestheykeepmebusy.blogspot.com/2009/11/willy-wonka- halloween.html

Sunday, December 5, 2010 A: Modularity

http://superpunch.blogspot.com/2009/10/lego-violet-beauregarde-and- more.html

Sunday, December 5, 2010 require 'active_support/concern' require 'active_support/ordered_options' require 'active_support/core_ext/kernel/singleton_class' require 'active_support/core_ext/module/delegation'

module ActiveSupport # Configurable provides a config method to store and retrieve # configuration options as an OrderedHash. module Configurable extend ActiveSupport::Concern

class Configuration < ActiveSupport::InheritableOptions def compile_methods! self.class.compile_methods!(keys.reject {|key| respond_to?(key)}) end

# compiles reader methods so we don't have to go through method_missing def self.compile_methods!(keys) keys.each do |key| class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{key}; _get(#{key.inspect}); end RUBY end end end ...

Sunday, December 5, 2010 Sunday, December 5, 2010 Rails 3.0 August 29, 2010

Sunday, December 5, 2010 SAVE YOURSELF, I’LL HOLD THEM BACK RIGHT NOW, I HOPE YOU’RE READY FOR A FIREFIGHT | ’CAUSE THE DEVIL’S GOT YOUR NUMBER TONIGHT | THEY SAY! | WE’RE NEVER LEAVING THIS PLACE ALIVE | BUT IF YOU SING THESE WORDS WE’LL NEVER DIE | GET OFF THE LEDGE AND DROP THE KNIFE | NOT A VICTIM OF A VICTIM’S LIFE | BECAUSE! | THIS AIN’T A ROOM FULL OF SUICIDES | WE’RE BELIEVERS. I BELIEVE TONIGHT | WE CAN LEAVE THIS WORLD LEAVE IT ALL BEHIND | WE CAN STEAL THIS CAR IF YOUR FOLKS DON’T MIND | WE CAN LIVE FOREVER IF YOU’VE GOT THE TIME | IF YOU SAVE YOURSELF TONIGHT | IF YOU SAVE YOURSELF TONIGHT | I’LL TELL YOU ALL HOW THE STORY ENDS | WHERE THE GOOD GUYS DIE AND THE BAD GUYS WIN | WHO CARES! | IT AIN’T ABOUT ALL THE FRIENDS YOU MADE | BUT THE GRAFFITI THEY WRITE ON YOUR GRAVE | FOR ALL OF US WHO’VE SEEN THE LIGHT | SALUTE THE DEAD AND LEAD THE FIGHT | HAIL HAIL! | WHO GIVES A DAMN IF WE LOSE THE WAR? | LET THE WALLS COME DOWN | LET THE ENGINES ROAR! | WE CAN LEAVE THIS WORLD LEAVE IT ALL BEHIND | WE CAN STEAL THIS CAR IF YOUR FOLKS DON’T MIND | WE CAN LIVE FOREVER IF YOU’VE GOT THE TIME | I’M THE ONLY FRIEND THAT MAKES YOU CRY | YOU’RE A HEART ATTACK IN BLACK HAIR DYE | SO JUST SAVE YOURSELF AND I’LL HOLD THEM BACK TONIGHT | BREAKDOWN | IF YOU SAVE YOURSELF TONIGHT | CAN YOU SAVE YOURSELF TONIGHT | RIGHT NOW! | ’CAUSE I’LL HOLD THEM BACK | WE CAN LEAVE THIS WORLD LEAVE IT ALL BEHIND | WE CAN STEAL THIS CAR IF YOUR FOLKS DON’T MIND | WE CAN LIVE FOREVER IF YOU’VE GOT THE TIME | YOU MOTHERFUCKER | YOU’RE THE BROKEN GLASS IN THE MORNING LIGHT | BE A BURNING STAR IF IT TAKES ALL NIGHT | SO JUST SAVE YOURSELF AND I’LL HOLD THEM BACK TONIGHT | IF YOU SAVE YOURSELF TONIGHT | CAN YOU SAVE YOURSELF TONIGHT?

S/C/A/R/E/C/R/O/W MOVE YOUR BODY WHEN THE SUNLIGHT DIES | EVERYBODY HIDE YOUR BODY FROM THE SCARECROW | EVERYBODY HIDE | MAKE A WISH WHEN YOUR CHILDHOOD DIES | HERE THE KNOCK KNOCK KNOCK WHEN SHE CRIES | WE’RE ALL ALONE TONIGHT | HOLD YOUR BREATH WHEN THE BLACKBIRD FLIES | COUNT TO 17 AND CLOSE YOUR EYES | I’LL KEEP YOU SAFE INSIDE | HE BURNS | MY SKIN | NEVER MIND ABOUT THE SHAPE I’M IN—I’LL KEEP YOU SAFE TONIGHT | MOVE YOUR BODY WHEN THE SUNLIGHT DIES | EVERYBODY HIDE YOUR BODY FROM THE SCARECROW | EVERYBODY HIDE | MOVE YOUR BODY WHEN THE SUNLIGHT DIES | EVERYBODY HIDE YOUR BODY FROM THE SCARECROW | EVERYBODY HIDE | BLOW A KISS AT THE METHANE SKIES | SEE THE RUST THROUGH YOUR PLAYGROUND EYES | WE’RE ALL IN LOVE TONIGHT | LEAVE A DREAM WHERE THE FALLOUT LIES | WATCH IT GROW WHERE THE TEARSTAIN DRIES | TO KEEP YOU SAFE TONIGHT | HE BURNS | MY SKIN | NEVER MIND ABOUT THE SHAPE I’M IN—I’LL KEEP YOU SAFE TONIGHT | MOVE YOUR BODY WHEN THE SUNLIGHT DIES | EVERYBODY HIDE YOUR BODY FROM THE SCARECROW | EVERYBODY HIDE | MOVE YOUR BODY WHEN THE SUNLIGHT DIES | EVERYBODY HIDE YOUR BODY FROM THE SCARECROW | EVERYBODY HIDE | LOVE, LOVE, LOVE WON’T STOP THIS | BOMB, BOMB, LOVE WON’T STOP THIS | BOMB, BOMB, LOVE WON’T STOP THIS BOMB | RUN, RUN, BUNNY, RUN | RUN, RUN, BUNNY, RUN | MOVE YOUR BODY WHEN THE SUNLIGHT DIES | EVERYBODY HIDE YOUR BODY FROM THE SCARECROW | EVERYBODY HIDE The Rich Get Richer: RAILS 3 OBIE FERNANDEZ

Notable Plugin Changes

• Formtastic 1.1 (made compatible) • InheritedResources 1.1 (rewritten) • Devise (significant upgrades) • RSpec 2 (rewritten) • EmailSpec 1.0 (rewritten) • MetaSearch (instead of Searchlogic)

Sunday, December 5, 2010 Sunday, December 5, 2010 Sunday, December 5, 2010 What’s new in Rails 3?

Sunday, December 5, 2010 Sunday, December 5, 2010 Sunday, December 5, 2010 config/routes.rb

Sunday, December 5, 2010 # This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment', __FILE__) run Example::Application

config.ru

Sunday, December 5, 2010 Rack::Cache ActionDispatch::Static Rack::Lock Rack::Runtime Rails::Rack::Logger ActionDispatch::ShowExceptions ActionDispatch::RemoteIp Rack::Sendfile ActionDispatch::Callbacks ActionDispatch::Cookies ActionDispatch::Flash ActionDispatch::ParamsParser Rack::MethodOverride ActionDispatch::Head Rack::ConditionalGet Rack::ETag ActionDispatch::BestStandardsSupport

Rails 3 Middleware “Stack”

Sunday, December 5, 2010 Sunday, December 5, 2010 Sunday, December 5, 2010 Sunday, December 5, 2010 gem "rails", "3.0.1" gem 'jquery-rails' gem "mysql" gem "haml", "3.0.18" gem "decent_exposure", "1.0.0.rc1" gem "devise", "1.1.3" gem "chronic", "0.2.3" gem "seed-fu", "1.2.3", :git => "git://github.com/supaspoida/seed-fu.git" gem "block_helpers", "0.3.3" gem "will_paginate", "3.0.pre2" gem "geokit", "1.5.0"

group :test do gem "", "0.3.9" gem 'database_cleaner', '0.5.0' gem 'launchy', '0.3.7' gem "rspec-rails", "2.0.1" gem "mocha", "0.9.9" gem "shoulda", "2.11.3" gem "selenium-webdriver" gem "timecop", "0.3.5" gem "watchr" gem "specjour", "0.3.1" gem "email_spec", "1.0.0" end Gemfile

Sunday, December 5, 2010 $ bundle Fetching source index for http://rubygems.org Using (0.8.7) Using abstract (1.0.0) Using activesupport (3.0.1) Using builder (2.1.2) Using i18n (0.4.2) Using activemodel (3.0.1) ...

Your bundle is complete! It was installed into /Users/obie/.rvm/gems/ruby-1.9.2- p0@example-application

Sunday, December 5, 2010 Sunday, December 5, 2010 Arel by Nick Kallen

Sunday, December 5, 2010 Sunday, December 5, 2010 “closure under composition”

Sunday, December 5, 2010 User.find :conditions => { :name => "obie" }

# in Rails 3 becomes

User.where(:name => "obie")

Sunday, December 5, 2010 >> u = User.where(first_name: "Pascale"); u.to_sql => "SELECT `users`.* FROM `users` WHERE (`users`.`first_name` = 'Pascale')

>> u.where(age: 21).to_sql => "SELECT `users`.* FROM `users` WHERE (`users`.`first_name` = 'Pascale') AND (`users`.`age` = 21)"

>> u.order(:name).limit(20).to_sql => "SELECT `users`.* FROM `users` WHERE (`users`.`first_name` = 'Pascale') ORDER BY name LIMIT 20"

Sunday, December 5, 2010 class Invitation < ActiveRecord::Base

default_scope order("created_at DESC") scope :accepted, where("accepted_at is NOT NULL") scope :pending, where(accepted_at: nil)

...

end

Scopes

Sunday, December 5, 2010 All of my open-sourced projects share two attributes. First, the source code is extremely stylized and meant to be /read/ more than /used/. They are literary arguments in code much more than a useful piece of infrastructure. If you read the source-code to Arel you will see a highly afected "combinator" and "interpreter" style of coding.

Nick Kallen

Sunday, December 5, 2010 “Holy shit, Rails 3 is slow!”

Sunday, December 5, 2010 #5098

Sunday, December 5, 2010 joins = [{:dim_locations=>[:dim_zip, {:dim_city=> {:dim_state=>:dim_country}}]}, :dim_ages, :dim_car_makes, :dim_educations, :dim_employments, :dim_foods, :dim_genders, :dim_get_aways, :dim_home_ownerships, :dim_incomes, :dim_marital_statuses, :dim_teams] conditions = ["(dim_zips.zip_code = ? OR dim_zips.zip_code IS NULL) AND (dim_cities.city = ? OR dim_cities.city IS NULL) AND (dim_states.state_code = ? OR dim_states.state_code IS NULL) AND (dim_states.state = ? OR dim_states.state IS NULL) AND (dim_countries.country_code = ? OR dim_countries.country_code IS NULL) AND (dim_countries.country = ? OR dim_countries.country IS NULL) AND (dim_ages.age = ? OR dim_ages.age IS NULL) AND (dim_car_makes.car_make IN (?) OR dim_car_makes.car_make IS NULL) AND (dim_educations.education = ? OR dim_educations.education IS NULL) AND (dim_employments.employment = ? OR dim_employments.employment IS NULL) AND (dim_foods.food IN (?) OR dim_foods.food IS NULL) AND (dim_genders.gender = ? OR dim_genders.gender IS NULL) AND (dim_get_aways.get_away IN (?) OR dim_get_aways.get_away IS NULL) AND (dim_home_ownerships.home_ownership = ? OR dim_home_ownerships.home_ownership IS NULL) AND (dim_incomes.income = ? OR dim_incomes.income IS NULL) AND (dim_marital_statuses.marital_status = ? OR dim_marital_statuses.marital_status IS NULL) AND (dim_teams.team IN (?) OR dim_teams.team IS NULL)", "98104", "Seattle", "WA", "Washington", "US", "United States of America", "18-34", ["Ashton Martin"], "Bachelors", "Full Time", ["Brazilian"], "Male", ["France"], "Rent", "Less than 30k", "Married", ["Arizona Cardinals", "Boston Bruins"]] Benchmark.measure do Koupon.includes(joins).where(conditions).each end => 127.930000 0.390000 128.320000 (129.897278)

Sunday, December 5, 2010 Sunday, December 5, 2010 O(n^2) vs O(n)

Sunday, December 5, 2010 routing

Sunday, December 5, 2010 ActionController::Routing::Routes.draw do |map| map.resources :schedules do |schedules| schedules.resource :timeslots end map.resources :sponsors, :member => {:enable => :post, :disable => :post} map.resources :talks map.root :controller => 'home', :action => 'index' end Rails 2.x

BizConf::Application::Routes.draw do resources :schedules do resource :timeslots end

resources :sponsors do post :enable, :disable end

resources :talks root :to => 'home#index' end config/routes.rb

Sunday, December 5, 2010 match "/api/v1/post/:id", :to => redirect("/api/article/%{id}")

Sunday, December 5, 2010 Sunday, December 5, 2010 ActionController

Sunday, December 5, 2010 THE ONLY HOPE FOR ME IS YOU REMEMBER ME | WHERE, WHERE WILL YOU STAND? | WHEN ALL THE LIGHTS GO OUT | ACROSS THESE CITY STREETS | WHERE WERE YOU WHEN | ALL OF THE EMBERS FELL | I STILL REMEMBER THEM | COVERED IN ASH, COVERED IN GLASS | COVERED IN ALL MY FRIENDS | I STILL THINK OF THE BOMBS THEY BUILD | IF THERE’S A PLACE THAT I COULD BE | THEN I’D BE ANOTHER MEMORY | CAN I BE THE ONLY HOPE FOR YOU | BECAUSE YOU’RE THE ONLY HOPE FOR ME | AND IF WE CAN’T FIND WHERE WE BELONG | WE’LL HAVE TO MAKE IT ON OUR OWN | FACE ALL THE PAIN AND TAKE IT ON | BECAUSE THE ONLY HOPE FOR ME | IS YOU ALONE | HOW IT SHOULD BE? | MANY YEARS AFTER THE DISASTERS THAT WE’VE SEEN | WHAT HAVE WE LEARNED? | OTHER THAN PEOPLE BURN IN PURIFYING FLAME | I SAY IT’S OKAY | I KNOW YOU CAN TELL | THOUGH YOU CAN SEE ME SMILE | I STILL THINK OF THE GUNS THEY SELL | IF THERE’S A PLACE THAT I COULD BE | THEN I’D BE ANOTHER MEMORY | CAN I BE THE ONLY HOPE FOR YOU | BECAUSE YOU’RE THE ONLY HOPE FOR ME | AND IF WE CAN’T FIND WHERE WE BELONG | WE’LL HAVE TO MAKE IT ON OUR OWN | FACE ALL THE PAIN AND TAKE IT ON | BECAUSE THE ONLY HOPE FOR ME | IS YOU ALONE | THE ONLY HOPE FOR ME | THE ONLY HOPE FOR ME | IS YOU, THE ONLY HOPE FOR ME | IS YOU, THE ONLY HOPE FOR ME | IS YOU, THE ONLY HOPE FOR ME | IS YOU, THE ONLY HOPE | IF THERE’S A PLACE THAT I COULD BE | THEN I’D BE ANOTHER MEMORY | CAN I BE THE ONLY HOPE FOR YOU | BECAUSE YOU’RE THE ONLY HOPE FOR ME | AND IF WE CAN’T FIND WHERE WE BELONG | WE’LL HAVE TO MAKE IT ON OUR OWN | FACE ALL THE PAIN AND TAKE IT ON | BECAUSE THE ONLY HOPE FOR ME IS YOU ALONE | THE ONLY HOPE FOR ME IS YOU ALONE

PARTY POISON EVERYBODY PAY ATTENTION TO ME | I GOT THE ANSWER | I GOT THE ANSWER | STREET WALKING CHEETAH WITH A CAPITOL G | SO GET YOUR HANDS UP, NOW GET YOUR HANDS UP | HIDE YOUR EYES, WE’RE GONNA SHINE TONIGHT | SUB-ATOMIC NEVER GET THE BEST OF ME | AIN’T A DJ GONNA SAVE MY SOUL | I SOLD IT LONG AGO FOR ROCK ’N’ ROLL | DROP THE NEEDLE WHEN THE TAPE DECK BLOWS | GOTTA SHOUT THIS OUT SO EVERYBODY KNOWS | THIS AIN’T A PARTY | GET OFF THE DANCE FLOOR | YOU WANT THE GET DOWN | HERE COMES THE GANG WAR | YOU’RE DOIN’ ALRIGHT | I GOT THE ANSWER | ’CAUSE ALL THE GOOD TIMES | THEY GIVE YOU CANCER | IF WE WERE ALL LIKE YOU IN THE END | OH WE’D BE KILLING OURSELVES BY SLEEPING IN | SO HIT THE LIGHTS I’LL DO IT AGAIN | AND KEEP YOUR CARS, AND YOUR DOGS AND YOUR FAMOUS FRIENDS | SLIDE UP THE FADERS WHEN THE CABINET SLAMS | AND GET YOUR HANDS UP, NOW GET YOUR HANDS UP | LIGHT UP THE STAGE AND WATCH ME KICK OUT THE JAMS | SO THROW YOUR FIST UP, NOW THROW YOUR FIST UP | AIN’T NOBODY GONNA TAKE MY LIFE | AIN’T NOBODY GONNA GET THE BEST OF ME | AIN’T A PREACHER GONNA SAVE ME NOW | GRAB A SEAT I’M GONNA SHOW YOU HOW | EVERYBODY HIT THE PYRO CUE | WE’RE GONNA BLOW THIS OFF AND SHOW YOU WHAT WE DO | THIS AIN’T A PARTY | GET OFF THE DANCE FLOOR | YOU WANT THE GET DOWN | HERE COMES THE GANG WAR | YOU’RE DOIN’ ALRIGHT | I GOT THE ANSWER | ’CAUSE ALL THE GOOD TIMES | THEY GIVE YOU CANCER | IF WE WERE ALL LIKE YOU IN THE END | WELL WE’D BE KILLING OURSELVES BY SLEEPING IN | SO HIT THE LIGHTS I’LL DO IT AGAIN | SO KEEP YOUR CARS, AND YOUR DOGS AND YOUR FAMOUS FRIENDS | WE CAME TO PARTY | KILL THE PARTY TONIGHT | WE CAME TO PARTY | KILL THE PARTY TONIGHT | LET’S GO | THIS AIN’T A PARTY | GET OFF THE DANCE FLOOR | YOU WANT THE GET DOWN | HERE COMES THE GANG WAR | YOU’RE DOIN’ ALRIGHT | I GOT THE ANSWER | ‘CAUSE ALL THE GOOD TIMES | GIMME GIMME GOOD TIMES PEOPLE TONIGHT | THIS AIN’T A PARTY | GET OFF THE DANCE FLOOR | YOU WANNA GET DOWN | HERE COMES THE ENCORE | IF WE WERE ALL LIKE YOU IN THE END | OH WE’D BE KILLING OURSELVES BY SLEEPING IN | SO HIT THE LIGHTS I’LL DO IT AGAIN | SO EVERYBODY GET DOWN | TILL THE PARTY BREAKS DOWN | NOW EVERYBODY GET DOWN | NOW EVERYBODY GET DOWN TILL THE PARTY BREAKS DOWN TONIGHT

AbstractController::Base

ActionController::Metal

ActionController::Base

ApplicationController

Sunday, December 5, 2010 ActionController::Metal

Sunday, December 5, 2010 require 'mongo'

class GridfsController < ActionController::Metal def serve gridfs_path = env["PATH_INFO"].gsub("/images/", "") begin fs = Mongo::GridFileSystem.new(Mongoid.database) gridfs_file = fs.open(gridfs_path, 'r') self.response_body = gridfs_file.read self.content_type = gridfs_file.content_type rescue self.status = :file_not_found self.content_type = 'text/plain' self.response_body = '' end end end

http://socialmemorycomplex.net/2010/06/02/gridfs-with-mongoid-and-carrierwave-on-rails-3/

Sunday, December 5, 2010 ActionMailer

Sunday, December 5, 2010 $ rails Usage: rails COMMAND [ARGS]

The most common rails commands are: generate Generate new code (short-cut alias: "g") console Start the Rails console (short-cut alias: "c") server Start the Rails server (short-cut alias: "s") dbconsole Start a console for database in config/database.yml (short-cut alias: "db") new Create a new Rails application. "rails new my_app" creates a new application called MyApp in "./my_app"

In addition to those, there are: application Generate the Rails application code destroy Undo code generated with "generate" benchmarker See how fast a piece of code runs profiler Get profile information from a piece of code plugin Install a plugin runner Run a piece of code in the application environment

Sunday, December 5, 2010 The Rich Get Richer: RAILS 3 OBIE FERNANDEZ

Upgrade Path?

• Upgrade to 2.3.8 and Bundler

• Try http://github.com/rails/rails_upgrade • Upgrade to 3.0.x

• rails console working

• rails console production working • (unit) tests or specs green • (integration specs) green

Sunday, December 5, 2010 Sunday, December 5, 2010 Sunday, December 5, 2010 Ryan Bigg Rails 3 Documentation Project

MAKE YOUR DONATION AT http://pledgie.com/ campaigns/14034

Sunday, December 5, 2010 Q/A

Sunday, December 5, 2010 PROGRA MMING/R UBY ON RAI LS A ddison-Wesley Professional Ruby S eries FERNKAESANDEZ The Bible for Application Development “The Rails 3 Way is a Ruby on Rails strips complexity from the development process, enabling comprehensive resource professional developers to focus on what matters most: delivering business that digs into the new value via clean and maintainable code. The Rails™ 3 Way is the only features in Rails 3 and comprehensive, authoritative guide to delivering production-quality code with Rails 3. Pioneering Rails expert Obie Fernandez and a team of leading experts perhaps more importantly, T illuminate the entire Rails 3 API, along with the idioms, design approaches, the rationale behind them.” and libraries that make developing applications with Rails so powerful. HE Drawing on their unsurpassed experience and track record, they address —YEHUDA KATZ, Rails Core the real challenges development teams face, showing how to use Rails 3 to maximize your productivity.

Using numerous detailed code examples, the author systematically covers OBIE FERNANDEZ has been Rails 3 key capabilities and subsystems, making this book a reference that hacking computers since he got his R you will turn to again and again. He presents advanced Rails programming first Commodore VIC-20 in the eighties, techniques that have been proven effective in day-to-day usage on dozens of and found himself in the right place and production Rails systems and offers important insights into behavior-driven

time as a programmer on some of the AILS development and production considerations such as scalability. Dive deep into first Java enterprise projects of the the Rails 3 codebase and discover why Rails is designed the way it is—and mid-nineties. Obie has been evangelizing how to make it do what you want it to do. Ruby on Rails online via blog posts This book will help you and publications since early 2005. Q Learn what’s new in Rails 3 He has traveled around the world relentlessly promoting Rails at large Q Increase your productivity as a web application developer industry conferences. As CEO and Q Realize the overall joy in programming with Rails Founder of Hashrocket, Obie specializes ™ Q Leverage Rails’ powerful capabilities for building REST-compliant APIs in orchestrating the creation of 3 W Q Drive implementation and protect long-term maintainability using RSpec large-scale, web-based applications, ™ Q Design and manipulate your domain layer using Active Record both for startups and mission-critical Q Understand and program complex program flows using Action Controller enterprise projects. He still gets his hands THE RAILS 3 WAY Q Master sophisticated URL routing concepts dirty with code on at least a weekly basis Q Use Ajax techniques via Rails 3 support for unobtrusive JavaScript and posts regularly on various topics Q Learn to extend Rails with popular gems and plugins, and how to to his popular technology blog. write your own AY Q Extend Rails with the best third-party plug-ins and write your own Q Integrate email services into your applications with Action Mailer Forewords by David Heinemeier Hansson, creator of Ruby on Rails Q Improve application responsiveness with background processing and Yehuda Katz, Rails Core Q Create your own non-Active Record domain classes using Active Model Q Master Rails’ utility classes and extensions in Active Support obiefernandez.com hashrocket.com informit.com/ruby tr3w.com

ISBN-13: 978-0-321-60166-7 Cover design by Chuti Prasertsith ISBN-10: 0-321-60166-1 OBIE FERNANDEZ Cover photograph by Grant Faint/Getty Images Inc. 54999

Text printed on recycled paper with DURRAN JORDAN, JON LARKOWSKI, 9 780321 601667 XAVIER NORIA, and TIM POPE $49.99 U.S. | $59.99 CANADA

Sunday, December 5, 2010 HASHROCKET EXPERTLY CRAFTED WEB

Thank you

Obie Fernandez [email protected]

Sunday, December 5, 2010