Beautiful Code in Rails 3: Gregg Pollack
Beautiful Code in Rails 3: Gregg Pollack
by
Gregg Pollack
Options:
‐O, [‐‐skip‐activerecord] # Skip ActiveRecord files
‐r, [‐‐ruby=PATH] # Path to the Ruby binary of your choice
# Default: /Users/greggpollack/.rvm/rubies/ruby‐
‐T, [‐‐skip‐testunit] # Skip TestUnit files
[‐‐dev] # Setup the application with Gemfile pointing
to your rails checkout
‐J, [‐‐skip‐prototype] # Skip Prototype files
‐G, [‐‐skip‐git] # Skip Git ignores and keeps
‐m, [‐‐template=TEMPLATE] # Path to an application template
‐d, [‐‐database=DATABASE] # Preconfigure for selected database
[‐‐edge] # Setup the application with Gemfile
# pointing to Rails repository
$ rails test_app
create $ ls script/
create README
create .gitignore
...
$ cd test_app/
rails
$ rails
Usage: rails COMMAND [ARGS]
The most common rails commands are:
generate Generate new code (short‐cut alias: "g")
c
console Start the Rails console (short‐cut alias: " ")
s
server Start the Rails server (short‐cut alias: " ")
dbconsole Start a console for the database specified in config/database.yml
(short‐cut alias: "db")
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
All commands can be run with ‐h for more information.
old scripts new hotness
script/generate rails g
script/console rails c
script/server rails s
script/dbconsole rails db
old scripts new hotness
script/generate r g
script/console r c
script/server r s
script/dbconsole r db
alias r='rails'
New Router API
New Routing API
config/routes.rb
TestApp::Application.routes.draw do |map|
map.resources :posts
end
New Routing API
config/routes.rb
TestApp::Application.routes.draw do |map|
resources :posts
end
New Routing API
Rails 2
map.resources :posts do |post|
post.resources :comments
end
Rails 3
resources :posts do
resources :comments
end
New Routing API
Rails 2
map.resources :posts, :member => { :confirm => :post, :notify => :post } do |post|
post.resources :comments, :member => { :preview => :post }, :collection => { :archived => :get }
end
Rails 3
resources :posts do
member do Rails 3
post :confirm
resources :posts do
get :notify
member do
end
post :confirm
get :notify
resources :comments do
end
member do
post :preview
resources :comments do
end
post :preview, :on => :member
get :archived, :on => :collection
collection do
end
get :archived
end
end
end
end
Rails 2
map.connect 'login', :controller => 'session', :action => 'new'
Rails 3
match 'login' => 'session#new'
Rails 3
match 'login' => 'session#new', :as => :login
New Routing API
Rails 2
map.root :controller => "users"
Rails 3
root :to => "users#index"
Rails 3
match ':controller(/:action(/:id(.:format)))'
def index
@users = User.all
respond_to do |format|
format.html
format.xml { render :xml => @users.to_xml }
end
end
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
...
New ActionController Syntax
Improved Syntax
class UsersController < ApplicationController
respond_to :html, :xml, :json
def index
@users = User.all
respond_with(@users)
end
def show
@user = User.find(params[:id])
respond_with(@user)
end
...
Mikel L i n ds aa r
ActionMailer
New ActionMailer Syntax
Rails 2
$script/generate mailer UserMailer welcome forgot_password
create app/models/user_mailer.rb
Rails 3
$r g mailer UserMailer welcome forgot_password
create app/mailers/user_mailer.rb
New ActionMailer Syntax
Rails 2
def welcome(user, subdomain)
subject 'Welcome to TestApp'
recipients user.email
from '[email protected]'
UserMailer.deliver_welcome(user, subdomain)
Rails 3
def welcome(user, subdomain)
@user = user
@subdomain = subdomain
UserMailer.welcome(user, subdomain).deliver
New ActionMailer Syntax
Rails 3
class UserMailer < ActionMailer::Base
attachments['test.pdf'] = File.read("#{Rails.root}/public/test.pdf")
end
welcome.text.erb
Defaults welcome.html.erb
Nic k K al l e n
ActiveRelation
Rails 3
@posts = Post.where(:published => true)
if params[:order]
@posts = @posts.order(params[:order])
end
@posts.each do |p|
...
Que
end ry r
uns
here
Lazy Loading
We can refactor!
@posts = Post.where(:published => true)
if params[:order]
@posts = @posts.order(params[:order])
end
@posts = @posts.order(params[:order])
posts = Post.order(params[:order])
@published = Post.published
@unpublished = Post.unpublished
ActiveRelation
@published = Post.published
@unpublished = Post.unpublished
Rails 2
class Post < ActiveRecord::Base
default_scope :order => 'title'
Rails 3
class Post < ActiveRecord::Base
default_scope order('title')
Rails 2
Post.find(:all, :conditions => {:author => "Joe"}, :includes => :comments,
:order => "title", :limit => 10)
Rails 3
Post.where(:author => "Joe").include(:comments).order(:title).limit(10)
ActiveRecord ActiveRelation
ActionView Erubis
Rails 2 Rails 2
<%= @post.body %> <%= h @post.body %>
(unsafe) (safe)
Rails 3 Rails 3
<%= raw @post.body %> <%= @post.body %>
(unsafe) (safe)
Adopting Unobtrusive Javascript
data-remote
data-method
data-confirm
data-disable-with
Adopting Unobtrusive Javascript
Rails 2
<%= link_to_remote 'Show', :url => post %>
Rails 3
<%= link_to 'Show', post, :remote => true %>
Rails 2
<% remote_form_for(@post) do |f| %>
Rails 3
<% form_for(@post, :remote => true) do |f| %>
Rails 2 Rails 3
<%= link_to 'Destroy', post, :method => :delete %>
Rails 2 Rails 3
<%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %>
Rails 2
<%= f.submit 'Create Post', :disable_with => "Please wait..." %>
Rails 3
<%= f.submit :disable_with => "Please wait..." %>
data-remote
data-method
data-confirm
data-disable-with
/public/stylesheets/rails.js
document.observe("dom:loaded", function() {
$(document.body).observe("click", function(event) {
$('a[data-confirm],input[data-confirm]').live('click', function () {
// ... Do a confirm box
});
prototype_legacy_helper
http://github.com/rails/prototype_legacy_helper
Beautiful Code in Rails 3
Bundler
http://railscasts.com/episodes/201-bundler
http://envylabs.com
Come to our Rails 3 training at
Railsconf 2010
Gregg Pollack
http://bit.ly/rails3ropes
407-754-5517
[email protected]
We’re also available to run Rails 3
Training at your company, email:
Ruby5 Podcast [email protected]
http://ruby5.envylabs.com