Rails For Kids 2009

  • 1,644 views
Uploaded on

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

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,644
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
35
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Tuesday, December 15, 2009
  • 2. 13 e 14 Outubro 2009 Tuesday, December 15, 2009
  • 3. 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
  • 4. 25/07/2004 Tuesday, December 15, 2009
  • 5. • Action Pack • Action Controller • Action View • Active Record • Action Mailer Tuesday, December 15, 2009
  • 6. Tuesday, December 15, 2009
  • 7. Tuesday, December 15, 2009
  • 8. Tuesday, December 15, 2009
  • 9. Tuesday, December 15, 2009
  • 10. 13/12/2005 Tuesday, December 15, 2009
  • 11. • db/schema.rb • config/environment.rb • lib/tasks (Rakefile) • scripts (stubs) • vendor/plugins Tuesday, December 15, 2009
  • 12. • 2 vezes mais rápido • FCGI melhor • Inflector • session (ActiveRecordStore) • rake freeze_gems Tuesday, December 15, 2009
  • 13. Tuesday, December 15, 2009
  • 14. Tuesday, December 15, 2009
  • 15. Tuesday, December 15, 2009
  • 16. Tuesday, December 15, 2009
  • 17. Tuesday, December 15, 2009
  • 18. Tuesday, December 15, 2009
  • 19. Tuesday, December 15, 2009
  • 20. Tuesday, December 15, 2009
  • 21. Tuesday, December 15, 2009
  • 22. Tuesday, December 15, 2009
  • 23. Tuesday, December 15, 2009
  • 24. Tuesday, December 15, 2009
  • 25. Tuesday, December 15, 2009
  • 26. Tuesday, December 15, 2009
  • 27. > 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::Base end Tuesday, December 15, 2009
  • 28. 28/03/2006 Tuesday, December 15, 2009
  • 29. Tuesday, December 15, 2009
  • 30. Tuesday, December 15, 2009
  • 31. Tuesday, December 15, 2009
  • 32. Tuesday, December 15, 2009
  • 33. Tuesday, December 15, 2009
  • 34. Tuesday, December 15, 2009
  • 35. 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
  • 36. page['cartbox'].replace :partial => 'cart' page['num_items'].replace :partial => 'num_items' page["product_#{params[:id]}"].addClassName 'incart' Tuesday, December 15, 2009
  • 37. 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 end end Tuesday, December 15, 2009
  • 38. 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 end end Tuesday, December 15, 2009
  • 39. Tuesday, December 15, 2009
  • 40. > script/plugin install git://github.com/rails/ exception_notification.git # config/initializers/exception.rb ExceptionNotifier.sender_address = %("Application Error" <railssummit@locaweb.com.br>) ExceptionNotifier.exception_recipients = %w(fabioakita@gmail.com fabio.akita@locaweb.com.br) ExceptionNotifier.email_prefix = "[railssummit] " # app/controllers/application_controller.rb class ApplicationController < ActionController::Base include ExceptionNotifiable ... end Tuesday, December 15, 2009
  • 41. > script/plugin install git://github.com/rails/ exception_notification.git # config/initializers/exception.rb ExceptionNotifier.sender_address = %("Application Error" <railssummit@locaweb.com.br>) ExceptionNotifier.exception_recipients = %w(fabioakita@gmail.com fabio.akita@locaweb.com.br) ExceptionNotifier.email_prefix = "[railssummit] " # app/controllers/application_controller.rb class ApplicationController < ActionController::Base include ExceptionNotifiable ... end Tuesday, December 15, 2009
  • 42. > 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
  • 43. class User < ActiveRecord::Base acts_as_authentic end • OpenID • LDAP • Facebook Connect • OAuth (Twitter) Tuesday, December 15, 2009
  • 44. 19/01/2007 Tuesday, December 15, 2009
  • 45. Tuesday, December 15, 2009
  • 46. Tuesday, December 15, 2009
  • 47. Tuesday, December 15, 2009
  • 48. Tuesday, December 15, 2009
  • 49. Tuesday, December 15, 2009
  • 50. Tuesday, December 15, 2009
  • 51. Tuesday, December 15, 2009
  • 52. Tuesday, December 15, 2009
  • 53. # GET /weblog # GET /weblog.xml # GET /weblog.rss class 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 end end Tuesday, December 15, 2009
  • 54. /comments/1;edit Tuesday, December 15, 2009
  • 55. /comments/1;edit Tuesday, December 15, 2009
  • 56. Tuesday, December 15, 2009
  • 57. Tuesday, December 15, 2009
  • 58. 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! end end Tuesday, December 15, 2009
  • 59. light = TrafficLight.new light.color # => "green" light.cycle! light.color # => "yellow" light.cycle! light.color # => "red" light.cycle! light.color # => "green" • Acts As State Machine (AASM) • Alter Ego • State-Fu http://jmettraux.wordpress.com/2009/07/03/state-machine-workflow-engine/ Tuesday, December 15, 2009
  • 60. 07/12/2007 Tuesday, December 15, 2009
  • 61. • 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
  • 62. map.namespace(:admin) do |admin| admin.resources :products, :collection => { :inventory => :get }, :member => { :duplicate => :post }, :has_many => [ :tags, :images, :variants ] end # /avatars/45 => AvatarsController#show map.resources :avatars # /people/5/avatar => AvatarsController#show map.resources :people, :has_one => :avatar Tuesday, December 15, 2009
  • 63. # config/initializers/mime_types.rb Mime.register_alias "text/html", :iphone # app/controllers/application.rb 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 Tuesday, December 15, 2009
  • 64. # config/initializers/mime_types.rb Mime.register_alias "text/html", :iphone # app/controllers/application.rb 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 Tuesday, December 15, 2009
  • 65. # config/initializers/mime_types.rb Mime.register_alias "text/html", :iphone # app/controllers/application.rb 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 Tuesday, December 15, 2009
  • 66. # app/controllers/posts_controller.rb class PostsController < ApplicationController def index respond_to do |format| format.html # renders index.html.erb format.iphone # renders index.iphone.erb end end end Tuesday, December 15, 2009
  • 67. # app/controllers/posts_controller.rb class PostsController < ApplicationController def index respond_to do |format| format.html # renders index.html.erb format.iphone # renders index.iphone.erb end end end Tuesday, December 15, 2009
  • 68. 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 end end Tuesday, December 15, 2009
  • 69. 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 end end Tuesday, December 15, 2009
  • 70. 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
  • 71. 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
  • 72. class PostsController < ApplicationController rescue_from User::NotAuthorized, :with => :deny_access protected def deny_access ... end end Tuesday, December 15, 2009
  • 73. class PostsController < ApplicationController rescue_from User::NotAuthorized, :with => :deny_access protected def deny_access ... end end Tuesday, December 15, 2009
  • 74. # 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 => 'ec54b1c89c810d5937ede6b2969ee227c7653ffaffb37927a71203ef968 7928d256572ae5c8e66efbf0b9686103b597c3bae537b813fc838580c794 248c428da' } Tuesday, December 15, 2009
  • 75. 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 create_table :people do |t| t.integer :account_id t.string :first_name, :last_name, :null => false t.text :description t.timestamps end Tuesday, December 15, 2009
  • 76. # sellers.yml shopify: name: Shopify # products.yml pimp_cup: seller: shopify name: Pimp cup Tuesday, December 15, 2009
  • 77. Tuesday, December 15, 2009
  • 78. # config/environments.rb config.gem "mbleigh-acts-as-taggable-on", :lib => "acts-as-taggable-on", :source => "http://gems.github.com" # app/models/user.rb class User < ActiveRecord::Base acts_as_taggable_on :tags, :skills, :interests named_scope :by_join_date, :order => "created_at DESC" end Tuesday, December 15, 2009
  • 79. # config/environments.rb config.gem "mbleigh-acts-as-taggable-on", :lib => "acts-as-taggable-on", :source => "http://gems.github.com" # app/models/user.rb class User < ActiveRecord::Base acts_as_taggable_on :tags, :skills, :interests named_scope :by_join_date, :order => "created_at DESC" end Tuesday, December 15, 2009
  • 80. @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_date User.tagged_with("awesome").by_date.paginate( :page => params[:page], :per_page => 20) Tuesday, December 15, 2009
  • 81. # config/environments.rb config.gem 'laserlemon-vestal_versions', :lib => 'vestal_versions', :source => 'http://gems.github.com' > script/generate vestal_versions_migration > rake db:migrate # app/model/user.rb class User < ActiveRecord::Base versioned end >> u.version => 1 >> u.update_attribute(:first_name, 'Stephen') => true >> u.version => 2 >> u.revert_to(:first) => 1 Tuesday, December 15, 2009
  • 82. # config/environments.rb config.gem 'laserlemon-vestal_versions', :lib => 'vestal_versions', :source => 'http://gems.github.com' > script/generate vestal_versions_migration > rake db:migrate # app/model/user.rb class User < ActiveRecord::Base versioned end >> u.version => 1 >> u.update_attribute(:first_name, 'Stephen') => true >> u.version => 2 >> u.revert_to(:first) => 1 Tuesday, December 15, 2009
  • 83. 01/06/2008 Tuesday, December 15, 2009
  • 84. # config/environment.rb config.time_zone = 'UTC' $ rake time:zones:local * UTC -06:00 * Central America Central 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
  • 85. 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? #=> true article.save #=> true article.changed? #=> false Tuesday, December 15, 2009
  • 86. 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
  • 87. 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 usage User.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
  • 88. > script/generate migration post create db/migrate/20080402122512_post.rb Tuesday, December 15, 2009
  • 89. Tuesday, December 15, 2009
  • 90. # db/migrate/001_add_avatar_columns_to_userrb class 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.rb class 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
  • 91. # db/migrate/001_add_avatar_columns_to_userrb class 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.rb class 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
  • 92. 21/11/2008 Tuesday, December 15, 2009
  • 93. # 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
  • 94. 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
  • 95. 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) end end Tuesday, December 15, 2009
  • 96. 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) end end Tuesday, December 15, 2009
  • 97. 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) end end Tuesday, December 15, 2009
  • 98. # config/environments/production.rb: config.threadsafe! # config/database.yml development: adapter: mysql username: root database: myapp_dev pool: 10 Tuesday, December 15, 2009
  • 99. # config/routes.rb map.resources :publishers, :shallow => true do |publisher| publisher.resources :magazines do |magazine| magazine.resources :photos end end # /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
  • 100. # antes def full_name @full_name ||= "#{first_name} #{last_name}" end # depois extend ActiveSupport::Memoizable def full_name "#{first_name} #{last_name}" end memoize :full_name Tuesday, December 15, 2009
  • 101. class Vendor < ActiveRecord::Base has_one :account delegate :email, :password, :to => :account, :prefix => true end # @vendor.account_email # @vendor.account_password class Vendor < ActiveRecord::Base has_one :account delegate :email, :password, :to => :account, :prefix => :owner end # @vendor.owner_email # @vendor.owner_password Tuesday, December 15, 2009
  • 102. class UserMailer < ActionMailer::Base def registration(user) subject "You've registered" from "system@example.com" end end # layouts/user_mailer.html.erb class UserMailer < ActionMailer::Base layout 'email' ... end # layouts/email.html.erb Tuesday, December 15, 2009
  • 103. Tuesday, December 15, 2009
  • 104. 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
  • 105. # locales/i18n_routes.yml es: edit: editar new: crear users: usuarios # config/routes.rb ActionController::Routing::Routes.draw do |map| map.resources :users map.root :controller => 'users' end #ActionController::Routing::Translator.i18n ActionController::Routing::Translator.translate_from_file 'locales', 'i18n-routes.yml' # app/controllers/application_controller.rb class ApplicationController < ActionController::Base before_filter :set_locale_from_url ... end Tuesday, December 15, 2009
  • 106. > 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
  • 107. 16/03/2009 Tuesday, December 15, 2009
  • 108. • 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
  • 109. > rake middleware use Rack::Lock use ActionController::Failsafe use ActionController::Session::CookieStore use ActionController::ParamsParser use Rack::MethodOverride use Rack::Head use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache run ActionController::Dispatcher.new Tuesday, December 15, 2009
  • 110. # app/metal/poller.rb class 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 end end # app/controllers/old_poller_controller.rb class OldPollerController < ApplicationController def poller render :text => "Hello World!" end end Tuesday, December 15, 2009
  • 111. # benchmark the traditional controller $ ab -n 1000 http://127.0.0.1:3000/old_poller/poller Requests 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/poller Requests per second: 1154.66 [#/sec] (mean) Time per request: 0.866 [ms] (mean) Tuesday, December 15, 2009
  • 112. <% 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
  • 113. <% 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
  • 114. class 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)} end end Tuesday, December 15, 2009
  • 115. class Project < ActiveRecord::Base has_many :tasks accept_nested_attributes_for :tasks, :allow_destroy => true end Tuesday, December 15, 2009
  • 116. <% 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
  • 117. <% 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
  • 118. User.transaction do User.create(:username => 'Admin') User.transaction(:requires_new => true) do User.create(:username => 'Regular') raise ActiveRecord::Rollback end end User.find(:all) # => Returns only Admin Tuesday, December 15, 2009
  • 119. 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
  • 120. 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
  • 121. class Article < ActiveRecord::Base default_scope :order => 'created_at DESC' end Article.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 block Article.with_exclusive_scope { find(:all) } #=> "SELECT * FROM `articles` Tuesday, December 15, 2009
  • 122. class Article < ActiveRecord::Base default_scope :order => 'created_at DESC' end Article.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 block Article.with_exclusive_scope { find(:all) } #=> "SELECT * FROM `articles` Tuesday, December 15, 2009
  • 123. 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
  • 124. 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
  • 125. 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
  • 126. 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
  • 127. 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
  • 128. 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
  • 129. # template.rb run "rm public/index.html" generate(:scaffold, "person name:string") route "map.root :controller => 'people'" rake("db:migrate") git :init git :add => "." git :commit => "-a -m 'Initial commit'" > rake rails:template LOCATION=~/template.rb Tuesday, December 15, 2009
  • 130. def remove_email(email) emails.find_by_email(email).try(:destroy) end Tuesday, December 15, 2009
  • 131. def remove_email(email) emails.find_by_email(email).try(:destroy) end Tuesday, December 15, 2009
  • 132. XmlMini.backend = 'LibXML' XmlMini.backend = 'Nokogiri' Tuesday, December 15, 2009
  • 133. Tuesday, December 15, 2009
  • 134. > script/plugin install git://github.com/ddollar/rack-debug.git # config/environments/development.rb config.middleware.use "Rack::Debug" # app/controllers/users_controller.rb ... @user = User.find(params[:id]) debugger render :show ... > rake debug Connected. # 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
  • 135. > script/plugin install git://github.com/ddollar/rack-debug.git # config/environments/development.rb config.middleware.use "Rack::Debug" # app/controllers/users_controller.rb ... @user = User.find(params[:id]) debugger render :show ... > rake debug Connected. # 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
  • 136. > 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
  • 137. • 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
  • 138. Tuesday, December 15, 2009
  • 139. Tuesday, December 15, 2009
  • 140. Tuesday, December 15, 2009
  • 141. Tuesday, December 15, 2009
  • 142. Tuesday, December 15, 2009