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: "5bb3f6b40f80c80451f647aa7ed3d133"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: a38f0caf-5c72-42d9-9bfc-c5863a2020c1
X-Runtime: 0.331800
Content-Length: 6205
Server: WEBrick/1.3.1 (Ruby/2.0.0/2012-12-10)
Date: Mon, 10 Dec 2012 01:00:53 GMT
Connection: Keep-Alive
Set-Cookie: _depot_session=blVaOHZ4RWpRaDNYbzg1Mkl3UVFEWEhoOVhwT3d5THdlWFNXL1NNTFYwbVI2d3VMZkgyTXNYRjRTSnZLVkVFa0huTk5uYW9YRGNad1ZzaG1ZRnVJdzNTa3c3ck1LQnFKeUJYZmg1VW1sYldDTU9OM3V6N29idERqcElCTXJIWkpiUmNRRjR3RUFieVBrS0NUcTF1TE5GbnowUGZESHgrbFI4S0hZUGZLN0RnNWRqajFuOTF0Z3FYSGJHTUx6R0t3eUYzZlhHc1pKZGJsbWR5UlJXSWVydz09LS1EWEZsMldvZGVLb080US9lNStjWStnPT0%3D--3acbc565a26311e06faa20edb38b2cfe4c0c50c0; 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: "1c3e833cf0a378d3337f01528bb0a240"
Last-Modified: Mon, 10 Dec 2012 00:51:47 GMT
Date: Mon, 10 Dec 2012 01:00:53 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: edbb246d-2673-4b05-8285-a47e1d6389a2
X-Runtime: 0.549744
Content-Length: 6205
Server: WEBrick/1.3.1 (Ruby/2.0.0/2012-12-10)
Connection: Keep-Alive
Set-Cookie: _depot_session=WDE5N2dmRTFpV2UwbnY0d004MDJ3NlhGTnN0UEpLbVZSMEZBczRleElJOVNPL2tOU05SbzZqQzV4QTBLT0Q1am5NeHAyRXp6NjFWSGl3YkE4VXBXdy9CY2p6UGlMWGlDWDhJbGZiVjRlbTV5M2hjMVJXQ3QxNFRheFRkU1RDMzBpY2hoRVBkQzMwM3F2czV4TDhkVk85Sjg1dE1nRGFINU83WHZZQTNmRnlqT0ZhU0lDTC9iYWNJbHowZVE4WERDUjJJRko2cWoyZkVQaS9Ic2FlN2pDQT09LS1uWmxBTTdKdXRaTnU1Tzk5QUJrOUh3PT0%3D--dc12f83652c0c4cdc13d93bbe04cdbb4df29cdf8; path=/; HttpOnly
 
curl --silent --dump - --output /dev/null http://localhost:3000/ -H 'If-None-Match: "1c3e833cf0a378d3337f01528bb0a240"'
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: "1c3e833cf0a378d3337f01528bb0a240"
Last-Modified: Mon, 10 Dec 2012 00:51:47 GMT
Date: Mon, 10 Dec 2012 01:00:54 GMT
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 71c2c554-d6f3-4c76-912d-323b890ff1e0
X-Runtime: 0.147894
Server: WEBrick/1.3.1 (Ruby/2.0.0/2012-12-10)
Connection: Keep-Alive
Set-Cookie: _depot_session=V3hlSGt4dmtuRHFGVHV2VUVBdml6TFVqTUlDdlIwUDZpbkZaU09kOFR6Vm5oblU1cFEydkdXVkVWNGxIbGdQUi9DRTVJaWxJMU1JT3gxMit4SGJ0d2FzeGhuMXBGVWJoZ0wyYUVFd1ZTL2s9LS1XbStLR1RQcjErSEV4TWdVenhMbi9RPT0%3D--854c64005c9fb61e461a6eb853f0ca99db116758; path=/; HttpOnly
 
curl --silent --dump - --output /dev/null http://localhost:3000/ -H 'If-Modified-Since: Mon, 10 Dec 2012 00:51:47 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: "1c3e833cf0a378d3337f01528bb0a240"
Last-Modified: Mon, 10 Dec 2012 00:51:47 GMT
Date: Mon, 10 Dec 2012 01:00:54 GMT
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 42ab7c5f-f6d8-43da-be76-0a4e3be65eb4
X-Runtime: 0.114905
Server: WEBrick/1.3.1 (Ruby/2.0.0/2012-12-10)
Connection: Keep-Alive
Set-Cookie: _depot_session=NXBTYTRPcW8rdFpmVEs2cWlPT3RpSlpuYjJCcjlZTjN4VlpUZGp3TkR3K0VnNkhhRHpoZWNFdEZwUFFnc1lEVGhCbFFudnVyekYwc3pwRUd3cFhXUnl0dWV2aXNwV2M3enVuMkQ4ZnViaEE9LS1DZFBGM2ZJUUQ0NmRZc2dqTEpIZk5nPT0%3D--85343fd2b49ba0d31a399bf24f3ea3c34b50237a; 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.4.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.1) 
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:0x000000029cb3a8>
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: "1c3e833cf0a378d3337f01528bb0a240"
Last-Modified: Mon, 10 Dec 2012 00:51:47 GMT
Date: Mon, 10 Dec 2012 01:01:06 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 391d702c-8062-4068-8187-b1e7c4d49bb8
X-Runtime: 1.077676
X-Content-Digest: 829cb4ba20376043707a20f34957dd6fb3012824
Content-Length: 6205
Age: 5
X-Rack-Cache: fresh
Server: WEBrick/1.3.1 (Ruby/2.0.0/2012-12-10)
Connection: Keep-Alive
 
curl --silent --dump - --output /dev/null http://localhost:3000/ -H 'If-None-Match: "1c3e833cf0a378d3337f01528bb0a240"'
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: "1c3e833cf0a378d3337f01528bb0a240"
Date: Mon, 10 Dec 2012 01:01:06 GMT
Cache-Control: max-age=600, public
X-Ua-Compatible: IE=Edge
X-Request-Id: 391d702c-8062-4068-8187-b1e7c4d49bb8
X-Runtime: 1.077676
X-Content-Digest: 829cb4ba20376043707a20f34957dd6fb3012824
Age: 5
X-Rack-Cache: fresh
Server: WEBrick/1.3.1 (Ruby/2.0.0/2012-12-10)
Connection: Keep-Alive
 

25.1 rack 21.2 Form Helpers