Fitting for the occasion


      MeetUP @ Balabit



         October 14, 2010
         nucc@balabit.com
Rails 3.0

• Merb + Rails 2.3 = Rails 3.0
• Bundler
• Rack
• HTML 5
• Arel
Rails 3.0

 • Merb + Rails 2.3 = Rails 3.0
users                                 
  .where(users[:name].eq('nucc'))       
 • Bundler
  .project(users[:id])                
# => SELECT users.id FROM users WHERE users.name = 'nucc'
 • Rack
users.where(users[:name].eq('bob')).where(users[:age].lt(25))
#•=> SELECT * FROM users where users.name=’bob’ and users.age < 25
   HTML 5
 • Arel
users.where(users[:name].eq('bob').or(users[:age].lt(25)))
# => SELECT * FROM users where users.name=’bob’ or users.age < 25

valid_users = users.where(users[:valid].eq(1))
men = valid_users.where(users[:sex].eq(1))
women = valid_users.where(users[:sex].eq(2))
number_of_women = women.count()
Sharing information

  Product   Products
  Model     Controller
Sharing information

  Product   Products
  Model     Controller
REST

• Representational State Transfer

• Roy Fielding - 2000
• SOAP is a protocol, REST is an architecture
• Representation of a resource
• iWiW, Facebook, GitHub, Twitter, Google Search
REST Mapping

    Verb          Path           Action
    GET        /products         index
    GET       /products/:id      show
    POST       /products         create
    GET     /products/:id/edit    edit
    PUT       /products/:id      update
   DELETE     /products/:id      delete
Configuration
 /app/models/product.rb                     /app/controllers/products_controller.rb
 class Product < ActiveRecord::Base         class Products < ApplicationController
 end
                                             def index
                                              @products = Product.all
                                             end

                                             def show
                                              @product = Product.find params[:id]
                                             end


 config/routes.rb                             def update
                                                ...
 Meetup::Application.routes.draw do |map|
                                             end
  resources :products
                                             ...
 end
                                            end
Using resource
/app/models/user.rb
class User < ActiveResource::Base
   site.url = “http://api.twitter.com”
end

                                         /app/controller/user_controller.rb
                                         class UserController < ActionController::Base
                                            self.site = “http://api.twitter.com”

                                           self.element_name = “user”
                                           self.proxy = “...”
                                           self.timeout = 5
                                           self.ssl_options = { :key => “...” }
                                         end
Fitting for the occasion

  Product   Product
  Model     Controller
Fitting for the occasion

                            HTTP
  Product   Product
  Model     Controller
                                Android UI / XML

                                   iPhone UI / XML


                                XML

                         JSON
Respond to
class ProductsController < Application
  def index
   @products = Product.all

  respond_to do |format|
    format.html                 # index.html.erb
    format.iphone               # index.iphone.erb
    format.json { render :json => @products }
    format.xml { render :xml => @products}
  end
 end
end
Fitting for the occasion

            Product    /products.html
  Product
  Model     Controller
                                 /products.xml

                                  /products.iphone


                           /products.rss

                  /products.js
Review


         /app/models
         /app/controllers


         /app/views
         /app/helpers
Rendering
render :xml => @products
render :json => @products
render :file => “../owners/owner.html.erb”
render :text => “Hello World”


render :update do |page|
 page.replace_html(“products”, :partial => product, :object=> @product)
end
Views
                                Layout
                :header

                     content




                                         index.html.erb
        :menu      product #1

                   product #2

                   product #3


                :footer
Layout
 # layout.html.erb           # index.html.erb
 <html>
  <body>                     <%= content_for :header do %>
   <div class=”header”>        <span> BALABIT Products </span>
     <%= yield :header %>    <% end %>
   </div>
   <div class=”content”>     <%= content_for :menu do %>
     <div class=”menu”>        <li>Special menu item</li>
        <%= yield :menu %>   <% end %>
     </div>
   </div>
                             <div class=”products”>
   <div class=”content”>       ...
    <%= yield %>             </div>
   </div>

    ...
Partial

/app/views/products/index.html.erb
            content              #object
                                 render :partial => “product”, :object => ...
          product #1
                                 #array
                                 render :partial => “product”, :collection => ...
          product #2

          product #3


                         /app/views/products/_product.html.erb
Partial
                             # /app/views/products/index.html.erb
                             <div class=”products”>
                              <%= render :partial => “product”, :collection => @products %>
/app/views/products/index.html.erb
                             </div>

            content          # /app/views/products/_product.html.erb
                                   #object
                             <div class=”product”>
                               <span class=”title”><%= product.name %></span> =>
                                    render :partial => “product”, :object             ...
          product #1           <span class=”owner”><%= product.owner %></span>
                             </div>#array
                                  render :partial => “product”, :collection => ...
          product #2         # result
                             <div class=”products”>
                              <div class=”product”>
          product #3             <span class=”title”>SCB</span>
                                 <span class=”owner”>Marci</span>
                              </div>
                             </div>
                         /app/views/products/_product.html.erb
Helpers

/app/views/products/index.html.erb                  /app/helpers/products_helper.rb
<div>                                               module ProductsHelper
  <span> Number of products: </span>
  <%= number_of_products(@product) %>                def number_of_products( products )
<div>                                                 products.select{ |p| p.active? }.size
                                                     end
<% form_for @product, :remote => true do | f | %>
 <%= f.text_field :version %>                        end
<% end %>
Cache
class ProductController < Application   class ProductController < Application
                                           before_filter :authentication
  caches_page :index                       caches_action :index

  def index                               def index
   @products = Product.all                 @products = Product.all
  end                                     end

    def create                              def create
      expire_page :action => :index           expire_page :action => :index
      ...                                     ...
    end                                     end
 ...                                     ...
end                                     end
Cache
<html>
 <body>

<% cache do %>
  <div class=”menu”>
   <li>Show products</li>
  </div>
<% end %>

<% cache(:action => 'update', :action_suffix => 'products') do %>
  <div class=”products”>
    <%= render :partial => “product”, :collection => @products %>
  </div>
<% end %>

# expire_fragment( :controller => ‘products’, :action => 'index', :action_suffix => 'products')
Questions?
Thank you!

Resource and view

  • 1.
    Fitting for theoccasion MeetUP @ Balabit October 14, 2010 nucc@balabit.com
  • 2.
    Rails 3.0 • Merb+ Rails 2.3 = Rails 3.0 • Bundler • Rack • HTML 5 • Arel
  • 3.
    Rails 3.0 •Merb + Rails 2.3 = Rails 3.0 users .where(users[:name].eq('nucc')) • Bundler .project(users[:id]) # => SELECT users.id FROM users WHERE users.name = 'nucc' • Rack users.where(users[:name].eq('bob')).where(users[:age].lt(25)) #•=> SELECT * FROM users where users.name=’bob’ and users.age < 25 HTML 5 • Arel users.where(users[:name].eq('bob').or(users[:age].lt(25))) # => SELECT * FROM users where users.name=’bob’ or users.age < 25 valid_users = users.where(users[:valid].eq(1)) men = valid_users.where(users[:sex].eq(1)) women = valid_users.where(users[:sex].eq(2)) number_of_women = women.count()
  • 4.
    Sharing information Product Products Model Controller
  • 5.
    Sharing information Product Products Model Controller
  • 6.
    REST • Representational StateTransfer • Roy Fielding - 2000 • SOAP is a protocol, REST is an architecture • Representation of a resource • iWiW, Facebook, GitHub, Twitter, Google Search
  • 7.
    REST Mapping Verb Path Action GET /products index GET /products/:id show POST /products create GET /products/:id/edit edit PUT /products/:id update DELETE /products/:id delete
  • 8.
    Configuration /app/models/product.rb /app/controllers/products_controller.rb class Product < ActiveRecord::Base class Products < ApplicationController end def index @products = Product.all end def show @product = Product.find params[:id] end config/routes.rb def update ... Meetup::Application.routes.draw do |map| end resources :products ... end end
  • 9.
    Using resource /app/models/user.rb class User< ActiveResource::Base site.url = “http://api.twitter.com” end /app/controller/user_controller.rb class UserController < ActionController::Base self.site = “http://api.twitter.com” self.element_name = “user” self.proxy = “...” self.timeout = 5 self.ssl_options = { :key => “...” } end
  • 10.
    Fitting for theoccasion Product Product Model Controller
  • 11.
    Fitting for theoccasion HTTP Product Product Model Controller Android UI / XML iPhone UI / XML XML JSON
  • 12.
    Respond to class ProductsController< Application def index @products = Product.all respond_to do |format| format.html # index.html.erb format.iphone # index.iphone.erb format.json { render :json => @products } format.xml { render :xml => @products} end end end
  • 13.
    Fitting for theoccasion Product /products.html Product Model Controller /products.xml /products.iphone /products.rss /products.js
  • 14.
    Review /app/models /app/controllers /app/views /app/helpers
  • 15.
    Rendering render :xml =>@products render :json => @products render :file => “../owners/owner.html.erb” render :text => “Hello World” render :update do |page| page.replace_html(“products”, :partial => product, :object=> @product) end
  • 16.
    Views Layout :header content index.html.erb :menu product #1 product #2 product #3 :footer
  • 17.
    Layout # layout.html.erb # index.html.erb <html> <body> <%= content_for :header do %> <div class=”header”> <span> BALABIT Products </span> <%= yield :header %> <% end %> </div> <div class=”content”> <%= content_for :menu do %> <div class=”menu”> <li>Special menu item</li> <%= yield :menu %> <% end %> </div> </div> <div class=”products”> <div class=”content”> ... <%= yield %> </div> </div> ...
  • 18.
    Partial /app/views/products/index.html.erb content #object render :partial => “product”, :object => ... product #1 #array render :partial => “product”, :collection => ... product #2 product #3 /app/views/products/_product.html.erb
  • 19.
    Partial # /app/views/products/index.html.erb <div class=”products”> <%= render :partial => “product”, :collection => @products %> /app/views/products/index.html.erb </div> content # /app/views/products/_product.html.erb #object <div class=”product”> <span class=”title”><%= product.name %></span> => render :partial => “product”, :object ... product #1 <span class=”owner”><%= product.owner %></span> </div>#array render :partial => “product”, :collection => ... product #2 # result <div class=”products”> <div class=”product”> product #3 <span class=”title”>SCB</span> <span class=”owner”>Marci</span> </div> </div> /app/views/products/_product.html.erb
  • 20.
    Helpers /app/views/products/index.html.erb /app/helpers/products_helper.rb <div> module ProductsHelper <span> Number of products: </span> <%= number_of_products(@product) %> def number_of_products( products ) <div> products.select{ |p| p.active? }.size end <% form_for @product, :remote => true do | f | %> <%= f.text_field :version %> end <% end %>
  • 21.
    Cache class ProductController <Application class ProductController < Application before_filter :authentication caches_page :index caches_action :index def index def index @products = Product.all @products = Product.all end end def create def create expire_page :action => :index expire_page :action => :index ... ... end end ... ... end end
  • 22.
    Cache <html> <body> <% cachedo %> <div class=”menu”> <li>Show products</li> </div> <% end %> <% cache(:action => 'update', :action_suffix => 'products') do %> <div class=”products”> <%= render :partial => “product”, :collection => @products %> </div> <% end %> # expire_fragment( :controller => ‘products’, :action => 'index', :action_suffix => 'products')
  • 23.
  • 24.