Module: Merb::ConditionalGetMixin

Included in:
Controller
Defined in:
merb-core/lib/merb-core/controller/mixins/conditional_get.rb

Overview

Provides conditional get support in Merb core. Conditional get support is intentionally simple and does not do fancy stuff like making ETag value from Ruby objects for you.

The most interesting method for end user is #request_fresh? that is used after setting of last modification time or ETag:

def show
  self.etag = Digest::SHA1.hexdigest(calculate_cache_key(params))

  if request_fresh?
    self.status = 304
    return ''
  else
    @product = Product.get(params[:id])
    display @product
  end
end

See Also:

Instance Method Summary (collapse)

Instance Method Details

- (String?) etag

Value of the ETag header.

Returns:

  • (String)

    Value of ETag response header if set.

  • (nil)

    If ETag header not set.



43
44
45
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 43

def etag
  headers[Merb::Const::ETAG]
end

- (String) etag=(tag)

Sets ETag response header by calling #to_s on the argument

Parameters:

  • tag (#to_s)

    value of ETag header

Returns:

  • (String)

    Value of ETag header enclosed in double quotes as required by the RFC.



33
34
35
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 33

def etag=(tag)
  headers[Merb::Const::ETAG] = %("#{tag}")
end

- (Boolean) etag_matches?(tag = self.etag)

Test to see if the request's Etag matches the one supplied locally

Returns:

  • (Boolean)

    True if ETag response header equals If-None-Match request header, false if it does not.



53
54
55
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 53

def etag_matches?(tag = self.etag)
  tag == self.request.if_none_match
end

- (Time?) last_modified

Value of the Last-Modified header

Returns:

  • (Time)

    Value of Last-Modified response header if set.

  • (nil)

    If Last-Modified not set.



77
78
79
80
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 77

def last_modified
  last_mod = headers[Merb::Const::LAST_MODIFIED]
  Time.rfc2822(last_mod) if last_mod
end

- (String) last_modified=(time)

Sets Last-Modified response header

Parameters:

  • time (Time, DateTime)

    The last modified time of the resource

Returns:

  • (String)

    The last modified time of the resource in the format required by the RFC



65
66
67
68
69
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 65

def last_modified=(time)
  time = time.to_time if time.is_a?(DateTime)
  # time.utc.strftime("%a, %d %b %Y %X") if we could rely on locale being American
  headers[Merb::Const::LAST_MODIFIED] = time.httpdate
end

- (Boolean) not_modified?(time = self.last_modified)

Test to see if the request's If-Modified-Since is satisfied

Parameters:

  • time (Time) (defaults to: self.last_modified)

    Time to test if the If-Modified-Since header against

Returns:

  • (Boolean)

    True if Last-Modified response header is smaller than If-Modified-Since request header, false otherwise.



90
91
92
93
94
95
96
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 90

def not_modified?(time = self.last_modified)
  if !request.if_modified_since.nil? and !time.nil?
    time <= request.if_modified_since
  else
    false
  end
end

- (Boolean) request_fresh?

Tests freshness of response using all supplied validators

A response with no validators is always stale.

Returns:

  • (Boolean)

    True if ETag matches and entity is not modified, false if one or more validators failed, or none were supplied



106
107
108
109
110
111
112
113
114
115
116
# File 'merb-core/lib/merb-core/controller/mixins/conditional_get.rb', line 106

def request_fresh?
  # make sure we have something to compare too.
  return false unless last_modified or etag

  fresh = true

  # only check if we have set the right headers
  fresh &&= etag_matches?(self.etag) if etag
  fresh &&= not_modified?(self.last_modified) if last_modified
  fresh
end