SlideShare ist ein Scribd-Unternehmen logo
1 von 142
Downloaden Sie, um offline zu lesen
Tuesday, December 15, 2009
13 e 14
                             Outubro

                             2009
Tuesday, December 15, 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
25/07/2004




Tuesday, December 15, 2009
• Action Pack
                • Action Controller
                • Action View
               • Active Record
               • Action Mailer

Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
13/12/2005




Tuesday, December 15, 2009
• db/schema.rb
               • config/environment.rb
               • lib/tasks (Rakefile)
               • scripts (stubs)
               • vendor/plugins

Tuesday, December 15, 2009
• 2 vezes mais rápido
               • FCGI melhor
               • Inflector
               • session (ActiveRecordStore)
               • rake freeze_gems

Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
> 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/03/2006




Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
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['cartbox'].replace :partial => 'cart'
          page['num_items'].replace :partial => 'num_items'
          page["product_#{params[:id]}"].addClassName 'incart'




Tuesday, December 15, 2009
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
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
Tuesday, December 15, 2009
> 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
> 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
> 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
class User < ActiveRecord::Base
                               acts_as_authentic
                             end




               • OpenID
               • LDAP
               • Facebook Connect
               • OAuth (Twitter)
Tuesday, December 15, 2009
19/01/2007




Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
# 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
/comments/1;edit




Tuesday, December 15, 2009
/comments/1;edit




Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
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
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
07/12/2007




Tuesday, December 15, 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
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
# 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
# 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
# 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
# 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
# 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
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
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
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
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
class PostsController < ApplicationController
       rescue_from User::NotAuthorized, :with => :deny_access

       protected
         def deny_access
           ...
         end
      end




Tuesday, December 15, 2009
class PostsController < ApplicationController
       rescue_from User::NotAuthorized, :with => :deny_access

       protected
         def deny_access
           ...
         end
      end




Tuesday, December 15, 2009
# 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
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
# sellers.yml
                             shopify:
                               name: Shopify

                             # products.yml
                             pimp_cup:
                               seller: shopify
                               name: Pimp cup




Tuesday, December 15, 2009
Tuesday, December 15, 2009
# 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
# 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
@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
# 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
# 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
01/06/2008




Tuesday, December 15, 2009
# 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
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
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
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
> script/generate migration post
             create db/migrate/20080402122512_post.rb




Tuesday, December 15, 2009
Tuesday, December 15, 2009
# 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
# 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
21/11/2008




Tuesday, December 15, 2009
# 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
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
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
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
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
# config/environments/production.rb:
                             config.threadsafe!

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




Tuesday, December 15, 2009
# 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
# 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
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
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
Tuesday, December 15, 2009
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
# 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
> 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
16/03/2009




Tuesday, December 15, 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
> 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
# 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
# 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
<% 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
<% 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
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
class Project < ActiveRecord::Base
                         has_many :tasks

                         accept_nested_attributes_for :tasks,
                           :allow_destroy => true
                       end




Tuesday, December 15, 2009
<% 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
<% 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
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
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
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
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
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
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
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
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
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
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
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
# 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
def remove_email(email)
                     emails.find_by_email(email).try(:destroy)
                   end




Tuesday, December 15, 2009
def remove_email(email)
                     emails.find_by_email(email).try(:destroy)
                   end




Tuesday, December 15, 2009
XmlMini.backend = 'LibXML'
                             XmlMini.backend = 'Nokogiri'




Tuesday, December 15, 2009
Tuesday, December 15, 2009
> 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
> 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
> 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
• 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
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009
Tuesday, December 15, 2009

Weitere ähnliche Inhalte

Was ist angesagt?

Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Thomas Fuchs
 
Render API - Pavel Makhrinsky
Render API - Pavel MakhrinskyRender API - Pavel Makhrinsky
Render API - Pavel Makhrinsky
DrupalCampDN
 
Solving Problems with YUI3: AutoComplete
Solving Problems with YUI3: AutoCompleteSolving Problems with YUI3: AutoComplete
Solving Problems with YUI3: AutoComplete
IsaacSchlueter
 

Was ist angesagt? (20)

An in-depth look at jQuery UI
An in-depth look at jQuery UIAn in-depth look at jQuery UI
An in-depth look at jQuery UI
 
jQuery and_drupal
jQuery and_drupaljQuery and_drupal
jQuery and_drupal
 
JavaScript 1.5 to 2.0 (TomTom)
JavaScript 1.5 to 2.0 (TomTom)JavaScript 1.5 to 2.0 (TomTom)
JavaScript 1.5 to 2.0 (TomTom)
 
jQuery (MeshU)
jQuery (MeshU)jQuery (MeshU)
jQuery (MeshU)
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
Dev In Rio 2009
Dev In Rio 2009Dev In Rio 2009
Dev In Rio 2009
 
Workshop 18: CSS Animations & cool effects
Workshop 18: CSS Animations & cool effectsWorkshop 18: CSS Animations & cool effects
Workshop 18: CSS Animations & cool effects
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
HTML5 and CSS3 Shizzle
HTML5 and CSS3 ShizzleHTML5 and CSS3 Shizzle
HTML5 and CSS3 Shizzle
 
Render API - Pavel Makhrinsky
Render API - Pavel MakhrinskyRender API - Pavel Makhrinsky
Render API - Pavel Makhrinsky
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
 
WordPress and Ajax
WordPress and AjaxWordPress and Ajax
WordPress and Ajax
 
Randomising css animations
Randomising css animationsRandomising css animations
Randomising css animations
 
Solving Problems with YUI3: AutoComplete
Solving Problems with YUI3: AutoCompleteSolving Problems with YUI3: AutoComplete
Solving Problems with YUI3: AutoComplete
 
jQuery Essentials
jQuery EssentialsjQuery Essentials
jQuery Essentials
 
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do More
 
Jquery tutorial-beginners
Jquery tutorial-beginnersJquery tutorial-beginners
Jquery tutorial-beginners
 
Getting the Most Out of jQuery Widgets
Getting the Most Out of jQuery WidgetsGetting the Most Out of jQuery Widgets
Getting the Most Out of jQuery Widgets
 
jQuery: Nuts, Bolts and Bling
jQuery: Nuts, Bolts and BlingjQuery: Nuts, Bolts and Bling
jQuery: Nuts, Bolts and Bling
 

Ähnlich wie Rails For Kids 2009

#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
Justin Cataldo
 
Bundling Client Side Assets
Bundling Client Side AssetsBundling Client Side Assets
Bundling Client Side Assets
Timothy Oxley
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
arcware
 

Ähnlich wie Rails For Kids 2009 (20)

Semcomp de São Carlos
Semcomp de São CarlosSemcomp de São Carlos
Semcomp de São Carlos
 
And the Greatest of These Is ... Space
And the Greatest of These Is ... SpaceAnd the Greatest of These Is ... Space
And the Greatest of These Is ... Space
 
#NewMeetup Performance
#NewMeetup Performance#NewMeetup Performance
#NewMeetup Performance
 
Page Caching Resurrected: A Fairy Tale
Page Caching Resurrected: A Fairy TalePage Caching Resurrected: A Fairy Tale
Page Caching Resurrected: A Fairy Tale
 
GPars For Beginners
GPars For BeginnersGPars For Beginners
GPars For Beginners
 
Choosing a Javascript Framework
Choosing a Javascript FrameworkChoosing a Javascript Framework
Choosing a Javascript Framework
 
Background Processing in Ruby on Rails
Background Processing in Ruby on RailsBackground Processing in Ruby on Rails
Background Processing in Ruby on Rails
 
ActiveResource & REST
ActiveResource & RESTActiveResource & REST
ActiveResource & REST
 
Enecomp 2009
Enecomp 2009Enecomp 2009
Enecomp 2009
 
Ecossistema Rails Campus Party 09
Ecossistema Rails   Campus Party 09Ecossistema Rails   Campus Party 09
Ecossistema Rails Campus Party 09
 
Tek 2013 - Building Web Apps from a New Angle with AngularJS
Tek 2013 - Building Web Apps from a New Angle with AngularJSTek 2013 - Building Web Apps from a New Angle with AngularJS
Tek 2013 - Building Web Apps from a New Angle with AngularJS
 
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
Open Source Monitoring for Java with JMX and Graphite (GeeCON 2013)
 
Bundling Client Side Assets
Bundling Client Side AssetsBundling Client Side Assets
Bundling Client Side Assets
 
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
10 Things Every Plugin Developer Should Know (WordCamp Atlanta 2013)
 
Application Logging With The ELK Stack
Application Logging With The ELK StackApplication Logging With The ELK Stack
Application Logging With The ELK Stack
 
PHP 5 Sucks. PHP 5 Rocks.
PHP 5 Sucks. PHP 5 Rocks.PHP 5 Sucks. PHP 5 Rocks.
PHP 5 Sucks. PHP 5 Rocks.
 
Rush, a shell that will yield to you
Rush, a shell that will yield to youRush, a shell that will yield to you
Rush, a shell that will yield to you
 
Road to Rails
Road to RailsRoad to Rails
Road to Rails
 
Adventurous Merb
Adventurous MerbAdventurous Merb
Adventurous Merb
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 

Mehr von Fabio Akita

Mehr von Fabio Akita (20)

Devconf 2019 - São Carlos
Devconf 2019 - São CarlosDevconf 2019 - São Carlos
Devconf 2019 - São Carlos
 
Meetup Nerdzão - English Talk about Languages
Meetup Nerdzão  - English Talk about LanguagesMeetup Nerdzão  - English Talk about Languages
Meetup Nerdzão - English Talk about Languages
 
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
 
Desmistificando Blockchains - 20o Encontro Locaweb SP
Desmistificando Blockchains - 20o Encontro Locaweb SPDesmistificando Blockchains - 20o Encontro Locaweb SP
Desmistificando Blockchains - 20o Encontro Locaweb SP
 
Desmistificando Blockchains - Insiter Goiania
Desmistificando Blockchains - Insiter GoianiaDesmistificando Blockchains - Insiter Goiania
Desmistificando Blockchains - Insiter Goiania
 
Blockchain em 7 minutos - 7Masters
Blockchain em 7 minutos - 7MastersBlockchain em 7 minutos - 7Masters
Blockchain em 7 minutos - 7Masters
 
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
 
Desmistificando Mitos de Tech Startups - Intercon 2017
Desmistificando Mitos de Tech Startups - Intercon 2017Desmistificando Mitos de Tech Startups - Intercon 2017
Desmistificando Mitos de Tech Startups - Intercon 2017
 
30 Days to Elixir and Crystal and Back to Ruby
30 Days to Elixir and Crystal and Back to Ruby30 Days to Elixir and Crystal and Back to Ruby
30 Days to Elixir and Crystal and Back to Ruby
 
Uma Discussão sobre a Carreira de TI
Uma Discussão sobre a Carreira de TIUma Discussão sobre a Carreira de TI
Uma Discussão sobre a Carreira de TI
 
THE CONF - Opening Keynote
THE CONF - Opening KeynoteTHE CONF - Opening Keynote
THE CONF - Opening Keynote
 
A Journey through New Languages - Rancho Dev 2017
A Journey through New Languages - Rancho Dev 2017A Journey through New Languages - Rancho Dev 2017
A Journey through New Languages - Rancho Dev 2017
 
Desmistificando Mitos de Startups - Sebrae - AP
Desmistificando Mitos de Startups - Sebrae - APDesmistificando Mitos de Startups - Sebrae - AP
Desmistificando Mitos de Startups - Sebrae - AP
 
A Journey through New Languages - Guru Sorocaba 2017
A Journey through New Languages - Guru Sorocaba 2017A Journey through New Languages - Guru Sorocaba 2017
A Journey through New Languages - Guru Sorocaba 2017
 
A Journey through New Languages - Insiter 2017
A Journey through New Languages - Insiter 2017A Journey through New Languages - Insiter 2017
A Journey through New Languages - Insiter 2017
 
A Journey through New Languages - Locaweb Tech Day
A Journey through New Languages - Locaweb Tech DayA Journey through New Languages - Locaweb Tech Day
A Journey through New Languages - Locaweb Tech Day
 
A Journey through new Languages - Intercon 2016
A Journey through new Languages - Intercon 2016A Journey through new Languages - Intercon 2016
A Journey through new Languages - Intercon 2016
 
Premature Optimization 2.0 - Intercon 2016
Premature Optimization 2.0 - Intercon 2016Premature Optimization 2.0 - Intercon 2016
Premature Optimization 2.0 - Intercon 2016
 
Conexão Kinghost - Otimização Prematura
Conexão Kinghost - Otimização PrematuraConexão Kinghost - Otimização Prematura
Conexão Kinghost - Otimização Prematura
 
The Open Commerce Conference - Premature Optimisation: The Root of All Evil
The Open Commerce Conference - Premature Optimisation: The Root of All EvilThe Open Commerce Conference - Premature Optimisation: The Root of All Evil
The Open Commerce Conference - Premature Optimisation: The Root of All Evil
 

Kürzlich hochgeladen

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Kürzlich hochgeladen (20)

Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

Rails For Kids 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
  • 5. • Action Pack • Action Controller • Action View • Active Record • Action Mailer 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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
  • 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