Skip to content

Commit

Permalink
Merge with docrails
Browse files Browse the repository at this point in the history
  • Loading branch information
lifo committed Nov 1, 2008
1 parent 5a02f0b commit b047929
Show file tree
Hide file tree
Showing 26 changed files with 1,096 additions and 611 deletions.
3 changes: 3 additions & 0 deletions actionpack/lib/action_controller/base.rb
Expand Up @@ -1062,6 +1062,9 @@ def default_url_options(options = nil)
# When using <tt>redirect_to :back</tt>, if there is no referrer, # When using <tt>redirect_to :back</tt>, if there is no referrer,
# RedirectBackError will be raised. You may specify some fallback # RedirectBackError will be raised. You may specify some fallback
# behavior for this case by rescuing RedirectBackError. # behavior for this case by rescuing RedirectBackError.
#
# When using <tt>redirect_to</tt> an instance variable called
# @performed_redirect will be set to true.
def redirect_to(options = {}, response_status = {}) #:doc: def redirect_to(options = {}, response_status = {}) #:doc:
raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? raise ActionControllerError.new("Cannot redirect to nil!") if options.nil?


Expand Down
10 changes: 5 additions & 5 deletions actionpack/lib/action_view/helpers/text_helper.rb
Expand Up @@ -344,9 +344,9 @@ def simple_format(text, html_options={})
text << "</p>" text << "</p>"
end end


# Turns all URLs and e-mail addresses into clickable links. The +link+ parameter # Turns all URLs and e-mail addresses into clickable links. The <tt>:link</tt> option
# will limit what should be linked. You can add HTML attributes to the links using # will limit what should be linked. You can add HTML attributes to the links using
# +href_options+. Options for +link+ are <tt>:all</tt> (default), # <tt>:href_options</tt>. Possible values for <tt>:link</tt> are <tt>:all</tt> (default),
# <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and # <tt>:email_addresses</tt>, and <tt>:urls</tt>. If a block is given, each URL and
# e-mail address is yielded and the result is used as the link text. # e-mail address is yielded and the result is used as the link text.
# #
Expand All @@ -355,15 +355,15 @@ def simple_format(text, html_options={})
# # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and # # => "Go to <a href=\"http://www.rubyonrails.org\">http://www.rubyonrails.org</a> and
# # say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>" # # say hello to <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
# #
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :urls) # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :urls)
# # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a> # # => "Visit <a href=\"http://www.loudthinking.com/\">http://www.loudthinking.com/</a>
# # or e-mail david@loudthinking.com" # # or e-mail david@loudthinking.com"
# #
# auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :email_addresses) # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :link => :email_addresses)
# # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>" # # => "Visit http://www.loudthinking.com/ or e-mail <a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>"
# #
# post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com." # post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
# auto_link(post_body, :all, :target => '_blank') do |text| # auto_link(post_body, :href_options => { :target => '_blank' }) do |text|
# truncate(text, 15) # truncate(text, 15)
# end # end
# # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>. # # => "Welcome to my new blog at <a href=\"http://www.myblog.com/\" target=\"_blank\">http://www.m...</a>.
Expand Down
104 changes: 103 additions & 1 deletion activesupport/lib/active_support/cache.rb
@@ -1,7 +1,33 @@
require 'benchmark' require 'benchmark'


module ActiveSupport module ActiveSupport
# See ActiveSupport::Cache::Store for documentation.
module Cache module Cache
# Creates a new CacheStore object according to the given options.
#
# If no arguments are passed to this method, then a new
# ActiveSupport::Cache::MemoryStore object will be returned.
#
# If you pass a Symbol as the first argument, then a corresponding cache
# store class under the ActiveSupport::Cache namespace will be created.
# For example:
#
# ActiveSupport::Cache.lookup_store(:memory_store)
# # => returns a new ActiveSupport::Cache::MemoryStore object
#
# ActiveSupport::Cache.lookup_store(:drb_store)
# # => returns a new ActiveSupport::Cache::DRbStore object
#
# Any additional arguments will be passed to the corresponding cache store
# class's constructor:
#
# ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache")
# # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache")
#
# If the first argument is not a Symbol, then it will simply be returned:
#
# ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
# # => returns MyOwnCacheStore.new
def self.lookup_store(*store_option) def self.lookup_store(*store_option)
store, *parameters = *([ store_option ].flatten) store, *parameters = *([ store_option ].flatten)


Expand Down Expand Up @@ -36,6 +62,21 @@ def self.expand_cache_key(key, namespace = nil)
expanded_cache_key expanded_cache_key
end end


# An abstract cache store class. There are multiple cache store
# implementations, each having its own additional features. See the classes
# under the ActiveSupport::Cache module, e.g.
# ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most
# popular cache store for large production websites.
#
# ActiveSupport::Cache::Store is meant for caching strings. Some cache
# store implementations, like MemoryStore, are able to cache arbitrary
# Ruby objects, but don't count on every cache store to be able to do that.
#
# cache = ActiveSupport::Cache::MemoryStore.new
#
# cache.read("city") # => nil
# cache.write("city", "Duckburgh")
# cache.read("city") # => "Duckburgh"
class Store class Store
cattr_accessor :logger cattr_accessor :logger


Expand All @@ -44,7 +85,46 @@ def silence!
self self
end end


# Pass <tt>:force => true</tt> to force a cache miss. # Fetches data from the cache, using the given key. If there is data in
# the cache with the given key, then that data is returned.
#
# If there is no such data in the cache (a cache miss occurred), then
# then nil will be returned. However, if a block has been passed, then
# that block will be run in the event of a cache miss. The return value
# of the block will be written to the cache under the given cache key,
# and that return value will be returned.
#
# cache.write("today", "Monday")
# cache.fetch("today") # => "Monday"
#
# cache.fetch("city") # => nil
# cache.fetch("city") do
# "Duckburgh"
# end
# cache.fetch("city") # => "Duckburgh"
#
# You may also specify additional options via the +options+ argument.
# Setting <tt>:force => true</tt> will force a cache miss:
#
# cache.write("today", "Monday")
# cache.fetch("today", :force => true) # => nil
#
# Other options will be handled by the specific cache store implementation.
# Internally, #fetch calls #read, and calls #write on a cache miss.
# +options+ will be passed to the #read and #write calls.
#
# For example, MemCacheStore's #write method supports the +:expires_in+
# option, which tells the memcached server to automatically expire the
# cache item after a certain period. We can use this option with #fetch
# too:
#
# cache = ActiveSupport::Cache::MemCacheStore.new
# cache.fetch("foo", :force => true, :expires_in => 5.seconds) do
# "bar"
# end
# cache.fetch("foo") # => "bar"
# sleep(6)
# cache.fetch("foo") # => nil
def fetch(key, options = {}) def fetch(key, options = {})
@logger_off = true @logger_off = true
if !options[:force] && value = read(key, options) if !options[:force] && value = read(key, options)
Expand All @@ -68,10 +148,32 @@ def fetch(key, options = {})
end end
end end


# Fetches data from the cache, using the given key. If there is data in
# the cache with the given key, then that data is returned. Otherwise,
# nil is returned.
#
# You may also specify additional options via the +options+ argument.
# The specific cache store implementation will decide what to do with
# +options+.
def read(key, options = nil) def read(key, options = nil)
log("read", key, options) log("read", key, options)
end end


# Writes the given value to the cache, with the given key.
#
# You may also specify additional options via the +options+ argument.
# The specific cache store implementation will decide what to do with
# +options+.
#
# For example, MemCacheStore supports the +:expires_in+ option, which
# tells the memcached server to automatically expire the cache item after
# a certain period:
#
# cache = ActiveSupport::Cache::MemCacheStore.new
# cache.write("foo", "bar", :expires_in => 5.seconds)
# cache.read("foo") # => "bar"
# sleep(6)
# cache.read("foo") # => nil
def write(key, value, options = nil) def write(key, value, options = nil)
log("write", key, options) log("write", key, options)
end end
Expand Down
1 change: 1 addition & 0 deletions activesupport/lib/active_support/cache/file_store.rb
@@ -1,5 +1,6 @@
module ActiveSupport module ActiveSupport
module Cache module Cache
# A cache store implementation which stores everything on the filesystem.
class FileStore < Store class FileStore < Store
attr_reader :cache_path attr_reader :cache_path


Expand Down
42 changes: 33 additions & 9 deletions activesupport/lib/active_support/cache/mem_cache_store.rb
Expand Up @@ -2,8 +2,19 @@


module ActiveSupport module ActiveSupport
module Cache module Cache
# A cache store implementation which stores data in Memcached:
# http://www.danga.com/memcached/
#
# This is currently the most popular cache store for production websites.
#
# Special features:
# - Clustering and load balancing. One can specify multiple memcached servers,
# and MemCacheStore will load balance between all available servers. If a
# server goes down, then MemCacheStore will ignore it until it goes back
# online.
# - Time-based expiry support. See #write and the +:expires_in+ option.
class MemCacheStore < Store class MemCacheStore < Store
module Response module Response # :nodoc:
STORED = "STORED\r\n" STORED = "STORED\r\n"
NOT_STORED = "NOT_STORED\r\n" NOT_STORED = "NOT_STORED\r\n"
EXISTS = "EXISTS\r\n" EXISTS = "EXISTS\r\n"
Expand All @@ -13,6 +24,14 @@ module Response


attr_reader :addresses attr_reader :addresses


# Creates a new MemCacheStore object, with the given memcached server
# addresses. Each address is either a host name, or a host-with-port string
# in the form of "host_name:port". For example:
#
# ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
#
# If no addresses are specified, then MemCacheStore will connect to
# localhost port 11211 (the default memcached port).
def initialize(*addresses) def initialize(*addresses)
addresses = addresses.flatten addresses = addresses.flatten
options = addresses.extract_options! options = addresses.extract_options!
Expand All @@ -21,16 +40,21 @@ def initialize(*addresses)
@data = MemCache.new(addresses, options) @data = MemCache.new(addresses, options)
end end


def read(key, options = nil) def read(key, options = nil) # :nodoc:
super super
@data.get(key, raw?(options)) @data.get(key, raw?(options))
rescue MemCache::MemCacheError => e rescue MemCache::MemCacheError => e
logger.error("MemCacheError (#{e}): #{e.message}") logger.error("MemCacheError (#{e}): #{e.message}")
nil nil
end end


# Set key = value. Pass :unless_exist => true if you don't # Writes a value to the cache.
# want to update the cache if the key is already set. #
# Possible options:
# - +:unless_exist+ - set to true if you don't want to update the cache
# if the key is already set.
# - +:expires_in+ - the number of seconds that this value may stay in
# the cache. See ActiveSupport::Cache::Store#write for an example.
def write(key, value, options = nil) def write(key, value, options = nil)
super super
method = options && options[:unless_exist] ? :add : :set method = options && options[:unless_exist] ? :add : :set
Expand All @@ -44,7 +68,7 @@ def write(key, value, options = nil)
false false
end end


def delete(key, options = nil) def delete(key, options = nil) # :nodoc:
super super
response = @data.delete(key, expires_in(options)) response = @data.delete(key, expires_in(options))
response == Response::DELETED response == Response::DELETED
Expand All @@ -53,13 +77,13 @@ def delete(key, options = nil)
false false
end end


def exist?(key, options = nil) def exist?(key, options = nil) # :nodoc:
# Doesn't call super, cause exist? in memcache is in fact a read # Doesn't call super, cause exist? in memcache is in fact a read
# But who cares? Reading is very fast anyway # But who cares? Reading is very fast anyway
!read(key, options).nil? !read(key, options).nil?
end end


def increment(key, amount = 1) def increment(key, amount = 1) # :nodoc:
log("incrementing", key, amount) log("incrementing", key, amount)


response = @data.incr(key, amount) response = @data.incr(key, amount)
Expand All @@ -68,7 +92,7 @@ def increment(key, amount = 1)
nil nil
end end


def decrement(key, amount = 1) def decrement(key, amount = 1) # :nodoc:
log("decrement", key, amount) log("decrement", key, amount)


response = @data.decr(key, amount) response = @data.decr(key, amount)
Expand All @@ -77,7 +101,7 @@ def decrement(key, amount = 1)
nil nil
end end


def delete_matched(matcher, options = nil) def delete_matched(matcher, options = nil) # :nodoc:
super super
raise "Not supported by Memcache" raise "Not supported by Memcache"
end end
Expand Down
14 changes: 14 additions & 0 deletions activesupport/lib/active_support/cache/memory_store.rb
@@ -1,5 +1,19 @@
module ActiveSupport module ActiveSupport
module Cache module Cache
# A cache store implementation which stores everything into memory in the
# same process. If you're running multiple Ruby on Rails server processes
# (which is the case if you're using mongrel_cluster or Phusion Passenger),
# then this means that your Rails server process instances won't be able
# to share cache data with each other. If your application never performs
# manual cache item expiry (e.g. when you're using generational cache keys),
# then using MemoryStore is ok. Otherwise, consider carefully whether you
# should be using this cache store.
#
# MemoryStore is not only able to store strings, but also arbitrary Ruby
# objects.
#
# MemoryStore is not thread-safe. Use SynchronizedMemoryStore instead
# if you need thread-safety.
class MemoryStore < Store class MemoryStore < Store
def initialize def initialize
@data = {} @data = {}
Expand Down
@@ -1,5 +1,6 @@
module ActiveSupport module ActiveSupport
module Cache module Cache
# Like MemoryStore, but thread-safe.
class SynchronizedMemoryStore < MemoryStore class SynchronizedMemoryStore < MemoryStore
def initialize def initialize
super super
Expand Down

0 comments on commit b047929

Please sign in to comment.