Agile Web Development with Rails, Edition 4

25.1 rack 21.2 Form Helpers

22 Caching

Restart the server.

curl --silent --dump - --output /dev/null http://localhost:3000/
HTTP/1.1 200 OK 
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Xhr-Current-Location: /
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "e93f57f690ceaa1eeb1e8b2e77a7eaaa"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 3cd1af81-d5d8-4d8f-b6af-be4b5234bdeb
X-Runtime: 0.157084
Content-Length: 6205
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-11-10)
Date: Mon, 10 Dec 2012 23:24:13 GMT
Connection: Keep-Alive
Set-Cookie: _depot_session=SmU4Sno1cGg3d0JlSnQrQ0VsV0tJVTUwNm9wejlweTJ6cVRBWXJjMW0zVGJPakY2RTYzNndzVEVUMmFWY3NtUTdnWXVkaUZqYloyUW5OcmNVVFZyU0w1aEVnTXBEN3NsWGxwVU0xQTI3MlVmMGUwVm1Vd0ZHd0k0R3B1eFZaVlg0Y2R3TzB5c1MzZGZGZFRyNUtybjdJYmRRUTQyU1BwVlRrNHlhRkFoZ1AzVjVzaTdON3g4Y1JRZGpDT0xEZkRYTUpZTytIZ3NqcWpDVGdOYWxUZGhwZz09LS11cXgrY213QW1XR2h5VTUvQnh0THN3PT0%3D--9404d3197518c0d35acc4a4c4b0ebd0e8ea774c2; path=/; HttpOnly
 

add a method to return the latest product

edit app/models/product.rb
  def self.latest
    Product.order('updated_at desc').limit(1).first
  end

set ETAG and LastModified headers on the response

edit app/controllers/store_controller.rb
class StoreController < ApplicationController
  skip_before_filter :authorize
  def index
    if params[:set_locale]
      redirect_to store_path(locale: params[:set_locale])
    else
      @products = Product.order(:title)
      @cart = current_cart
    end
 
    latest = Product.latest
    fresh_when etag: latest, last_modified: latest.created_at.utc
    expires_in 10.minutes, public: true
  end
end
curl --silent --dump - --output /dev/null http://localhost:3000/
HTTP/1.1 200 OK 
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Xhr-Current-Location: /
Etag: "82d03041ae6d6e0db734802c5577023b"
Last-Modified: Mon, 10 Dec 2012 23:12:02 GMT
Date: Mon, 10 Dec 2012 23:24:13 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 2e89fd07-8192-4467-aa46-8574ec490a38
X-Runtime: 0.339901
Content-Length: 6205
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-11-10)
Connection: Keep-Alive
Set-Cookie: _depot_session=Q3cxVytLcnBnQTI5LytEVkVzMTk1eGZybUNKVElaVkxzd2VlWXpGeGM2K2x4L29kYkJJOFlrN1c5UUJ5S1J4Y013dnlpbGVYVWJnVUllMDdxL0dOT0pCdk9nUytwSHMvZ0NFanJPZGYvRlFYWmFPVzNqTUpPeURjMmZLcVNaUGFjbk00WDdyYmNCRW1CVWtpNmtSb3gwMmJCTmRCNFBwdVVuWlJwazFTR0ZLb1dpZkpLVFdEakxCMXRmaW4vbnJld01zeVA2SCt2S1JDQWwzSGUzSXRtZz09LS1WZStzK1AwS0VPQ2w2NmtCa1M3WGZBPT0%3D--18a53d6c5012da7dd68246b905022b97fe828b81; path=/; HttpOnly
 
curl --silent --dump - --output /dev/null http://localhost:3000/ -H 'If-None-Match: "82d03041ae6d6e0db734802c5577023b"'
HTTP/1.1 304 Not Modified 
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Xhr-Current-Location: /
Etag: "82d03041ae6d6e0db734802c5577023b"
Last-Modified: Mon, 10 Dec 2012 23:12:02 GMT
Date: Mon, 10 Dec 2012 23:24:13 GMT
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: f601e15b-eb1b-4d52-af26-bc24bafd8d1a
X-Runtime: 0.104318
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-11-10)
Connection: close
Set-Cookie: _depot_session=MjZNSlV4dkV0RnJvS0dmaDVaVmNXTDJEUjgzcGJjQndJMkt1QVQrZmFHV1hGYUU0NFErSUxneGoyTmJKYkYxZVBROVVyNFJqZzRBM0tRL2xUdTZwd004bE5uTjZOeThqQlMydWdMRDFYT3M9LS1odGdkYmNJbmd4YzNHT1ZCMTgycnBRPT0%3D--d5ac39babc07ad10a6f4c9690d6e9fe1c025e2ed; path=/; HttpOnly
 
curl --silent --dump - --output /dev/null http://localhost:3000/ -H 'If-Modified-Since: Mon, 10 Dec 2012 23:12:02 GMT'
HTTP/1.1 304 Not Modified 
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Xhr-Current-Location: /
Etag: "82d03041ae6d6e0db734802c5577023b"
Last-Modified: Mon, 10 Dec 2012 23:12:02 GMT
Date: Mon, 10 Dec 2012 23:24:14 GMT
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 8e8d9372-761e-4bde-bf03-6dcaa0925bfd
X-Runtime: 0.113516
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-11-10)
Connection: close
Set-Cookie: _depot_session=QUE5SGhXK1lvclNCdWhmaEpCYjV1RERKRnBuL3FZRi9LelpTMmlaMjBRaUZHR0hRYWpkc2tydDh3Vmp2dUFpUU82MkhrZGlOcVQrR04rcVRXVXd6ZkhiQXh1SkdDNVl2S3MxUHp6c1RjQXc9LS1TcFhvdk1SZlQ0d3ViTndiWjhjNUxBPT0%3D--d1401d9a295160efd466b66ab68bb8a85e902896; path=/; HttpOnly
 

Turn on caching in development

edit config/environments/development.rb
Depot::Application.configure do
  # Settings specified here will take precedence over those in config/application.rb.
 
  # In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false
 
  # Do not eager load code on boot.
  config.eager_load = false
 
  # Show full error reports and disable caching.
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = true
  config.action_dispatch.rack_cache = true
 
  # Don't care if the mailer can't send.
  config.action_mailer.raise_delivery_errors = false
 
  # Don't actually send emails
  config.action_mailer.delivery_method = :test
  #
  # Alternate configuration example, using gmail:
  #   config.action_mailer.delivery_method = :smtp
  #   config.action_mailer.smtp_settings = {
  #     address:        "smtp.gmail.com",
  #     port:           587, 
  #     domain:         "domain.of.sender.net",
  #     authentication: "plain",
  #     user_name:      "dave",
  #     password:       "secret",
  #     enable_starttls_auto: true
  #   } 
 
  # Print deprecation notices to the Rails logger.
  config.active_support.deprecation = :log
 
  # Only use best-standards-support built into browsers.
  config.action_dispatch.best_standards_support = :builtin
 
  # Log the query plan for queries taking more than this (works
  # with SQLite, MySQL, and PostgreSQL).
  config.active_record.auto_explain_threshold_in_seconds = 0.5
 
  # Raise an error on page load if there are pending migrations
  config.active_record.migration_error = :page_load
 
  # Debug mode disables concatenation and preprocessing of assets.
  config.assets.debug = true
end

add 'rack-cache' to the bundle

edit Gemfile
gem 'rack-cache'
bundle install
Using rake (10.0.2) 
Using i18n (0.6.1) 
Using minitest (4.3.3) 
Using multi_json (1.5.0) 
Using tzinfo (0.3.35) 
Using activesupport (4.0.0.beta) 
Using builder (3.1.4) 
Using erubis (2.7.0) 
Using journey (2.0.0.20120723141804) 
Using rack (1.4.1) 
Using rack-test (0.6.2) 
Using actionpack (4.0.0.beta) 
Using mime-types (1.19) 
Using polyglot (0.3.3) 
Using treetop (1.4.12) 
Using mail (2.5.3) 
Using actionmailer (4.0.0.beta) 
Using activemodel (4.0.0.beta) 
Using activerecord-deprecated_finders (0.0.1) 
Using arel (3.0.2.20120819075748) 
Using activerecord (4.0.0.beta) 
Using activeresource (4.0.0.beta) 
Using bcrypt-ruby (3.0.1) 
Using bundler (1.2.3) 
Using highline (1.6.15) 
Using net-ssh (2.6.2) 
Using net-scp (1.0.4) 
Using net-sftp (2.0.5) 
Using net-ssh-gateway (1.1.0) 
Using capistrano (2.13.5) 
Using coffee-script-source (1.4.0) 
Using execjs (1.4.0) 
Using coffee-script (2.2.0) 
Using json (1.7.5) 
Using rdoc (3.12) 
Using thor (0.16.0) 
Using railties (4.0.0.beta) 
Using coffee-rails (4.0.0.beta) 
Using hike (1.2.1) 
Using jquery-rails (2.1.4) 
Using kaminari (0.14.1) 
Using mysql2 (0.3.11) 
Using rack-cache (1.2) 
Using tilt (1.3.3) 
Using sprockets (2.8.2) 
Using sprockets-rails (2.0.0.rc1) 
Using rails (4.0.0.beta) 
Using sass (3.2.3) 
Using sass-rails (4.0.0.beta) 
Using sqlite3 (1.3.6) 
Using turbolinks (0.6.1) 
Using uglifier (1.3.0) 
Updating files in vendor/cache
Could not find activesupport-4.0.0.beta.gem for installation

Restart the server.

rake middleware
use Rack::Cache
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000047392c8>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::EncryptedCookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
run Depot::Application.routes
curl --silent --dump - --output /dev/null http://localhost:3000/
HTTP/1.1 200 OK 
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Xhr-Current-Location: /
Etag: "82d03041ae6d6e0db734802c5577023b"
Last-Modified: Mon, 10 Dec 2012 23:12:02 GMT
Date: Mon, 10 Dec 2012 23:24:25 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 23c89a63-f820-4901-aa31-6c96ef256918
X-Runtime: 0.925845
X-Content-Digest: e3571783e5eea00a9ad9905e2e95c43ba45d6f4f
Content-Length: 6205
Age: 7
X-Rack-Cache: fresh
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-11-10)
Connection: Keep-Alive
 
curl --silent --dump - --output /dev/null http://localhost:3000/ -H 'If-None-Match: "82d03041ae6d6e0db734802c5577023b"'
HTTP/1.1 304 Not Modified 
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Xhr-Current-Location: /
Etag: "82d03041ae6d6e0db734802c5577023b"
Date: Mon, 10 Dec 2012 23:24:25 GMT
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 23c89a63-f820-4901-aa31-6c96ef256918
X-Runtime: 0.925845
X-Content-Digest: e3571783e5eea00a9ad9905e2e95c43ba45d6f4f
Age: 7
X-Rack-Cache: fresh
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-11-10)
Connection: close
 

25.1 rack 21.2 Form Helpers