Upload
richard-schneeman
View
11.747
Download
0
Tags:
Embed Size (px)
DESCRIPTION
This is the 3rd of 8 presentations given at University of Texas during my Beginner to Builder Rails 3 Class. For more info and the whole series including video presentations at my blog: http://schneems.tumblr.com/tagged/Rails-3-beginner-to-builder-2011
Citation preview
June, 2011
Beginner to BuilderWeek 3Richard Schneeman@schneems
Friday, June 24, 2011
@Schneems
Austin on Rails• Tuesday, 27th 7:00pm
• 7th and Brazos 8th Floor
• @austinonrails
Friday, June 24, 2011
@Schneems
Rails - Week 3• Ruby
• Variables
• Rails
• JS/CSS/images
• Controllers
• Controller Testing
• Database Associations
Friday, June 24, 2011
@Schneems
Variablesfoobar # 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
Friday, June 24, 2011
@Schneems
Instance Variables
@color = "blue"
def instance_fur_color
return @color
end
puts instance_fur_color
>> "blue"
color = "pink"
def local_fur_color
return color
end
puts local_fur_color
>> NameError:
undefined local variable
Friday, June 24, 2011
@Schneems
Instance Variables
@color = "blue"
def instance_fur_color
return @color
end
puts instance_fur_color
>> "blue"
color = "pink"
def local_fur_color
return defined?(color)
end
>> False
Friday, June 24, 2011
@Schneems
class Dog def set_color(color) @fur_color = color end def color
"fur color is #{@fur_color}" endend# create a Dog instancelassie = Dog.new
# set colorlassie.set_color("brown")# get @fur_colorlassie.color>> "@fur_color is brown"
Instance Variables
Friday, June 24, 2011
@Schneems
Bad Scopeclass Circle
$sides = 0
def self.sides
$sides
end
end
class Triangle
$sides = 3
def self.sides
$sides
end
end
Triangle.sides
>> 3
Circle.sides
>> 3
Friday, June 24, 2011
@Schneems
Rails - Week 3• Rails - A Place for Everything
• Public
• Images
• Javascripts
• Stylesheets
Friday, June 24, 2011
@Schneems
• 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’ %>
Rails - Week 3
Friday, June 24, 2011
@Schneems
Controllers• The C in MVC
• handles buisness logic
class ClientsController < ApplicationController
def new
end
end
htt://localhost:3000/clients/new
Friday, June 24, 2011
@Schneems
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
Friday, June 24, 2011
@Schneems
Controllers• params, get data from the url
• instance variables pass data to view
def index
@status = params[:status]
if @status == "activated"
@clients = Client.activated
else
@clients = Client.unactivated
end
end
http://localhost:3000/clients?status=activated
Friday, June 24, 2011
@Schneems
Controllers• Receive Arrays
GET /clients?ids[]=1&ids[]=2&ids[]=3
params[:ids] # => [“1”,”2”,”3”]
Arrays
Friday, June 24, 2011
@Schneems
Controllers• 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”}
}
Form
Friday, June 24, 2011
@Schneems
Controllers• Control application flow
• render content
# send to another action/url
redirect_to "/home"
# render content
render :action => "new"
render :layout => "awesome"
render :text => "foo"
render :json => {}
htt://localhost:3000/clients/new
Friday, June 24, 2011
@Schneems
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 ?
Friday, June 24, 2011
@Schneems
Rails - Week 3• Use HTTP to send data to controller• get, post, put, head, delete
• Verify Response
• Assigns
• Cookies
• Flash
• Session
Friday, June 24, 2011
@Schneems
• Stored on the user’s computer
• Mostly used for settings
cookies["remember_me"] = true
Cookies?
Friday, June 24, 2011
@Schneems
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
Friday, June 24, 2011
@Schneems
Flash?• Part of the session
• cleared after each request
• useful for error messages
Friday, June 24, 2011
@Schneems
Flash?flash[:notice] = "You must sign in to see this page."
redirect_to signup_url,
:notice => "You must sign in to see this page."
or
Friday, June 24, 2011
@Schneems
class PetControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end
• Functional Testing - Controllers
• Send data to controller
• Verify response
Rails - Week 3
Friday, June 24, 2011
• Use HTTP to send data
• Get, Post, Put, Delete
• assigns(:post) = @post
@Schneems
post :create, :post => { :title => 'Some title'}
assert assigns(:post).is_a?(Post)
Rails - Week 3
def create
@post = Post.create(params[:post])
end
Controller
Test
Friday, June 24, 2011
• Assert difference
@Schneems
Rails - Week 3
assert_difference('Post.count', 1) do
post :create, :post => { :title => 'Some title'}
end
Friday, June 24, 2011
@Schneems
Rails - Week 3
Friday, June 24, 2011
@Schneems
• Relational Databases
• Primary Key
• unique key can identify each row in a table
• Foreign Key
• Relates a row to another row’s primary key
Associations
Friday, June 24, 2011
@Schneems
• Unique identifier for all objectsPrimary Key
Hats:
id: 557
style: "Fedora"
Hats:
id: 687
style: "Cowboy"
Friday, June 24, 2011
@Schneems
Foreign Key• Relates to another row’s primary key
Hats
id: 557
style: "Fedora"
inspector_id: 35
Inspectors
id: 35
name: "John"
Friday, June 24, 2011
@Schneems
Foreign Key• Creates relationships
Inspectors
id: 35
name: "John"
Hats
id: 557
style: "Fedora"
inspector_id: 35
Hats
id: 558
style: "Ballcap"
inspector_id: 35
Hats
id: 559
style: "Silly"
inspector_id: 35
Friday, June 24, 2011
@Schneems
• belongs_to :parent_class
• Sets Foreign Key
Belongs_To
Friday, June 24, 2011
@Schneems
• has_many :child_class
• Builds Association in Ruby
Has_Many
i.e. Hat inspector has many hats
Friday, June 24, 2011
• How Does this Help?
• Related objects contain links to one another
• Get one object, you’ve got all associated
@Schneems
>> myCustomer = Customer.where(:id => 2)
>> orders = myCustomer.orders.all
Has_Many
Friday, June 24, 2011
@Schneems
• 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
• ...
Has_Many
Friday, June 24, 2011
• N+1 - (Cont.)
@Schneems
customers = Customer.all
customers.each do |customer|
customer.orders do |order|
order.products do |product|
puts product
end
end
Associations
This would generate 10,001 database queries(not a good thing)
Friday, June 24, 2011
• N+1 - How do we Fix it?
• What if we could Pre-load Associations?
• Includes
This would generate 1 database query!!Will take significantly less time than alternative
Note: database access is almost always be your bottleneck
@Schneems
Customer.includes(:orders => :products).all
Associations
Friday, June 24, 2011
@Schneems
Has_Many :Through =>• Chain Associations Using :Through
What Classes have foreign keys?
Friday, June 24, 2011
@Schneems
• Appointments
• physician_id
• patient_id
Has_Many :Through =>
What Classes have foreign keys?
Friday, June 24, 2011
• Physician Class
• Uses Appointments
• Finds Patients
• Automatically
@Schneems
>> dr = Physicians.first
>> dr.patients
Has_Many :Through =>
Friday, June 24, 2011
@Schneems
• HABTM (has and belongs to many)
• Creates direct many to many relationship
Has & Belongs To Many
This is essentially using :through with a single purpose table: assemblies_parts
Friday, June 24, 2011
@Schneems
• Use HABTM
• Don’t need to do anything with the relationship model
• Restricted DB size
• Use :through
• Need validations
• Need callbacks
• Need extra attributes
HABTM - Vs. :Through
Friday, June 24, 2011
@Schneems
Questions?http://guides.rubyonrails.orghttp://stackoverflow.com
Friday, June 24, 2011