Your SlideShare is downloading. ×
Rails 3 Beginner to Builder 2011 Week 8
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Rails 3 Beginner to Builder 2011 Week 8

7,589

Published on

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 …

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

Published in: Education, Technology
2 Comments
2 Likes
Statistics
Notes
No Downloads
Views
Total Views
7,589
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
118
Comments
2
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Beginner to Builder Week8July, 2011Monday, August 8, 11
  • 2. Rails - Week 8 • Dealing with nil • Acceptance Testing • Partials • Cells • Memcache@SchneemsMonday, August 8, 11
  • 3. Dealing with Nil user = 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>@SchneemsMonday, August 8, 11
  • 4. 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"@SchneemsMonday, August 8, 11
  • 5. || & ||= 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@SchneemsMonday, August 8, 11
  • 6. ‘if’ returns result # if returns to where it was called result = if true "foo" else "bar" end puts result >> "foo" result = if false "foo" else "bar" end puts result >> "bar"@SchneemsMonday, August 8, 11
  • 7. Acceptance Testing • Run your full application stack • Behavior Driven Development (BDD) • High payout for little time testing • slow • potentially brittle@SchneemsMonday, August 8, 11
  • 8. Capybara & Rspec • Capybara • Headless browser • open your webpages • click links ... Gemfile gem capybara, 0.3.7 gem rspec-rails, 1.3.2@SchneemsMonday, August 8, 11
  • 9. Capybara & Rspec # go to a path visit root_path visit "/" # click buttons click "sign in" # fill out forms fill_in ‘Email’, :with => "schneems@example.com"@SchneemsMonday, August 8, 11
  • 10. Capybara & Rspec http://codingfrontier.com/integration-testing-setup-with-rspec-and-capy /spec/acceptance/signin_spec.rb 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@SchneemsMonday, August 8, 11
  • 11. DRY Views • Helpers • Small resusable components • content_for • Control page flow of compnents out of normal placement • Partials • Large reusable components • Cells • type logic is needed when controller Reusable components@SchneemsMonday, August 8, 11
  • 12. ViewHelpers • Rails has build in helpers • link_to • image_tag • etc. • Write your Own@SchneemsMonday, August 8, 11
  • 13. ViewHelpers app/helpers/product_helper.rb link_to_product(product = nil) link_to image_tag(product.image_url), product_path(product), :class => product end app/views/product/index.html.erb <%= link_to_product(@product) %> <a href=“...” class=”product”> <imgr src = “...” /> </a>@SchneemsMonday, August 8, 11
  • 14. content_for & yield • Replace content using content_for <head> <title> <html> <%= yield :head %> <head> </title> <title>A simple page</title> </head> </head> <p>Hello, Rails!</p> <body> => <p>Hello, Rails!</p> <% content_for :head do %> </body> A simple page </html> <% end %>@SchneemsMonday, August 8, 11
  • 15. 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>@SchneemsMonday, August 8, 11
  • 16. 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 %>@SchneemsMonday, August 8, 11
  • 17. Partials • Reusable chunks of view code <%# 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 %>@SchneemsMonday, August 8, 11
  • 18. Partials <%# renders spots.html.erb for each spot in @spots %> <%= render @spots %> /spots/_spots.html.erb <div> <h3>Name:</h3> <p><%= spot.name %></p> <p><%= spot.description %></p> </div>@SchneemsMonday, August 8, 11
  • 19. Partials • Locals <%# renders spots.html.erb for each spot in @spots %> <%= render @spots, :locals => {:foo => ”bar”} %> /spots/_spots.html.erb <div> <h3>Name:</h3> <p><%= spot.name %></p> <p><%= spot.description %></p> <p><%= foo %></p> </div>@SchneemsMonday, August 8, 11
  • 20. Partials • Optional Locals <%# renders spot.html.erb for each spot in @spots %> <%= render @spot2 %> /spots/_spot.html.erb <div> <h3>Name:</h3> <p><%= spot.name %></p> <p><%= spot.description %></p> <p><%= local_assigns[:foo]||something else %></p> </div>@SchneemsMonday, August 8, 11
  • 21. Cells • View Components • Look and Feel like Controllers gem install cells@SchneemsMonday, August 8, 11
  • 22. Cells /app/views/product/index.html <div id="header"> <%= render_cell :cart, :display, :user => @current_user %> /app/cells/cart_cell.rb class CartCell < Cell::Rails def display(options) user = args[:user] @items = user.items_in_cart render # renders display.html.haml end end /app/cells/cart.display.html.erb <p>You have <%= @items.size %></p>@SchneemsMonday, August 8, 11
  • 23. DRY Views • Helpers • Small resusable components • content_for • Control page flow of compnents out of normal placement • Partials • Large reusable components • Cells • type logic is needed when controller Reusable components@SchneemsMonday, August 8, 11
  • 24. Caching • Store data in alater so it can be served quicker cache@SchneemsMonday, August 8, 11
  • 25. Page Caching • Super Fast • Limited use cases class ProductsController < ActionController caches_page :index def index @products = Products.all end end http://guides.rubyonrails.org/caching_with_rails.html@SchneemsMonday, August 8, 11
  • 26. Page Caching class 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@SchneemsMonday, August 8, 11
  • 27. Action Caching • Allows Authentication checks class ProductsController < ActionController before_filter :authenticate caches_action :index def index @products = Product.all end def create expire_action :action => :index end end@SchneemsMonday, August 8, 11
  • 28. Action Caching • :layout => false • allows dynamic currentthe layout to render such as info in user • :if & :unless • caches_action :index, :layout => false caches_action :index, :if => lambda {current_user.present?} caches_action :index, :unless => lambda {current_user.blank?}@SchneemsMonday, August 8, 11
  • 29. Fragment Caching • Cache individual parts of pages <% cache(all_available_products) do %> All available products: <% end %>@SchneemsMonday, August 8, 11
  • 30. Fragment Caching • Cache individual parts of pages <% cache(:action => recent, :action_suffix => all_products) do %> All available products: ... <%- end -%>@SchneemsMonday, August 8, 11
  • 31. Fragment Caching • Expire fragments expire_fragment(:controller => products, :action => recent, :action_suffix => all_products)@SchneemsMonday, August 8, 11
  • 32. Sweeping Cache class ProductsController < ActionController before_filter :authenticate caches_action :index cache_sweeper :product_sweeper def index @products = Product.all end end@SchneemsMonday, August 8, 11
  • 33. Sweeping Cache class 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@SchneemsMonday, August 8, 11
  • 34. Cache Stores • Set the Cache store in your environment ActionController::Base.cache_store = :memory_store ActionController::Base.cache_store = :drb_store, "druby://localhost:9192" ActionController::Base.cache_store = :mem_cache_store, "localhost"@SchneemsMonday, August 8, 11
  • 35. Cache Stores • Simple Key/Value storage Rails.cache.read("city") # => nil Rails.cache.write("city", "Duckburgh") Rails.cache.read("city") # => "Duckburgh"@SchneemsMonday, August 8, 11
  • 36. Cache Stores • fetch Rails.cache.read("city") # => nil Rails.cache.fetch("city") do "Duckburgh" end # => "Duckburgh" Rails.cache.read("city") # => "Duckburgh"@SchneemsMonday, August 8, 11
  • 37. Cache Stores • Expires_in Rails.cache.write("city", "Duckburgh", :expires_in => 1.minute) Rails.cache.read("city") # => "Duckburgh" sleep 120 Rails.cache.read("city") # => nil@SchneemsMonday, August 8, 11
  • 38. Memcache • Cache your rails objects • Memcache Gem • Key Value Store (NOSQL) • Use to cache Expensive Queries require memcached $cache = Memcached.new("localhost:11211") $cache.set("foo", "bar") $cache.get("foo") => "bar"@SchneemsMonday, August 8, 11
  • 39. Memcache # 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 ... >@SchneemsMonday, August 8, 11
  • 40. Memcache ActionController::Base.cache_store = :mem_cache_store, "localhost"@SchneemsMonday, August 8, 11
  • 41. Memcache • Cache frequent queries 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 ... >@SchneemsMonday, August 8, 11
  • 42. Memcache • Cache expensive queries 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@SchneemsMonday, August 8, 11
  • 43. Memcache • Blazing Fast # 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@SchneemsMonday, August 8, 11
  • 44. Memcache • Key Value Store • Holds ruby objects • Extremely fast • volatile • available on Heroku >> heroku addons:add memcache@SchneemsMonday, August 8, 11
  • 45. Bonus - Keytar class User < ActiveRecord::Base • includeKeytar to generate Keys Use Keytar define_keys :username, :friends • end Use those keys in Memcache 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 ... >, ... ]@SchneemsMonday, August 8, 11
  • 46. Questions? http://guides.rubyonrails.org http://stackoverflow.com http://peepcode.com@SchneemsMonday, August 8, 11

×