rails 3 beginner to builder 2011 week 8

46
July, 2011 Beginner to Builder Week8 Monday, August 8, 11

Upload: richard-schneeman

Post on 10-May-2015

7.602 views

Category:

Education


4 download

DESCRIPTION

This is the last 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.com/tagged/Rails-3-beginner-to-builder-2011

TRANSCRIPT

Page 1: Rails 3 Beginner to Builder 2011 Week 8

July, 2011

Beginner to BuilderWeek8

Monday, August 8, 11

Page 2: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Rails - Week 8• Dealing with nil

• Acceptance Testing

• Partials

• Cells

• Memcache

Monday, August 8, 11

Page 3: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Dealing with Niluser = User.where(:username => "schneems").first

#<User ... >

user.image_url

>> "/schneems.png"

user = nil

user.image_url

# NameError: undefined local variable or method `user'

for #<Object:0x1001dc288>

Monday, August 8, 11

Page 4: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

try to deal# use try from ActiveSupport

user = User.where(:username => "schneems").first

#<User ... >

user.try(:image_url) || "/not_found.png"

>> "/schneems.png"

user = nil

user.try(:image_url) || "/not_found.png"

>> "/not_found.png"

Monday, August 8, 11

Page 5: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

|| & ||=per_page = params[:per_page]

per_page = 10 if per_page.blank?

# instead

per_page = params[:per_page]||10

# or

per_page = params[:per_page]

per_page ||= 10

Monday, August 8, 11

Page 6: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

‘if’ returns result# if returns to where it was calledresult = if true "foo"else "bar"end

puts result>> "foo"

result = if false "foo"else "bar"end

puts result>> "bar"

Monday, August 8, 11

Page 7: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Acceptance Testing• Run your full application stack

• Behavior Driven Development (BDD)

• High payout for little time testing

• slow

• potentially brittle

Monday, August 8, 11

Page 8: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

gem 'capybara', '0.3.7'

gem 'rspec-rails', '1.3.2'

Capybara & Rspec• Capybara

• Headless browser

• open your webpages

• click links ...

Gemfile

Monday, August 8, 11

Page 9: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

# go to a path

visit root_path

visit "/"

# click buttons

click "sign in"

# fill out forms

fill_in ‘Email’, :with => "[email protected]"

Capybara & Rspec

Monday, August 8, 11

Page 10: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

context "as a guest on the sign in page" do # Generate a valid user let(:user) { Factory(:user) } context ‘with valid credentials’ do #Fill in the form with the user’s credentials and submit it. before do visit root_path click ‘Sign In’ fill_in ‘Email’, :with => user.email fill_in ‘Password’, :with => ‘password’ click ‘Submit’ end

it "has a sign out link" do page.should have_xpath(‘//a’, :text => ‘Sign Out’) end

it "knows who I am" do page.should have_content(“Welcome, #{user.email}!”) end end end

Capybara & Rspechttp://codingfrontier.com/integration-testing-setup-with-rspec-and-capy

/spec/acceptance/signin_spec.rb

Monday, August 8, 11

Page 11: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

DRY Views• Helpers

• Small resusable components

• content_for

• Control placement of compnents out of normal page flow

• Partials

• Large reusable components

• Cells

• Reusable components when controller type logic is needed

Monday, August 8, 11

Page 12: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

ViewHelpers• Rails has build in helpers

• link_to

• image_tag

• etc.

• Write your Own

Monday, August 8, 11

Page 13: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

link_to_product(product = nil)

link_to image_tag(product.image_url),

product_path(product), :class => 'product'

end

ViewHelpersapp/helpers/product_helper.rb

<%= link_to_product(@product) %>

app/views/product/index.html.erb

<a href=“...” class=”product”>

<imgr src = “...” />

</a>

Monday, August 8, 11

Page 14: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

content_for & yield• Replace content using content_for

<head>

<title>

<%= yield :head %>

</title>

</head>

<p>Hello, Rails!</p>

<% content_for :head do %>

A simple page

<% end %>

<html>

<head>

<title>A simple page</title>

</head>

<body>

<p>Hello, Rails!</p>

</body>

</html>

=>

Monday, August 8, 11

Page 15: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

content_for in layouts• use helpers & content_for together

in layouts

<body id="<%= id_for_body(yield(:body_id)) %>"

class="<%= classes_for_body(yield(:body_class)) %>

<%= logged_in? ? 'logged-in' : 'not-logged-in' %>">

<%= yield %>

</body>

Monday, August 8, 11

Page 16: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

content_for in layouts# content_for head<%= yield :head_analytics %><%= yield :head_stylesheets %><%= yield :head_scripts %><%= yield :head %>

# content_for body<%= yield :main_title %><%= yield :sidebar_title %><%= yield :sidebar %>

# content_for footer<%= yield :footer %><%= yield :footer_libraries %><%= yield :footer_scripts %><%= yield :footer_analytics %>

Monday, August 8, 11

Page 17: Rails 3 Beginner to Builder 2011 Week 8

• Reusable chunks of view code

@Schneems

<%# renders 'spots.html.erb' with @spot %>

<%= render :partial => "spot", :object => @spot %>

<%= render "spot", :object => @spot %>

<%= render @spot %>

<%# renders 'spots.html.erb' for each spot in @spots %>

<%= render @spots %>

<%= render "spot", :collection => @spots %>

Partials

Monday, August 8, 11

Page 18: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

<%# renders 'spots.html.erb' for each spot in @spots %>

<%= render @spots %>

Partials

<div>

<h3>Name:</h3>

<p><%= spot.name %></p>

<p><%= spot.description %></p>

</div>

/spots/_spots.html.erb

Monday, August 8, 11

Page 19: Rails 3 Beginner to Builder 2011 Week 8

• Locals

@Schneems

<%# renders 'spots.html.erb' for each spot in @spots %>

<%= render @spots, :locals => {:foo => ”bar”} %>

Partials

<div>

<h3>Name:</h3>

<p><%= spot.name %></p>

<p><%= spot.description %></p>

<p><%= foo %></p>

</div>

/spots/_spots.html.erb

Monday, August 8, 11

Page 20: Rails 3 Beginner to Builder 2011 Week 8

• Optional Locals

@Schneems

<%# renders 'spot.html.erb' for each spot in @spots %>

<%= render @spot2 %>

Partials

<div>

<h3>Name:</h3>

<p><%= spot.name %></p>

<p><%= spot.description %></p>

<p><%= local_assigns[:foo]||'something else' %></p>

</div>

/spots/_spot.html.erb

Monday, August 8, 11

Page 21: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

gem install cells

Cells• View Components

• Look and Feel like Controllers

Monday, August 8, 11

Page 22: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

<div id="header">

<%= render_cell :cart, :display, :user => @current_user %>

Cells/app/views/product/index.html

class CartCell < Cell::Rails

def display(options)

user = args[:user]

@items = user.items_in_cart

render # renders display.html.haml

end

end

<p>You have <%= @items.size %></p>

/app/cells/cart_cell.rb

/app/cells/cart.display.html.erb

Monday, August 8, 11

Page 23: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

DRY Views• Helpers

• Small resusable components

• content_for

• Control placement of compnents out of normal page flow

• Partials

• Large reusable components

• Cells

• Reusable components when controller type logic is needed

Monday, August 8, 11

Page 24: Rails 3 Beginner to Builder 2011 Week 8

• Store data in a cache so it can be served quicker later

@Schneems

Caching

Monday, August 8, 11

Page 25: Rails 3 Beginner to Builder 2011 Week 8

• Super Fast

• Limited use cases

@Schneems

Page Caching

class ProductsController < ActionController

caches_page :index

def index

@products = Products.all

end

end

http://guides.rubyonrails.org/caching_with_rails.html

Monday, August 8, 11

Page 26: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Page Cachingclass ProductsController < ActionController

caches_page :index

def index

@products = Products.all

end

def create

expire_page :action => :index

end

end

http://guides.rubyonrails.org/caching_with_rails.html

Monday, August 8, 11

Page 27: Rails 3 Beginner to Builder 2011 Week 8

• Allows Authentication checks

@Schneems

Action Caching

class ProductsController < ActionController

before_filter :authenticate

caches_action :index

def index

@products = Product.all

end

def create

expire_action :action => :index

end

end

Monday, August 8, 11

Page 28: Rails 3 Beginner to Builder 2011 Week 8

• :layout => false

• allows dynamic info in the layout to render such as current user

• :if & :unless

@Schneems

Action Caching

caches_action :index, :layout => false

caches_action :index, :if => lambda {current_user.present?}

caches_action :index, :unless => lambda {current_user.blank?}

Monday, August 8, 11

Page 29: Rails 3 Beginner to Builder 2011 Week 8

• Cache individual parts of pages

@Schneems

Fragment Caching

<% cache('all_available_products') do %>

All available products:

<% end %>

Monday, August 8, 11

Page 30: Rails 3 Beginner to Builder 2011 Week 8

• Cache individual parts of pages

@Schneems

Fragment Caching

<% cache(:action => 'recent',

:action_suffix => 'all_products') do %>

All available products:

...

<%- end -%>

Monday, August 8, 11

Page 31: Rails 3 Beginner to Builder 2011 Week 8

• Expire fragments

@Schneems

Fragment Caching

expire_fragment(:controller => 'products',

:action => 'recent',

:action_suffix => 'all_products')

Monday, August 8, 11

Page 32: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Sweeping Cache

class ProductsController < ActionController

before_filter :authenticate

caches_action :index

cache_sweeper :product_sweeper

def index

@products = Product.all

end

end

Monday, August 8, 11

Page 33: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Sweeping Cacheclass ProductSweeper < ActionController::Caching::Sweeper

observe Product # This sweeper is going to keep an eye on the Product model

# If our sweeper detects that a Product was created call this def after_create(product)

expire_cache_for(product)

end

private

def expire_cache_for(product)

# Expire the index page now that we added a new product

expire_page(:controller => 'products', :action => 'index')

expire_fragment('all_available_products')

end

end

Monday, August 8, 11

Page 34: Rails 3 Beginner to Builder 2011 Week 8

• Set the Cache store in your environment

@Schneems

Cache Stores

ActionController::Base.cache_store = :memory_store

ActionController::Base.cache_store = :drb_store,

"druby://localhost:9192"

ActionController::Base.cache_store = :mem_cache_store,

"localhost"

Monday, August 8, 11

Page 35: Rails 3 Beginner to Builder 2011 Week 8

• Simple Key/Value storage

@Schneems

Cache Stores

Rails.cache.read("city") # => nil

Rails.cache.write("city", "Duckburgh")

Rails.cache.read("city") # => "Duckburgh"

Monday, August 8, 11

Page 36: Rails 3 Beginner to Builder 2011 Week 8

• fetch

@Schneems

Cache Stores

Rails.cache.read("city") # => nil

Rails.cache.fetch("city") do

"Duckburgh"

end

# => "Duckburgh"

Rails.cache.read("city") # => "Duckburgh"

Monday, August 8, 11

Page 37: Rails 3 Beginner to Builder 2011 Week 8

• Expires_in

@Schneems

Cache Stores

Rails.cache.write("city", "Duckburgh", :expires_in =>

1.minute)

Rails.cache.read("city") # => "Duckburgh"

sleep 120

Rails.cache.read("city") # => nil

Monday, August 8, 11

Page 38: Rails 3 Beginner to Builder 2011 Week 8

• Cache your rails objects

• Memcache Gem

• Key Value Store (NOSQL)

• Use to cache Expensive Queries

@Schneems

require 'memcached'

$cache = Memcached.new("localhost:11211")

$cache.set("foo", "bar")

$cache.get("foo")

=> "bar"

Memcache

Monday, August 8, 11

Page 39: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

# store strings

$cache.set("key", "value")

$cache.get("key")

=> "bar"

# store any ruby object

$cache.set("foo", [1,2,3,4,5])

$cache.get("foo")

=> [1,2,3,4,5]

# srsly any ruby object

$cache.set("foo", User.last)

$cache.get("foo")

=> #< User ... >

Memcache

Monday, August 8, 11

Page 40: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

ActionController::Base.cache_store = :mem_cache_store,

"localhost"

Memcache

Monday, August 8, 11

Page 41: Rails 3 Beginner to Builder 2011 Week 8

• Cache frequent queries

@Schneems

class User < ActiveRecord::Base

def self.fetch(username)

Rails.cache.fetch("user:#{username}") do

User.where(:username => "#{username}").first

end

end

end

=> User.fetch("schneems") #=> #<User id: 263595 ... >

Memcache

Monday, August 8, 11

Page 42: Rails 3 Beginner to Builder 2011 Week 8

• Cache expensive queries

@Schneems

class User < ActiveRecord::Base

def fetch_friends

Rails.cache.fetch("users:friends:#{self.id}") do

friends = Friendships.where(:user_1_id => self.id)

end

end

end

=> User.fetch("schneems").fetch_friend_ids

Memcache

Monday, August 8, 11

Page 43: Rails 3 Beginner to Builder 2011 Week 8

• Blazing Fast

@Schneems

# Database

Benchmark.measure do

User.where(:username => "schneems").first

end.real

=> 0.09 s

# Memcache

Benchmark.measure do

User.fetch("schneems")

end.real

=> 0.0009 s

Memcache

Monday, August 8, 11

Page 44: Rails 3 Beginner to Builder 2011 Week 8

• Key Value Store

• Holds ruby objects

• Extremely fast

• volatile

• available on Heroku

@Schneems

>> heroku addons:add memcache

Memcache

Monday, August 8, 11

Page 45: Rails 3 Beginner to Builder 2011 Week 8

• Use Keytar to generate Keys

• Use those keys in Memcache

@Schneems

class User < ActiveRecord::Base

include Keytar

define_keys :username, :friends

end

User.username_key("schneems")

=> "user:username:schneems"

user = Rails.cache.fetch(User.username_key("schneems"))

=> # < User id:33 ... >

user.friends_key

=> "users:friends:33"

friends = Rails.cache.fetch(user.friends_key)

=> #[#< User ... >, #< User ... >, ... ]

Bonus - Keytar

Monday, August 8, 11

Page 46: Rails 3 Beginner to Builder 2011 Week 8

@Schneems

Questions?

http://guides.rubyonrails.orghttp://stackoverflow.com

http://peepcode.com

Monday, August 8, 11