Rails For Kids 2009

142
Ruby on Rails Evolução Tuesday, December 15, 2009
  • date post

    11-Sep-2014
  • Category

    Technology

  • view

    16
  • download

    1

description

Evolução do Ruby on Rails através dos anos. Dia 12/set.

Transcript of Rails For Kids 2009

Page 1: Rails For Kids 2009

Ruby on RailsEvolução

Tuesday, December 15, 2009

Page 2: Rails For Kids 2009

13 e 14Outubro

2009Tuesday, December 15, 2009

Page 3: Rails For Kids 2009

07/2004 0.5

12/2005 1.0

03/2006 1.1

01/2007 1.2

12/2007 2.0

06/2008 2.1

11/2008 2.2

03/2009 2.3

Tuesday, December 15, 2009

Page 4: Rails For Kids 2009

Rails 0.525/07/2004

Tuesday, December 15, 2009

Page 5: Rails For Kids 2009

• Action Pack

• Action Controller

• Action View

• Active Record

• Action Mailer

Tuesday, December 15, 2009

Page 6: Rails For Kids 2009

Tuesday, December 15, 2009

Page 7: Rails For Kids 2009

Tuesday, December 15, 2009

Page 8: Rails For Kids 2009

Tuesday, December 15, 2009

Page 9: Rails For Kids 2009

Tuesday, December 15, 2009

Page 10: Rails For Kids 2009

Rails 1.013/12/2005

Tuesday, December 15, 2009

Page 11: Rails For Kids 2009

• db/schema.rb

• config/environment.rb

• lib/tasks (Rakefile)

• scripts (stubs)

• vendor/plugins

Tuesday, December 15, 2009

Page 12: Rails For Kids 2009

• 2 vezes mais rápido

• FCGI melhor

• Inflector

• session (ActiveRecordStore)

• rake freeze_gems

Tuesday, December 15, 2009

Page 13: Rails For Kids 2009

Tuesday, December 15, 2009

Page 14: Rails For Kids 2009

Tuesday, December 15, 2009

Page 15: Rails For Kids 2009

Tuesday, December 15, 2009

Page 16: Rails For Kids 2009

Tuesday, December 15, 2009

Page 17: Rails For Kids 2009

Tuesday, December 15, 2009

Page 18: Rails For Kids 2009

Tuesday, December 15, 2009

Page 19: Rails For Kids 2009

Tuesday, December 15, 2009

Page 20: Rails For Kids 2009

Tuesday, December 15, 2009

Page 21: Rails For Kids 2009

Tuesday, December 15, 2009

Page 22: Rails For Kids 2009

Tuesday, December 15, 2009

Page 23: Rails For Kids 2009

Tuesday, December 15, 2009

Page 24: Rails For Kids 2009

Tuesday, December 15, 2009

Page 25: Rails For Kids 2009

Tuesday, December 15, 2009

Page 26: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 27: Rails For Kids 2009

Annotate Models

> sudo gem install ctran-annotate_models> annotate

# == Schema Information## Table name: posts## id :integer not null, primary key# title :string(255)# body :text# created_at :datetime# updated_at :datetime#

class Post < ActiveRecord::Baseend

Tuesday, December 15, 2009

Page 28: Rails For Kids 2009

Rails 1.128/03/2006

Tuesday, December 15, 2009

Page 29: Rails For Kids 2009

Tuesday, December 15, 2009

Page 30: Rails For Kids 2009

Tuesday, December 15, 2009

Page 31: Rails For Kids 2009

Tuesday, December 15, 2009

Page 32: Rails For Kids 2009

Tuesday, December 15, 2009

Page 33: Rails For Kids 2009

Tuesday, December 15, 2009

Page 34: Rails For Kids 2009

Tuesday, December 15, 2009

Page 35: Rails For Kids 2009

RJS Templates (.rjs)

var Cart = { add: function(product_id) { Element.addClassName('product_' + product_id, 'incart') new Ajax.Request('/account/add_to_cart/' + product_id, { method: 'post', onComplete: Cart.refresh }) }, remove: function(product_id) { Element.removeClassName('product_' + product_id, 'incart') new Ajax.Request('/account/remove_from_cart/' + product_id, { method: 'post', onComplete: Cart.refresh }) }, refresh: function() { new Ajax.Updater('cartbox', '/products/cartbox') new Ajax.Updater('num_items', '/products/num_items') }}

Tuesday, December 15, 2009

Page 36: Rails For Kids 2009

RJS Templates (.rjs)

page['cartbox'].replace :partial => 'cart'page['num_items'].replace :partial => 'num_items'page["product_#{params[:id]}"].addClassName 'incart'

Tuesday, December 15, 2009

Page 37: Rails For Kids 2009

respond_to e to_xml

def create @comment = Comment.create(params[:id])

respond_to do |type| type.html { redirect_to :action => "index" } type.js type.xml do headers["Location"] = url_for(:action => "show", :id => @comment.id) @comment.to_xml end endend

Tuesday, December 15, 2009

Page 38: Rails For Kids 2009

respond_to e to_xml

def create @comment = Comment.create(params[:id])

respond_to do |type| type.html { redirect_to :action => "index" } type.js type.xml do headers["Location"] = url_for(:action => "show", :id => @comment.id) @comment.to_xml end endend

Tuesday, December 15, 2009

Page 39: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 40: Rails For Kids 2009

Exception Notification

> script/plugin install git://github.com/rails/exception_notification.git

# config/initializers/exception.rbExceptionNotifier.sender_address = %("Application Error" <[email protected]>)

ExceptionNotifier.exception_recipients = %w([email protected] [email protected])

ExceptionNotifier.email_prefix = "[railssummit] "

# app/controllers/application_controller.rbclass ApplicationController < ActionController::Base include ExceptionNotifiable ...end

Tuesday, December 15, 2009

Page 41: Rails For Kids 2009

Exception Notification

> script/plugin install git://github.com/rails/exception_notification.git

# config/initializers/exception.rbExceptionNotifier.sender_address = %("Application Error" <[email protected]>)

ExceptionNotifier.exception_recipients = %w([email protected] [email protected])

ExceptionNotifier.email_prefix = "[railssummit] "

# app/controllers/application_controller.rbclass ApplicationController < ActionController::Base include ExceptionNotifiable ...end

Tuesday, December 15, 2009

Page 42: Rails For Kids 2009

Authlogic

> sudo gem install binarylogic-authlogic

UserSession.create(:login => "bjohnson", :password => "my password", :remember_me => true) session = UserSession.new(:login => "bjohnson", :password => "my password", :remember_me => true); session.save

UserSession.create(:openid_identifier => "identifier", :remember_me => true) # requires the authlogic-oid "add on" gem UserSession.create(my_user_object, true) # skip authentication and log the user in directly, # the true means "remember me"

Tuesday, December 15, 2009

Page 43: Rails For Kids 2009

Authlogic

• OpenID

• LDAP

• Facebook Connect

• OAuth (Twitter)

class User < ActiveRecord::Base acts_as_authenticend

Tuesday, December 15, 2009

Page 44: Rails For Kids 2009

Rails 1.219/01/2007

Tuesday, December 15, 2009

Page 45: Rails For Kids 2009

Tuesday, December 15, 2009

Page 46: Rails For Kids 2009

Tuesday, December 15, 2009

Page 47: Rails For Kids 2009

Tuesday, December 15, 2009

Page 48: Rails For Kids 2009

Tuesday, December 15, 2009

Page 49: Rails For Kids 2009

Tuesday, December 15, 2009

Page 50: Rails For Kids 2009

Tuesday, December 15, 2009

Page 51: Rails For Kids 2009

Tuesday, December 15, 2009

Page 52: Rails For Kids 2009

Tuesday, December 15, 2009

Page 53: Rails For Kids 2009

Restful Resources

# GET /weblog# GET /weblog.xml# GET /weblog.rssclass WeblogController < ActionController::Base def index @posts = Post.find :all respond_to do |format| format.html format.xml { render :xml => @posts.to_xml } format.rss { render :action => "feed.rxml" } end endend

Tuesday, December 15, 2009

Page 54: Rails For Kids 2009

Custom Restful Actions

/comments/1;edit

Tuesday, December 15, 2009

Page 55: Rails For Kids 2009

Custom Restful Actions

/comments/1;edit

Tuesday, December 15, 2009

Page 56: Rails For Kids 2009

Unicode

Tuesday, December 15, 2009

Page 57: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 58: Rails For Kids 2009

State Machines

class TrafficLight include AlterEgo

state :proceed, :default => true do handle :color { "green" } transition :to => :caution, :on => :cycle! end

state :caution do handle :color { "yellow" } transition :to => :stop, :on => :cycle! end

state :stop do handle :color { "red" } transition :to => :proceed, :on => :cycle! endend

Tuesday, December 15, 2009

Page 59: Rails For Kids 2009

State Machines

• Acts As State Machine (AASM)

• Alter Ego

• State-Fu

light = TrafficLight.newlight.color # => "green"light.cycle!light.color # => "yellow"light.cycle!light.color # => "red"light.cycle!light.color # => "green"

http://jmettraux.wordpress.com/2009/07/03/state-machine-workflow-engine/

Tuesday, December 15, 2009

Page 60: Rails For Kids 2009

Rails 2.007/12/2007

Tuesday, December 15, 2009

Page 61: Rails For Kids 2009

• from_xml e serialização json

• plugins retirados (acts_as_list, etc)

• with_scope (privado)

• - ActiveWebService + ActiveResource

• config/initializers

• debugger (ruby-debug)

• SQLite3 por padrão

Tuesday, December 15, 2009

Page 62: Rails For Kids 2009

Namespaced Routes

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

# /avatars/45 => AvatarsController#showmap.resources :avatars

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

Tuesday, December 15, 2009

Page 63: Rails For Kids 2009

Mime-Types e Multi Views

# config/initializers/mime_types.rbMime.register_alias "text/html", :iphone

# app/controllers/application.rbclass 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 endend

Tuesday, December 15, 2009

Page 64: Rails For Kids 2009

Mime-Types e Multi Views

# config/initializers/mime_types.rbMime.register_alias "text/html", :iphone

# app/controllers/application.rbclass 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 endend

Tuesday, December 15, 2009

Page 65: Rails For Kids 2009

Mime-Types e Multi Views

# config/initializers/mime_types.rbMime.register_alias "text/html", :iphone

# app/controllers/application.rbclass 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 endend

Tuesday, December 15, 2009

Page 66: Rails For Kids 2009

Mime-Types e Multi Views

# app/controllers/posts_controller.rbclass PostsController < ApplicationController def index respond_to do |format| format.html # renders index.html.erb format.iphone # renders index.iphone.erb end endend

Tuesday, December 15, 2009

Page 67: Rails For Kids 2009

Mime-Types e Multi Views

# app/controllers/posts_controller.rbclass PostsController < ApplicationController def index respond_to do |format| format.html # renders index.html.erb format.iphone # renders index.iphone.erb end endend

Tuesday, December 15, 2009

Page 68: Rails For Kids 2009

HTTP Basic Authentication

class PostsController < ApplicationController before_filter :authenticate, :except => [ :index ]

def index render :text => "Everyone can see me!" end def edit render :text => "I’m not publicly accessible" end

private def authenticate authenticate_or_request_with_http_basic do |user_name, password| user_name == "dhh" && password == "secret" end endend

Tuesday, December 15, 2009

Page 69: Rails For Kids 2009

HTTP Basic Authentication

class PostsController < ApplicationController before_filter :authenticate, :except => [ :index ]

def index render :text => "Everyone can see me!" end def edit render :text => "I’m not publicly accessible" end

private def authenticate authenticate_or_request_with_http_basic do |user_name, password| user_name == "dhh" && password == "secret" end endend

Tuesday, December 15, 2009

Page 70: Rails For Kids 2009

proteção contra CSRF

class ApplicationController < ActionController::Base helper :all # include all helpers, all the time

# See ActionController::RequestForgeryProtection for # details # Uncomment the :secret if you're not using the # cookie session store protect_from_forgery # :secret => # '9b76dcad7de4d8eca67e9d53329006ac'end

Tuesday, December 15, 2009

Page 71: Rails For Kids 2009

proteção contra CSRF

class ApplicationController < ActionController::Base helper :all # include all helpers, all the time

# See ActionController::RequestForgeryProtection for # details # Uncomment the :secret if you're not using the # cookie session store protect_from_forgery # :secret => # '9b76dcad7de4d8eca67e9d53329006ac'end

Tuesday, December 15, 2009

Page 72: Rails For Kids 2009

Tratamento de Exceções

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

protected def deny_access ... endend

Tuesday, December 15, 2009

Page 73: Rails For Kids 2009

Tratamento de Exceções

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

protected def deny_access ... endend

Tuesday, December 15, 2009

Page 74: Rails For Kids 2009

Session Cookie Store

# Your secret key for verifying cookie session data # integrity. If you change this key, all old sessions # will become invalid! Make sure the secret is at least # 30 characters and all random, no regular words or you'll # be exposed to dictionary attacks. config.action_controller.session = { :session_key => '_my_app_session', :secret => 'ec54b1c89c810d5937ede6b2969ee227c7653ffaffb37927a71203ef9687928d256572ae5c8e66efbf0b9686103b597c3bae537b813fc838580c794248c428da' }

Tuesday, December 15, 2009

Page 75: Rails For Kids 2009

Sexy Migrations

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", :datetimeend

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

Tuesday, December 15, 2009

Page 76: Rails For Kids 2009

Foxy Fixtures

# sellers.ymlshopify: name: Shopify

# products.ymlpimp_cup: seller: shopify name: Pimp cup

Tuesday, December 15, 2009

Page 77: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 78: Rails For Kids 2009

Acts as Taggable

# config/environments.rbconfig.gem "mbleigh-acts-as-taggable-on", :lib => "acts-as-taggable-on", :source => "http://gems.github.com" # app/models/user.rbclass User < ActiveRecord::Base acts_as_taggable_on :tags, :skills, :interests named_scope :by_join_date, :order => "created_at DESC"end

Tuesday, December 15, 2009

Page 79: Rails For Kids 2009

Acts as Taggable

# config/environments.rbconfig.gem "mbleigh-acts-as-taggable-on", :lib => "acts-as-taggable-on", :source => "http://gems.github.com" # app/models/user.rbclass User < ActiveRecord::Base acts_as_taggable_on :tags, :skills, :interests named_scope :by_join_date, :order => "created_at DESC"end

Tuesday, December 15, 2009

Page 80: Rails For Kids 2009

Acts as Taggable

@user.tag_list = "awesome, slick, hefty" @user.skill_list = "joking, clowning, boxing" @user.skill_list # => ["joking","clowning","boxing"]@user.save

# The better way (utilizes named_scope)User.tagged_with("awesome", :on => :tags) # => [@user]User.tagged_with("awesome", :on => :skills) # => []

User.tagged_with("awesome").by_dateUser.tagged_with("awesome").by_date.paginate( :page => params[:page], :per_page => 20)

Tuesday, December 15, 2009

Page 81: Rails For Kids 2009

Model Versions# config/environments.rbconfig.gem 'laserlemon-vestal_versions', :lib => 'vestal_versions', :source => 'http://gems.github.com'

> script/generate vestal_versions_migration> rake db:migrate

# app/model/user.rbclass User < ActiveRecord::Base versionedend

>> u.version=> 1>> u.update_attribute(:first_name, 'Stephen')=> true>> u.version=> 2>> u.revert_to(:first)=> 1

Tuesday, December 15, 2009

Page 82: Rails For Kids 2009

Model Versions# config/environments.rbconfig.gem 'laserlemon-vestal_versions', :lib => 'vestal_versions', :source => 'http://gems.github.com'

> script/generate vestal_versions_migration> rake db:migrate

# app/model/user.rbclass User < ActiveRecord::Base versionedend

>> u.version=> 1>> u.update_attribute(:first_name, 'Stephen')=> true>> u.version=> 2>> u.revert_to(:first)=> 1

Tuesday, December 15, 2009

Page 83: Rails For Kids 2009

Rails 2.101/06/2008

Tuesday, December 15, 2009

Page 84: Rails For Kids 2009

Time Zones

# config/environment.rbconfig.time_zone = 'UTC'

$ rake time:zones:local* UTC -06:00 *Central AmericaCentral Time (US &amp; Canada)Guadalajara...

>> t = Task.find_by_name('foo')=> #< Task ... >>> t.alert_at=> Sun, 06 Apr 2008 10:30:00 CDT -05:00>> t.alert_at_before_type_cast=> "2008-04-06 15:30:00"

Tuesday, December 15, 2009

Page 85: Rails For Kids 2009

Dirty tracking

article = Article.find(:first)article.changed? # => false

article.title # => "Title"article.title = "New Title"article.title_changed? # => true

article.title_was #=> "Title"article.title_change #=> ["Title", "New Title"]

article.changed #=> ['title']article.changes #=> { 'title' => ["Title", "New Title"] }

article.changed? #=> truearticle.save #=> truearticle.changed? #=> false

Tuesday, December 15, 2009

Page 86: Rails For Kids 2009

Gem Dependencies

Rails::Initializer.run do |config| # Require the latest version of haml config.gem "haml"

config.gem "chronic", :version => '0.2.3'

config.gem "akitaonrails-locarails", :source => "http://gems.github.com"

config.gem "aws-s3", :lib => "aws/s3" end

# rake gems:install# rake gems:unpack

Tuesday, December 15, 2009

Page 87: Rails For Kids 2009

Named Scopes

class User < ActiveRecord::Base named_scope :active, :conditions => {:active => true} named_scope :inactive, :conditions => {:active => false} named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }end

# Standard usageUser.active # User.find(:all, :conditions => {:active => true})User.inactive # User.find(:all, :conditions => {:active => false})User.recent # User.find(:all, :conditions => ['created_at > ?', 1.week.ago])

# They're nest-able too!User.active.recent

# same as:# User.with_scope(:conditions => {:active => true}) do# User.find(:all, :conditions => ['created_at > ?', 1.week.ago])# end

Tuesday, December 15, 2009

Page 88: Rails For Kids 2009

migrações timestamped

> script/generate migration post create db/migrate/20080402122512_post.rb

Tuesday, December 15, 2009

Page 89: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 90: Rails For Kids 2009

Paperclip

# db/migrate/001_add_avatar_columns_to_userrbclass AddAvatarColumnsToUser < ActiveRecord::Migration def self.up add_column :users, :avatar_file_name, :string add_column :users, :avatar_content_type, :string add_column :users, :avatar_file_size, :integer add_column :users, :avatar_updated_at, :datetime end ...end

# app/models/user.rbclass User < ActiveRecord::Base has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }end

# app/views/users/new.html.erb<% form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %> <%= form.file_field :avatar %><% end %>

Tuesday, December 15, 2009

Page 91: Rails For Kids 2009

Paperclip

# db/migrate/001_add_avatar_columns_to_userrbclass AddAvatarColumnsToUser < ActiveRecord::Migration def self.up add_column :users, :avatar_file_name, :string add_column :users, :avatar_content_type, :string add_column :users, :avatar_file_size, :integer add_column :users, :avatar_updated_at, :datetime end ...end

# app/models/user.rbclass User < ActiveRecord::Base has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }end

# app/views/users/new.html.erb<% form_for :user, @user, :url => user_path, :html => { :multipart => true } do |form| %> <%= form.file_field :avatar %><% end %>

Tuesday, December 15, 2009

Page 92: Rails For Kids 2009

Rails 2.221/11/2008

Tuesday, December 15, 2009

Page 93: Rails For Kids 2009

i18n# config/locales/pt-BR.yml--- pt-BR: abbreviation: Abreviação access_denied: "Acesso Negado" account: Conta account_updated: "Conta Atualizada!" action: Ação actions: cancel: Cancelar create: Criar destroy: Destruir list: Lista listing: Listagem new: Nova update: Atualizar

Tuesday, December 15, 2009

Page 94: Rails For Kids 2009

i18n

flash[:notice] = I18n.t(:basket_successfully_cleared)

flash[:notice] = t('order_processed_successfully')

<tr> <th colspan="2"><%= t("item") %></th> <th><%= t("price") %></th> <th><%= t("qty") %></th> <th><%= t("total") %></th></tr>

Tuesday, December 15, 2009

Page 95: Rails For Kids 2009

E-Tag e Last-Modified

class ArticlesController < ApplicationController def show_with_respond_to_block @article = Article.find(params[:id]) # unless stale? => "304 Not Modified" if stale?(:last_modified => @article.published_at.utc, :etag => @article) respond_to do |wants| # normal response processing end end end def show_with_implied_render @article = Article.find(params[:id]) # If fresh => "304 Not Modified" fresh_when(:last_modified => @article.published_at.utc, :etag => @article) endend

Tuesday, December 15, 2009

Page 96: Rails For Kids 2009

E-Tag e Last-Modified

class ArticlesController < ApplicationController def show_with_respond_to_block @article = Article.find(params[:id]) # unless stale? => "304 Not Modified" if stale?(:last_modified => @article.published_at.utc, :etag => @article) respond_to do |wants| # normal response processing end end end def show_with_implied_render @article = Article.find(params[:id]) # If fresh => "304 Not Modified" fresh_when(:last_modified => @article.published_at.utc, :etag => @article) endend

Tuesday, December 15, 2009

Page 97: Rails For Kids 2009

E-Tag e Last-Modified

class ArticlesController < ApplicationController def show_with_respond_to_block @article = Article.find(params[:id]) # unless stale? => "304 Not Modified" if stale?(:last_modified => @article.published_at.utc, :etag => @article) respond_to do |wants| # normal response processing end end end def show_with_implied_render @article = Article.find(params[:id]) # If fresh => "304 Not Modified" fresh_when(:last_modified => @article.published_at.utc, :etag => @article) endend

Tuesday, December 15, 2009

Page 98: Rails For Kids 2009

Thread safe e Connection Pool (JRuby)

# config/environments/production.rb:config.threadsafe!

# config/database.ymldevelopment: adapter: mysql username: root database: myapp_dev pool: 10

Tuesday, December 15, 2009

Page 99: Rails For Kids 2009

Shallow Route Nesting

# config/routes.rbmap.resources :publishers, :shallow => true do |publisher| publisher.resources :magazines do |magazine| magazine.resources :photos endend

# /publishers/1 ==> publisher_path(1)# /publishers/1/magazines ==> publisher_magazines_path(1)# /magazines/2 ==> magazine_path(2)# /magazines/2/photos ==> magazines_photos_path(2)# /photos/3 ==> photo_path(3)

Tuesday, December 15, 2009

Page 100: Rails For Kids 2009

Memoization

# antesdef full_name @full_name ||= "#{first_name} #{last_name}"end

# depoisextend ActiveSupport::Memoizabledef full_name "#{first_name} #{last_name}"endmemoize :full_name

Tuesday, December 15, 2009

Page 101: Rails For Kids 2009

Delegates com Prefixes

class Vendor < ActiveRecord::Base has_one :account delegate :email, :password, :to => :account, :prefix => trueend# @vendor.account_email# @vendor.account_password

class Vendor < ActiveRecord::Base has_one :account delegate :email, :password, :to => :account, :prefix => :ownerend# @vendor.owner_email# @vendor.owner_password

Tuesday, December 15, 2009

Page 102: Rails For Kids 2009

Mailer Layouts

class UserMailer < ActionMailer::Base def registration(user) subject "You've registered" from "[email protected]" endend# layouts/user_mailer.html.erb

class UserMailer < ActionMailer::Base layout 'email' ...end# layouts/email.html.erb

Tuesday, December 15, 2009

Page 103: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 104: Rails For Kids 2009

Brazilian Rails

sudo gem install brazilian-rails

>> require 'brazilian-rails'=> ["PROJECTS"]

>> Dinheiro.new(256.55).por_extenso=> "duzentos e cinquenta e seis reais e cinquenta e cinco centavos"

>> Cnpj.new("691036040001-60").to_s=> "69.103.604/0001-60"

>> Date.new(2009,1,25).to_s_br=> "25/01/2009"

>> Time.new.strftime("%B")=> "Setembro"

Tuesday, December 15, 2009

Page 105: Rails For Kids 2009

Translated Routes

# locales/i18n_routes.ymles: edit: editar new: crear users: usuarios # config/routes.rbActionController::Routing::Routes.draw do |map| map.resources :users map.root :controller => 'users'end

#ActionController::Routing::Translator.i18nActionController::Routing::Translator.translate_from_file 'locales', 'i18n-routes.yml'

# app/controllers/application_controller.rbclass ApplicationController < ActionController::Base before_filter :set_locale_from_url ...end

Tuesday, December 15, 2009

Page 106: Rails For Kids 2009

Translated Routes

> script/plugin install git://github.com/raul/translate_routes.git

> rake routes

users_es GET /es/usuarios(.:format) {:action=>"index", ..:locale=>"es"} users_en GET /users(.:format) {:action=>"index", ..:locale=>"en"} POST /es/usuarios(.:format) {:action=>"create", ..:locale=>"es"} POST /users(.:format) {:action=>"create", ..:locale=>"en"} new_user_es GET /es/usuarios/crear(.:format) {:action=>"new", ..:locale=>"es"} new_user_en GET /users/new(.:format) {:action=>"new", ..:locale=>"en"}edit_user_es GET /es/usuarios/:id/editar(.:format) {:action=>"edit", ..:locale=>"es"}edit_user_en GET /users/:id/edit(.:format) {:action=>"edit", ..:locale=>"en"} user_es GET /es/usuarios/:id(.:format) {:action=>"show", ..:locale=>"es"} user_en GET /users/:id(.:format) {:action=>"show", ..:locale=>"en"} PUT /es/usuarios/:id(.:format) {:action=>"update", ..:locale=>"es"} PUT /users/:id(.:format) {:action=>"update", ..:locale=>"en"} DELETE /es/usuarios/:id(.:format) {:action=>"destroy", ..:locale=>"es"} DELETE /users/:id(.:format) {:action=>"destroy", ..:locale=>"en"} root_es /es {..:action=>"index", :locale=>"es"} root_en / {..:action=>"index", :locale=>"en"}

Tuesday, December 15, 2009

Page 107: Rails For Kids 2009

Rails 2.316/03/2009

Tuesday, December 15, 2009

Page 108: Rails For Kids 2009

• Rails Engines (limitado)

• Suporte Ruby 1.9.1

• Rack-based Lazy-loaded Sessions

• Quieter Backtrace

• Localized Views (show.da.html.erb)

• MySQL Conn. Reconnection

• Seed Data (db/seeds.rb)

Tuesday, December 15, 2009

Page 109: Rails For Kids 2009

Rack Support

> rake middleware

use Rack::Lockuse ActionController::Failsafeuse ActionController::Session::CookieStoreuse ActionController::ParamsParseruse Rack::MethodOverrideuse Rack::Headuse ActiveRecord::ConnectionAdapters::ConnectionManagementuse ActiveRecord::QueryCacherun ActionController::Dispatcher.new

Tuesday, December 15, 2009

Page 110: Rails For Kids 2009

Rails Metal

# app/metal/poller.rbclass Poller < Rails::Rack::Metal def call(env) if env["PATH_INFO"] =~ /^\/poller/ [200, {"Content-Type" => "text/html"}, "Hello, World!"] else [404, {"Content-Type" => "text/html"}, "Not Found"] end endend

# app/controllers/old_poller_controller.rbclass OldPollerController < ApplicationController def poller render :text => "Hello World!" endend

Tuesday, December 15, 2009

Page 111: Rails For Kids 2009

Rails Metal

# benchmark the traditional controller$ ab -n 1000 http://127.0.0.1:3000/old_poller/pollerRequests per second: 408.45 [#/sec] (mean)Time per request: 2.448 [ms] (mean)

# benchmark the Metal middleware$ ab -n 1000 http://127.0.0.1:3000/pollerRequests per second: 1154.66 [#/sec] (mean)Time per request: 0.866 [ms] (mean)

Tuesday, December 15, 2009

Page 112: Rails For Kids 2009

Nested Model Forms

<% form_for @project do |project_form| %> <div> <%= project_form.label :name, 'Project name:' %> <%= project_form.text_field :name %> </div>

<% @project.tasks.each do |task| %> <% new_or_existing = task.new_record? ? 'new' : 'existing' %> <% prefix = "project[#{new_or_existing}_task_attributes][]" %> <% fields_for prefix, task do |task_form| %> <p> <div> <%= task_form.label :name, 'Task:' %> <%= task_form.text_field :name %> </div>

<% unless task.new_record? %> <div> <%= task_form.label :_delete, 'Remove:' %> <%= task_form.check_box :_delete %> </div> <% end %> </p> <% end %> <% end %>

<%= project_form.submit %><% end %>

Tuesday, December 15, 2009

Page 113: Rails For Kids 2009

Nested Model Forms

<% form_for @project do |project_form| %> <div> <%= project_form.label :name, 'Project name:' %> <%= project_form.text_field :name %> </div>

<% @project.tasks.each do |task| %> <% new_or_existing = task.new_record? ? 'new' : 'existing' %> <% prefix = "project[#{new_or_existing}_task_attributes][]" %> <% fields_for prefix, task do |task_form| %> <p> <div> <%= task_form.label :name, 'Task:' %> <%= task_form.text_field :name %> </div>

<% unless task.new_record? %> <div> <%= task_form.label :_delete, 'Remove:' %> <%= task_form.check_box :_delete %> </div> <% end %> </p> <% end %> <% end %>

<%= project_form.submit %><% end %>

Tuesday, December 15, 2009

Page 114: Rails For Kids 2009

Nested Model Formsclass Project < ActiveRecord::Base after_update :save_tasks validates_associated :tasks

def new_task_attributes=(task_attributes) task_attributes.each { |attr| tasks.build(attr) } end

def existing_task_attributes=(task_attributes) tasks.reject(&:new_record?).each do |task| attributes = task_attributes[task.id.to_s] if attributes['_delete'] == '1' tasks.delete(task) else task.attributes = attributes end end end

private def save_tasks tasks.each { |task| task.save(false)} endend

Tuesday, December 15, 2009

Page 115: Rails For Kids 2009

Nested Model Forms

class Project < ActiveRecord::Base has_many :tasks

accept_nested_attributes_for :tasks, :allow_destroy => trueend

Tuesday, December 15, 2009

Page 116: Rails For Kids 2009

Nested Model Forms

<% form_for @project do |project_form| %> <div> <%= project_form.label :name, 'Project name:' %> <%= project_form.text_field :name %> </div>

<% project_form.fields_for :tasks do |task_form| %> <p> <div> <%= task_form.label :name, 'Task:' %> <%= task_form.text_field :name %> </div>

<% unless task_form.object.new_record? %> <div> <%= task_form.label :_delete, 'Remove:' %> <%= task_form.check_box :_delete %> </div> <% end %> </p> <% end %> <% end %>

<%= project_form.submit %><% end %>

Tuesday, December 15, 2009

Page 117: Rails For Kids 2009

Nested Model Forms

<% form_for @project do |project_form| %> <div> <%= project_form.label :name, 'Project name:' %> <%= project_form.text_field :name %> </div>

<% project_form.fields_for :tasks do |task_form| %> <p> <div> <%= task_form.label :name, 'Task:' %> <%= task_form.text_field :name %> </div>

<% unless task_form.object.new_record? %> <div> <%= task_form.label :_delete, 'Remove:' %> <%= task_form.check_box :_delete %> </div> <% end %> </p> <% end %> <% end %>

<%= project_form.submit %><% end %>

Tuesday, December 15, 2009

Page 118: Rails For Kids 2009

Nested Transactions

User.transaction do User.create(:username => 'Admin') User.transaction(:requires_new => true) do User.create(:username => 'Regular') raise ActiveRecord::Rollback endend

User.find(:all) # => Returns only Admin

Tuesday, December 15, 2009

Page 119: Rails For Kids 2009

Dynamic Scopes

Order.scoped_by_customer_id(12)Order.scoped_by_customer_id(12).find(:all, :conditions => "status = 'open'")Order.scoped_by_customer_id(12).scoped_by_status("open")

Tuesday, December 15, 2009

Page 120: Rails For Kids 2009

Dynamic Scopes

Order.scoped_by_customer_id(12)Order.scoped_by_customer_id(12).find(:all, :conditions => "status = 'open'")Order.scoped_by_customer_id(12).scoped_by_status("open")

Tuesday, December 15, 2009

Page 121: Rails For Kids 2009

Default Scopes

class Article < ActiveRecord::Base default_scope :order => 'created_at DESC'endArticle.find(:all) #=> "SELECT * FROM `articles` ORDER BY created_at DESC"

class Article < ActiveRecord::Base default_scope :order => 'created_at DESC' named_scope :published, :conditions => { :published => true }end

Article.published #=> "SELECT * FROM `articles` WHERE published = true # ORDER BY created_at DESC"

# Ignore other scoping within this blockArticle.with_exclusive_scope { find(:all) } #=> "SELECT * FROM `articles`

Tuesday, December 15, 2009

Page 122: Rails For Kids 2009

Default Scopes

class Article < ActiveRecord::Base default_scope :order => 'created_at DESC'endArticle.find(:all) #=> "SELECT * FROM `articles` ORDER BY created_at DESC"

class Article < ActiveRecord::Base default_scope :order => 'created_at DESC' named_scope :published, :conditions => { :published => true }end

Article.published #=> "SELECT * FROM `articles` WHERE published = true # ORDER BY created_at DESC"

# Ignore other scoping within this blockArticle.with_exclusive_scope { find(:all) } #=> "SELECT * FROM `articles`

Tuesday, December 15, 2009

Page 123: Rails For Kids 2009

Batch Processing

Article.find_each { |a| ... } # => iterate over all articles, in chunks of 1000 (the default) Article.find_each(:conditions => { :published => true }, :batch_size => 100 ) { |a| ... } # iterate over published articles in chunks of 100

Article.find_in_batches do |articles| articles.each { |a| ... } end # => articles is array of size 1000 Article.find_in_batches(batch_size => 100 ) do |articles| articles.each { |a| ... } end # iterate over all articles in chunks of 100

Article.published.find_in_batches(:batch_size => 100 ) do |articles| ...end # iterate over published articles in chunks of 100

Tuesday, December 15, 2009

Page 124: Rails For Kids 2009

Batch Processing

Article.find_each { |a| ... } # => iterate over all articles, in chunks of 1000 (the default) Article.find_each(:conditions => { :published => true }, :batch_size => 100 ) { |a| ... } # iterate over published articles in chunks of 100

Article.find_in_batches do |articles| articles.each { |a| ... } end # => articles is array of size 1000 Article.find_in_batches(batch_size => 100 ) do |articles| articles.each { |a| ... } end # iterate over all articles in chunks of 100

Article.published.find_in_batches(:batch_size => 100 ) do |articles| ...end # iterate over published articles in chunks of 100

Tuesday, December 15, 2009

Page 125: Rails For Kids 2009

Batch Processing

Article.find_each { |a| ... } # => iterate over all articles, in chunks of 1000 (the default) Article.find_each(:conditions => { :published => true }, :batch_size => 100 ) { |a| ... } # iterate over published articles in chunks of 100

Article.find_in_batches do |articles| articles.each { |a| ... } end # => articles is array of size 1000 Article.find_in_batches(batch_size => 100 ) do |articles| articles.each { |a| ... } end # iterate over all articles in chunks of 100

Article.published.find_in_batches(:batch_size => 100 ) do |articles| ...end # iterate over published articles in chunks of 100

Tuesday, December 15, 2009

Page 126: Rails For Kids 2009

HTTP Digest Authentication

class ArticlesController < ApplicationController before_filter :digest_authenticate def digest_authenticate s = authenticate_or_request_with_http_digest("Admin") do |username| (@user = User.find_by_username(username)).try(cleartext_password) end

# If authentication succeeds, log the user in. # If not, kick back out a failure # message as the response body if s session[:user_id] = @user.id else request_http_digest_authentication("Admin", "Authentication failed") end end

end

Tuesday, December 15, 2009

Page 127: Rails For Kids 2009

HTTP Digest Authentication

class ArticlesController < ApplicationController before_filter :digest_authenticate def digest_authenticate s = authenticate_or_request_with_http_digest("Admin") do |username| (@user = User.find_by_username(username)).try(cleartext_password) end

# If authentication succeeds, log the user in. # If not, kick back out a failure # message as the response body if s session[:user_id] = @user.id else request_http_digest_authentication("Admin", "Authentication failed") end end

end

Tuesday, December 15, 2009

Page 128: Rails For Kids 2009

HTTP Digest Authentication

class ArticlesController < ApplicationController before_filter :digest_authenticate def digest_authenticate s = authenticate_or_request_with_http_digest("Admin") do |username| (@user = User.find_by_username(username)).try(cleartext_password) end

# If authentication succeeds, log the user in. # If not, kick back out a failure # message as the response body if s session[:user_id] = @user.id else request_http_digest_authentication("Admin", "Authentication failed") end end

end

Tuesday, December 15, 2009

Page 129: Rails For Kids 2009

Application Templates

# template.rbrun "rm public/index.html"generate(:scaffold, "person name:string")route "map.root :controller => 'people'"rake("db:migrate")

git :initgit :add => "."git :commit => "-a -m 'Initial commit'"

> rake rails:template LOCATION=~/template.rb

Tuesday, December 15, 2009

Page 130: Rails For Kids 2009

Object#try

def remove_email(email) emails.find_by_email(email).try(:destroy) end

Tuesday, December 15, 2009

Page 131: Rails For Kids 2009

Object#try

def remove_email(email) emails.find_by_email(email).try(:destroy) end

Tuesday, December 15, 2009

Page 132: Rails For Kids 2009

XML Backends

XmlMini.backend = 'LibXML'XmlMini.backend = 'Nokogiri'

Tuesday, December 15, 2009

Page 133: Rails For Kids 2009

Plugins/Gems

Tuesday, December 15, 2009

Page 134: Rails For Kids 2009

Rack Middlewares

> script/plugin install git://github.com/ddollar/rack-debug.git

# config/environments/development.rbconfig.middleware.use "Rack::Debug"

# app/controllers/users_controller.rb...@user = User.find(params[:id])debuggerrender :show...

> rake debugConnected.

# refresh a page in your browser, your app will break at debugger statements(rdb:1) p @user#<User id: 1, name: "...">

http://github.com/rtomayko/rack-contrib/tree/master

Tuesday, December 15, 2009

Page 135: Rails For Kids 2009

Rack Middlewares

> script/plugin install git://github.com/ddollar/rack-debug.git

# config/environments/development.rbconfig.middleware.use "Rack::Debug"

# app/controllers/users_controller.rb...@user = User.find(params[:id])debuggerrender :show...

> rake debugConnected.

# refresh a page in your browser, your app will break at debugger statements(rdb:1) p @user#<User id: 1, name: "...">

http://github.com/rtomayko/rack-contrib/tree/master

Tuesday, December 15, 2009

Page 136: Rails For Kids 2009

SQL Server Adapter

> gem install dbi --version 0.4.1> gem install dbd-odbc --version 0.2.4> gem install activerecord-sqlserver-adapter

create_table :sql_server_custom_types, :force => true do |t| t.column :ten_code, :char, :limit => 10 t.column :ten_code_utf8, :nchar, :limit => 10 t.column :title_utf8, :nvarchar t.column :body, :varchar_max # varchar(max) t.column :body_utf8, :ntext t.column :body2_utf8, :nvarchar_max # nvarchar(max)end

Tuesday, December 15, 2009

Page 137: Rails For Kids 2009

• Testes (Rspec, Cucumber)

• Async (Delayed Job)

• Monitoramento (New Relic)

• Escalabilidade (Data Fabric)

• Bancos de Dados (CouchDB, Mongo)

• Life Cycle (Capistrano, Integrity, Puppet)

Tuesday, December 15, 2009

Page 138: Rails For Kids 2009

Tuesday, December 15, 2009

Page 139: Rails For Kids 2009

Tuesday, December 15, 2009

Page 140: Rails For Kids 2009

Tuesday, December 15, 2009

Page 141: Rails For Kids 2009

Tuesday, December 15, 2009