Beginner to Builder
                        Week 3
                        Richard Schneeman
                        @schneems




June, 2011
Friday, June 24, 2011
Austin on Rails
                        • Tuesday, 27th 7:00pm
                          • 7th and Brazos 8th Floor
                        • @austinonrails




@Schneems
Friday, June 24, 2011
Rails - Week 3
                        • Ruby
                          • Variables
                        • Rails
                          • JS/CSS/images
                          • Controllers
                            • Controller Testing
                          • Database Associations
@Schneems
Friday, June 24, 2011
Variables
                        foobar     # local variable

                        @foobar    # instance variable, starts with @

                        @@foobar   # class variable, starts with @@

                        $foobar    # global variable, starts with $

                        FOOBAR     # Constant, starts with a capitol letter

                        FooBar     # Classes are constants



@Schneems
Friday, June 24, 2011
Instance Variables

         @color = "blue"           color = "pink"
         def instance_fur_color    def local_fur_color
           return @color             return color
         end                       end
         puts instance_fur_color   puts local_fur_color
         >> "blue"                 >> NameError:
                                       undefined local variable




@Schneems
Friday, June 24, 2011
Instance Variables

         @color = "blue"           color = "pink"
         def instance_fur_color    def local_fur_color
           return @color             return defined?(color)
         end                       end
         puts instance_fur_color   >> False
         >> "blue"




@Schneems
Friday, June 24, 2011
Instance Variables
                        class Dog
                          def set_color(color)
                            @fur_color = color
                          end
                          def color
                            "fur color is #{@fur_color}"
                          end
                        end
                        # create a Dog instance
                        lassie = Dog.new
                        # set color
                        lassie.set_color("brown")
                        # get @fur_color
                        lassie.color
                        >> "@fur_color is brown"
@Schneems
Friday, June 24, 2011
Bad Scope
         class Circle
           $sides = 0
           def self.sides
             $sides
           end
                               Triangle.sides
         end
                               >> 3
                               Circle.sides
         class Triangle
                               >> 3
           $sides = 3
           def self.sides
             $sides
           end
         end

@Schneems
Friday, June 24, 2011
Rails - Week 3
                • Rails - A Place for Everything
                  • Public
                    • Images
                    • Javascripts
                    • Stylesheets


@Schneems
Friday, June 24, 2011
Rails - Week 3
                • Rails - A Place for Everything
                • View Helpers
                        • <%= stylesheet_link_tag :all %>
                        • <%= javascript_include_tag :defaults %>
                •       Require Specific Files
                        • <%= image_tag ‘rails.png’ %>
                        • <%= stylesheet_link_tag ‘scaffold.css’ %>
                        • <%= javascript_include_tag ‘rails.js’ %>


@Schneems
Friday, June 24, 2011
Controllers
                        • The C in MVC
                          • handles buisness logic
                 htt://localhost:3000/clients/new

                   class ClientsController < ApplicationController
                     def new
                     end
                   end




@Schneems
Friday, June 24, 2011
Controllers
                        • Pass data to controllers via query
                          string

               htt://localhost:3000/clients?status=activated
                   ?status=activated

                   ?status=activated&level=23

                   ?status=deactivated&level=1&foo=bar




@Schneems
Friday, June 24, 2011
Controllers
                        • params, get data from the url
                        • instance variables pass data to
                          view
               http://localhost:3000/clients?status=activated
                   def index
                    @status = params[:status]
                    if @status == "activated"
                       @clients = Client.activated
                    else
                       @clients = Client.unactivated
                    end
                   end
@Schneems
Friday, June 24, 2011
Controllers
                        • Receive Arrays
               Arrays

                   GET /clients?ids[]=1&ids[]=2&ids[]=3
                     params[:ids] # => [“1”,”2”,”3”]




@Schneems
Friday, June 24, 2011
Controllers
    Form
                        • Receive Hashes from forms
      <form action="/clients" method="post">
        <input type="text" name="client[name]" value="Acme" />
        <input type="text" name="client[phone]" value="12345" />
        <input type="text" name="client[address][postcode]" value="12345" />
      </form>


                Hash
                          params[:client] # =>
                              {:name => “Acme”,
                                :phone => “12345”,
                                :address => {:postcode => “12345”}
                              }
@Schneems
Friday, June 24, 2011
Controllers
                        • Control application flow
                        • render content
                        htt://localhost:3000/clients/new
                              # send to another action/url
                              redirect_to "/home"

                              # render content
                              render :action => "new"
                              render :layout => "awesome"
                              render :text => "foo"
                              render :json => {}
@Schneems
Friday, June 24, 2011
Rails - Week 3
                • Functional Testing - Controllers
                        •   web request successful?

                        •   user redirected to the right page?

                        •   user successfully authenticated?

                        •   correct object stored in the template?

                        •   appropriate message displayed to the user ?




@Schneems
Friday, June 24, 2011
Rails - Week 3
               • Use HTTP to send data to controller
                        •   get, post, put, head, delete

               • Verify Response
                 • Assigns
                 • Cookies
                 • Flash
                 • Session

@Schneems
Friday, June 24, 2011
Cookies?
                        • Stored on the user’s computer
                        • Mostly used for settings




                          cookies["remember_me"] = true


@Schneems
Friday, June 24, 2011
Session?
                        • store and access user specific data
                        • Uses cookies to store data by default
                        • very quick, and secure
                        • NOT for critical information
                          • Put it in the database
                          session[:logged_in] = true
                          session[:user_id] = 57
                          session[:is_mobile] = false
@Schneems
Friday, June 24, 2011
Flash?
                        • Part of the session
                        • cleared after each request
                        • useful for error messages




@Schneems
Friday, June 24, 2011
Flash?
              flash[:notice] = "You must sign in to see this page."



                                        or

            redirect_to signup_url,
                      :notice => "You must sign in to see this page."




@Schneems
Friday, June 24, 2011
Rails - Week 3
                  • Functional Testing - Controllers
                    • Send data to controller
                    • Verify response
                 class PetControllerTest < ActionController::TestCase
                   test "should get index" do
                     get :index
                     assert_response :success
                   end
                 end


@Schneems
Friday, June 24, 2011
Rails - Week 3
                 • Use HTTP to send data
                 • Get, Post, Put, Delete
       Controller
                 • assigns(:post) = @post
                  def create
                    @post = Post.create(params[:post])
                  end

       Test

                  post :create, :post => { :title => 'Some title'}
                  assert assigns(:post).is_a?(Post)

@Schneems
Friday, June 24, 2011
Rails - Week 3
                 • Assert difference


                assert_difference('Post.count', 1) do
                  post :create, :post => { :title => 'Some title'}
                end




@Schneems
Friday, June 24, 2011
Rails - Week 3




@Schneems
Friday, June 24, 2011
Associations
   • Relational Databases
     • Primary Key
       • unique key can identify
         each row in a table
     • Foreign Key
       • Relates a row keyanother
         row’s primary
                       to




@Schneems
Friday, June 24, 2011
Primary Key
                        • Unique identifier for all objects

                            Hats:
                              id: 557
                              style: "Fedora"

                            Hats:
                              id: 687
                              style: "Cowboy"



@Schneems
Friday, June 24, 2011
Foreign Key
                        • Relates to another row’s primary key

                            Hats
                              id: 557
                              style: "Fedora"
                              inspector_id: 35

                            Inspectors
                              id: 35
                              name: "John"


@Schneems
Friday, June 24, 2011
Foreign Key
                        • Creates relationships
                                    Inspectors
                                      id: 35
                                      name: "John"



     Hats                          Hats                 Hats
       id: 557                       id: 558              id: 559
       style: "Fedora"               style: "Ballcap"     style: "Silly"
       inspector_id: 35              inspector_id: 35     inspector_id: 35



@Schneems
Friday, June 24, 2011
Belongs_To
   • belongs_to :parent_class
     • Sets Foreign Key




@Schneems
Friday, June 24, 2011
Has_Many
   • has_many :child_class
     • Builds Association in Ruby




                        i.e. Hat inspector has many hats
@Schneems
Friday, June 24, 2011
Has_Many
   • How Does this Help?
     • Related objects contain links to one
       another
     • Get one object, you’ve got all associated
                   >> myCustomer = Customer.where(:id => 2)
                   >> orders = myCustomer.orders.all




@Schneems
Friday, June 24, 2011
Has_Many
         • Caveats
         •       myCustomer.orders builds SQL and hits the database

               • N+1 Problem - Imagine
                  • You query 100 customers
                  • Each Customer has 100 orders
                  • Each Order has 100 products
                  • ...
@Schneems
Friday, June 24, 2011
Associations
         • N+1 - (Cont.)
                        customers = Customer.all
                        customers.each do |customer|
                          customer.orders do |order|
                            order.products do |product|
                            puts product
                          end
                        end


            This would generate 10,001 database queries
                         (not a good thing)
@Schneems
Friday, June 24, 2011
Associations
         • N+1 - How do we Fix it?
           • What if we could Pre-load Associations?
             • Includes
                         Customer.includes(:orders => :products).all



                This would generate 1 database query!!
                              Will take significantly less time than alternative
                        Note: database access is almost always be your bottleneck


@Schneems
Friday, June 24, 2011
Has_Many :Through =>
         • Chain Associations Using :Through




                           What Classes have foreign keys?


@Schneems
Friday, June 24, 2011
Has_Many :Through =>
        • Appointments
          • physician_id
          • patient_id



                            What Classes have foreign keys?

@Schneems
Friday, June 24, 2011
Has_Many :Through =>
        • Physician Class
          • Uses Appointments
          • Finds Patients
            • Automatically

                         >> dr = Physicians.first
                         >> dr.patients


@Schneems
Friday, June 24, 2011
Has & Belongs To Many
        • HABTM (has and belongs to many)
          • Creates direct many to many relationship




                        This is essentially using :through with a
@Schneems
                        single purpose table: assemblies_parts
Friday, June 24, 2011
HABTM - Vs. :Through
        • Use HABTM
        • Don’t need to do anything with the relationship
          model
          • Restricted DB size
        • Use :through
          • Need validations
          • Need callbacks
          • Need extra attributes
@Schneems
Friday, June 24, 2011
Questions?
                   http://guides.rubyonrails.org
                   http://stackoverflow.com




@Schneems
Friday, June 24, 2011

Rails 3 Beginner to Builder 2011 Week 3

  • 1.
    Beginner to Builder Week 3 Richard Schneeman @schneems June, 2011 Friday, June 24, 2011
  • 2.
    Austin on Rails • Tuesday, 27th 7:00pm • 7th and Brazos 8th Floor • @austinonrails @Schneems Friday, June 24, 2011
  • 3.
    Rails - Week3 • Ruby • Variables • Rails • JS/CSS/images • Controllers • Controller Testing • Database Associations @Schneems Friday, June 24, 2011
  • 4.
    Variables foobar # local variable @foobar # instance variable, starts with @ @@foobar # class variable, starts with @@ $foobar # global variable, starts with $ FOOBAR # Constant, starts with a capitol letter FooBar # Classes are constants @Schneems Friday, June 24, 2011
  • 5.
    Instance Variables @color = "blue" color = "pink" def instance_fur_color def local_fur_color return @color return color end end puts instance_fur_color puts local_fur_color >> "blue" >> NameError: undefined local variable @Schneems Friday, June 24, 2011
  • 6.
    Instance Variables @color = "blue" color = "pink" def instance_fur_color def local_fur_color return @color return defined?(color) end end puts instance_fur_color >> False >> "blue" @Schneems Friday, June 24, 2011
  • 7.
    Instance Variables class Dog def set_color(color) @fur_color = color end def color "fur color is #{@fur_color}" end end # create a Dog instance lassie = Dog.new # set color lassie.set_color("brown") # get @fur_color lassie.color >> "@fur_color is brown" @Schneems Friday, June 24, 2011
  • 8.
    Bad Scope class Circle $sides = 0 def self.sides $sides end Triangle.sides end >> 3 Circle.sides class Triangle >> 3 $sides = 3 def self.sides $sides end end @Schneems Friday, June 24, 2011
  • 9.
    Rails - Week3 • Rails - A Place for Everything • Public • Images • Javascripts • Stylesheets @Schneems Friday, June 24, 2011
  • 10.
    Rails - Week3 • Rails - A Place for Everything • View Helpers • <%= stylesheet_link_tag :all %> • <%= javascript_include_tag :defaults %> • Require Specific Files • <%= image_tag ‘rails.png’ %> • <%= stylesheet_link_tag ‘scaffold.css’ %> • <%= javascript_include_tag ‘rails.js’ %> @Schneems Friday, June 24, 2011
  • 11.
    Controllers • The C in MVC • handles buisness logic htt://localhost:3000/clients/new class ClientsController < ApplicationController def new end end @Schneems Friday, June 24, 2011
  • 12.
    Controllers • Pass data to controllers via query string htt://localhost:3000/clients?status=activated ?status=activated ?status=activated&level=23 ?status=deactivated&level=1&foo=bar @Schneems Friday, June 24, 2011
  • 13.
    Controllers • params, get data from the url • instance variables pass data to view http://localhost:3000/clients?status=activated def index @status = params[:status] if @status == "activated" @clients = Client.activated else @clients = Client.unactivated end end @Schneems Friday, June 24, 2011
  • 14.
    Controllers • Receive Arrays Arrays GET /clients?ids[]=1&ids[]=2&ids[]=3 params[:ids] # => [“1”,”2”,”3”] @Schneems Friday, June 24, 2011
  • 15.
    Controllers Form • Receive Hashes from forms <form action="/clients" method="post"> <input type="text" name="client[name]" value="Acme" /> <input type="text" name="client[phone]" value="12345" /> <input type="text" name="client[address][postcode]" value="12345" /> </form> Hash params[:client] # => {:name => “Acme”, :phone => “12345”, :address => {:postcode => “12345”} } @Schneems Friday, June 24, 2011
  • 16.
    Controllers • Control application flow • render content htt://localhost:3000/clients/new # send to another action/url redirect_to "/home" # render content render :action => "new" render :layout => "awesome" render :text => "foo" render :json => {} @Schneems Friday, June 24, 2011
  • 17.
    Rails - Week3 • Functional Testing - Controllers • web request successful? • user redirected to the right page? • user successfully authenticated? • correct object stored in the template? • appropriate message displayed to the user ? @Schneems Friday, June 24, 2011
  • 18.
    Rails - Week3 • Use HTTP to send data to controller • get, post, put, head, delete • Verify Response • Assigns • Cookies • Flash • Session @Schneems Friday, June 24, 2011
  • 19.
    Cookies? • Stored on the user’s computer • Mostly used for settings cookies["remember_me"] = true @Schneems Friday, June 24, 2011
  • 20.
    Session? • store and access user specific data • Uses cookies to store data by default • very quick, and secure • NOT for critical information • Put it in the database session[:logged_in] = true session[:user_id] = 57 session[:is_mobile] = false @Schneems Friday, June 24, 2011
  • 21.
    Flash? • Part of the session • cleared after each request • useful for error messages @Schneems Friday, June 24, 2011
  • 22.
    Flash? flash[:notice] = "You must sign in to see this page." or redirect_to signup_url, :notice => "You must sign in to see this page." @Schneems Friday, June 24, 2011
  • 23.
    Rails - Week3 • Functional Testing - Controllers • Send data to controller • Verify response class PetControllerTest < ActionController::TestCase test "should get index" do get :index assert_response :success end end @Schneems Friday, June 24, 2011
  • 24.
    Rails - Week3 • Use HTTP to send data • Get, Post, Put, Delete Controller • assigns(:post) = @post def create @post = Post.create(params[:post]) end Test post :create, :post => { :title => 'Some title'} assert assigns(:post).is_a?(Post) @Schneems Friday, June 24, 2011
  • 25.
    Rails - Week3 • Assert difference assert_difference('Post.count', 1) do post :create, :post => { :title => 'Some title'} end @Schneems Friday, June 24, 2011
  • 26.
    Rails - Week3 @Schneems Friday, June 24, 2011
  • 27.
    Associations • Relational Databases • Primary Key • unique key can identify each row in a table • Foreign Key • Relates a row keyanother row’s primary to @Schneems Friday, June 24, 2011
  • 28.
    Primary Key • Unique identifier for all objects Hats: id: 557 style: "Fedora" Hats: id: 687 style: "Cowboy" @Schneems Friday, June 24, 2011
  • 29.
    Foreign Key • Relates to another row’s primary key Hats id: 557 style: "Fedora" inspector_id: 35 Inspectors id: 35 name: "John" @Schneems Friday, June 24, 2011
  • 30.
    Foreign Key • Creates relationships Inspectors id: 35 name: "John" Hats Hats Hats id: 557 id: 558 id: 559 style: "Fedora" style: "Ballcap" style: "Silly" inspector_id: 35 inspector_id: 35 inspector_id: 35 @Schneems Friday, June 24, 2011
  • 31.
    Belongs_To • belongs_to :parent_class • Sets Foreign Key @Schneems Friday, June 24, 2011
  • 32.
    Has_Many • has_many :child_class • Builds Association in Ruby i.e. Hat inspector has many hats @Schneems Friday, June 24, 2011
  • 33.
    Has_Many • How Does this Help? • Related objects contain links to one another • Get one object, you’ve got all associated >> myCustomer = Customer.where(:id => 2) >> orders = myCustomer.orders.all @Schneems Friday, June 24, 2011
  • 34.
    Has_Many • Caveats • myCustomer.orders builds SQL and hits the database • N+1 Problem - Imagine • You query 100 customers • Each Customer has 100 orders • Each Order has 100 products • ... @Schneems Friday, June 24, 2011
  • 35.
    Associations • N+1 - (Cont.) customers = Customer.all customers.each do |customer| customer.orders do |order| order.products do |product| puts product end end This would generate 10,001 database queries (not a good thing) @Schneems Friday, June 24, 2011
  • 36.
    Associations • N+1 - How do we Fix it? • What if we could Pre-load Associations? • Includes Customer.includes(:orders => :products).all This would generate 1 database query!! Will take significantly less time than alternative Note: database access is almost always be your bottleneck @Schneems Friday, June 24, 2011
  • 37.
    Has_Many :Through => • Chain Associations Using :Through What Classes have foreign keys? @Schneems Friday, June 24, 2011
  • 38.
    Has_Many :Through => • Appointments • physician_id • patient_id What Classes have foreign keys? @Schneems Friday, June 24, 2011
  • 39.
    Has_Many :Through => • Physician Class • Uses Appointments • Finds Patients • Automatically >> dr = Physicians.first >> dr.patients @Schneems Friday, June 24, 2011
  • 40.
    Has & BelongsTo Many • HABTM (has and belongs to many) • Creates direct many to many relationship This is essentially using :through with a @Schneems single purpose table: assemblies_parts Friday, June 24, 2011
  • 41.
    HABTM - Vs.:Through • Use HABTM • Don’t need to do anything with the relationship model • Restricted DB size • Use :through • Need validations • Need callbacks • Need extra attributes @Schneems Friday, June 24, 2011
  • 42.
    Questions? http://guides.rubyonrails.org http://stackoverflow.com @Schneems Friday, June 24, 2011