aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpaulccarey <paulccarey@gmail.com>2010-07-29 15:34:59 +0100
committerpaulccarey <paulccarey@gmail.com>2010-07-29 15:34:59 +0100
commit2b2ee222f3012a29c9db95d357a30029100b226b (patch)
tree6359b3994e1b4d77311c2fa039e0a7e9397357c8
parentc178a26ec784f34e82f08e26064d9798edb09e72 (diff)
parent873c5a9e5924a7776692b9a17b03d0becec6e513 (diff)
downloadrails-2b2ee222f3012a29c9db95d357a30029100b226b.tar.gz
rails-2b2ee222f3012a29c9db95d357a30029100b226b.tar.bz2
rails-2b2ee222f3012a29c9db95d357a30029100b226b.zip
Merge branch 'master' of github.com:lifo/docrails
-rw-r--r--actionmailer/README.rdoc4
-rw-r--r--actionmailer/lib/action_mailer/base.rb25
-rw-r--r--activemodel/lib/active_model/dirty.rb5
-rw-r--r--activerecord/lib/active_record/associations.rb2
-rw-r--r--activerecord/lib/active_record/base.rb13
-rw-r--r--activerecord/lib/active_record/persistence.rb15
-rw-r--r--activesupport/lib/active_support/cache.rb45
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb30
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute_accessors.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb26
-rw-r--r--railties/guides/source/active_support_core_extensions.textile15
11 files changed, 119 insertions, 77 deletions
diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc
index 64b0333c0a..b52c993f56 100644
--- a/actionmailer/README.rdoc
+++ b/actionmailer/README.rdoc
@@ -74,9 +74,9 @@ Or you can just chain the methods together like:
== Receiving emails
-To receive emails, you need to implement a public instance method called receive that takes a
+To receive emails, you need to implement a public instance method called <tt>receive</tt> that takes a
tmail object as its single parameter. The Action Mailer framework has a corresponding class method,
-which is also called receive, that accepts a raw, unprocessed email as a string, which it then turns
+which is also called <tt>receive</tt>, that accepts a raw, unprocessed email as a string, which it then turns
into the tmail object and calls the receive instance method.
Example:
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 7bbde53306..1ac8f9da1d 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -41,16 +41,16 @@ module ActionMailer #:nodoc:
# in the same manner as <tt>attachments[]=</tt>
#
# * <tt>headers[]=</tt> - Allows you to specify any header field in your email such
- # as <tt>headers['X-No-Spam'] = 'True'</tt>. Note, while most fields (like <tt>To:</tt>
+ # as <tt>headers['X-No-Spam'] = 'True'</tt>. Note, while most fields like <tt>To:</tt>
# <tt>From:</tt> can only appear once in an email header, other fields like <tt>X-Anything</tt>
# can appear multiple times. If you want to change a field that can appear multiple times,
- # you need to set it to nil first so that Mail knows you are replacing it, not adding
- # another field of the same name.)
+ # you need to set it to nil first so that Mail knows you are replacing it and not adding
+ # another field of the same name.
#
# * <tt>headers(hash)</tt> - Allows you to specify multiple headers in your email such
# as <tt>headers({'X-No-Spam' => 'True', 'In-Reply-To' => '1234@message.id'})</tt>
#
- # * <tt>mail</tt> - Allows you to specify your email to send.
+ # * <tt>mail</tt> - Allows you to specify email to be sent.
#
# The hash passed to the mail method allows you to specify any header that a Mail::Message
# will accept (any valid Email header including optional fields).
@@ -66,7 +66,7 @@ module ActionMailer #:nodoc:
# format.html
# end
#
- # The block syntax is useful if also need to specify information specific to a part:
+ # The block syntax is also useful in providing information specific to a part:
#
# mail(:to => user.email) do |format|
# format.text(:content_transfer_encoding => "base64")
@@ -121,7 +121,7 @@ module ActionMailer #:nodoc:
#
# <%= users_url(:host => "example.com") %>
#
- # You will want to avoid using the <tt>name_of_route_path</tt> form of named routes because it doesn't
+ # You want to avoid using the <tt>name_of_route_path</tt> form of named routes because it doesn't
# make sense to generate relative URLs in email messages.
#
# It is also possible to set a default host that will be used in all mailers by setting the <tt>:host</tt>
@@ -132,7 +132,7 @@ module ActionMailer #:nodoc:
# Setting <tt>ActionMailer::Base.default_url_options</tt> directly is now deprecated, use the configuration
# option mentioned above to set the default host.
#
- # If you do decide to set a default <tt>:host</tt> for your mailers you will want to use the
+ # If you do decide to set a default <tt>:host</tt> for your mailers you want to use the
# <tt>:only_path => false</tt> option when using <tt>url_for</tt>. This will ensure that absolute URLs are
# generated because the <tt>url_for</tt> view helper will, by default, generate relative URLs when a
# <tt>:host</tt> option isn't explicitly provided.
@@ -154,7 +154,7 @@ module ActionMailer #:nodoc:
# detect and use multipart templates, where each template is named after the name of the action, followed
# by the content type. Each such detected template will be added as separate part to the message.
#
- # For example, if the following templates existed:
+ # For example, if the following templates exist:
# * signup_notification.text.plain.erb
# * signup_notification.text.html.erb
# * signup_notification.text.xml.builder
@@ -171,8 +171,7 @@ module ActionMailer #:nodoc:
#
# = Attachments
#
- # You can see above how to make a multipart HTML / Text email, to send attachments is just
- # as easy:
+ # Sending attachment in emails is easy:
#
# class ApplicationMailer < ActionMailer::Base
# def welcome(recipient)
@@ -189,10 +188,8 @@ module ActionMailer #:nodoc:
#
# = Inline Attachments
#
- # You can also specify that a file should be displayed inline with other HTML. For example a
- # corporate logo or a photo or the like.
- #
- # To do this is simple, in the Mailer:
+ # You can also specify that a file should be displayed inline with other HTML. This is useful
+ # if you want to display a corporate logo or a photo.
#
# class ApplicationMailer < ActionMailer::Base
# def welcome(recipient)
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 4c80863e3a..5ea7636427 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -83,7 +83,10 @@ module ActiveModel
# person.name_changed? # => false
# person.name # => 'Bill'
#
- # Before modifying an attribute in-place:
+ # If an attribute is modified in-place then make use of <tt>[attribute_name]_will_change!</tt>
+ # to mark that the attribute is changing. Otherwise ActiveModel can't track changes to
+ # in-place attributes.
+ #
# person.name_will_change!
# person.name << 'y'
# person.name_change # => ['Bill', 'Billy']
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 1b9b725dd4..f540aa7f25 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -303,7 +303,7 @@ module ActiveRecord
# You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be
# aware of, mostly involving the saving of associated objects.
#
- # Unless you set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
+ # You can set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
# <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
# to +true+ will _always_ save the members, whereas setting it to +false+ will
# _never_ save the members.
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 5898ec3732..99043af1a5 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -220,6 +220,19 @@ module ActiveRecord #:nodoc:
# user = User.create(:preferences => %w( one two three ))
# User.find(user.id).preferences # raises SerializationTypeMismatch
#
+ # == Time Zone aware attributes
+ #
+ # By default, ActiveRecord::Base keeps all the datetime columns time zone aware by executing following code.
+ #
+ # ActiveRecord::Base.time_zone_aware_attributes = true
+ #
+ # This feature can easily be turned off by assigning value <tt>false</tt> .
+ #
+ # If your attributes are time zone aware and you desire to skip time zone conversion for certain attributes then you can do following:
+ #
+ # Topic.skip_time_zone_conversion_for_attributes = [:written_on]
+ #
+ #
# == Single table inheritance
#
# Active Record allows inheritance by storing the name of the class in a column that by default is named "type" (can be changed
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index b587abd5d0..38b91652ee 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -105,11 +105,16 @@ module ActiveRecord
# Updates a single attribute and saves the record.
# This is especially useful for boolean flags on existing records. Also note that
#
- # * validation is skipped
- # * No callbacks are invoked
- # * updated_at/updated_on column is updated if that column is available
- # * does not work on associations
- # * does not work on attr_accessor attributes. The attribute that is being updated must be column name.
+ # * The attribute being updated must be a column name.
+ # * Validation is skipped.
+ # * No callbacks are invoked.
+ # * updated_at/updated_on column is updated if that column is available.
+ # * Does not work on associations.
+ # * Does not work on attr_accessor attributes.
+ # * Does not work on new record. <tt>record.new_record?</tt> should return false for this method to work.
+ # * Updates only the attribute that is input to the method. If there are other changed attributes then
+ # those attributes are left alone. In that case even after this method has done its work <tt>record.changed?</tt>
+ # will return true.
#
def update_attribute(name, value)
raise ActiveRecordError, "#{name.to_s} is marked as readonly" if self.class.readonly_attributes.include? name.to_s
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 1445cec446..037cfffae2 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -129,13 +129,6 @@ module ActiveSupport
# cache.namespace = lambda { @last_mod_time } # Set the namespace to a variable
# @last_mod_time = Time.now # Invalidate the entire cache by changing namespace
#
- # All caches support auto expiring content after a specified number of seconds.
- # To set the cache entry time to live, you can either specify +:expires_in+ as
- # an option to the constructor to have it affect all entries or to the +fetch+
- # or +write+ methods for just one entry.
- #
- # cache = ActiveSupport::Cache::MemoryStore.new(:expire_in => 5.minutes)
- # cache.write(key, value, :expire_in => 1.minute) # Set a lower value for one entry
#
# Caches can also store values in a compressed format to save space and reduce
# time spent sending data. Since there is some overhead, values must be large
@@ -211,23 +204,30 @@ module ActiveSupport
# Setting <tt>:compress</tt> will store a large cache entry set by the call
# in a compressed format.
#
- # Setting <tt>:expires_in</tt> will set an expiration time on the cache
- # entry if it is set by call.
#
- # Setting <tt>:race_condition_ttl</tt> will invoke logic on entries set with
- # an <tt>:expires_in</tt> option. If an entry is found in the cache that is
- # expired and it has been expired for less than the number of seconds specified
- # by this option and a block was passed to the method call, then the expiration
- # future time of the entry in the cache will be updated to that many seconds
- # in the and the block will be evaluated and written to the cache.
+ # Setting <tt>:expires_in</tt> will set an expiration time on the cache. All caches
+ # support auto expiring content after a specified number of seconds. This value can
+ # be specified as an option to the construction in which call all entries will be
+ # affected. Or it can be supplied to the +fetch+ or +write+ method for just one entry.
+ #
+ # cache = ActiveSupport::Cache::MemoryStore.new(:expire_in => 5.minutes)
+ # cache.write(key, value, :expire_in => 1.minute) # Set a lower value for one entry
+ #
+ # Setting <tt>:race_condition_ttl</tt> is very useful in situations where a cache entry
+ # is used very frequently unver heavy load. If a cache expires and due to heavy load
+ # seven different processes will try to read data natively and then they all will try to
+ # write to cache. To avoid that case the first process to find an expired cache entry will
+ # bump the cache expiration time by the value set in <tt>:race_condition_ttl</tt>. Yes
+ # this process is extending the time for a stale value by another few seconds. Because
+ # of extended life of the previous cache, other processes will continue to use slightly
+ # stale data for a just a big longer. In the meantime that first process will go ahead
+ # and will write into cache the new value. After that all the processes will start
+ # getting new value. The key is to keep <tt>:race_condition_ttl</tt> small.
#
- # This is very useful in situations where a cache entry is used very frequently
- # under heavy load. The first process to find an expired cache entry will then
- # become responsible for regenerating that entry while other processes continue
- # to use the slightly out of date entry. This can prevent race conditions where
- # too many processes are trying to regenerate the entry all at once. If the
- # process regenerating the entry errors out, the entry will be regenerated
- # after the specified number of seconds.
+ # If the process regenerating the entry errors out, the entry will be regenerated
+ # after the specified number of seconds. Also note that the life of stale cache is
+ # extended only if it expired recently. Otherwise a new value is generated and
+ # <tt>:race_condition_ttl</tt> does not play any role.
#
# # Set all values to expire after one minute.
# cache = ActiveSupport::Cache::MemoryCache.new(:expires_in => 1.minute)
@@ -252,6 +252,7 @@ module ActiveSupport
#
# # val_1 => "new value 1"
# # val_2 => "original value"
+ # # sleep 10 # First thread extend the life of cache by another 10 seconds
# # cache.fetch("foo") => "new value 1"
#
# Other options will be handled by the specific cache store implementation.
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 576366e496..bfa57fe1f7 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -2,8 +2,8 @@ require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/module/remove_method'
class Class
- # Declare a class-level attribute whose value is inheritable and
- # overwritable by subclasses:
+ # Declare a class-level attribute whose value is inheritable by subclasses.
+ # Subclasses can change their own value and it will not impact parent class.
#
# class Base
# class_attribute :setting
@@ -18,12 +18,34 @@ class Class
# Subclass.setting # => false
# Base.setting # => true
#
+ # In the above case as long as Subclass does not assign a value to setting
+ # by performing <tt>Subclass.setting = _something_ </tt>, <tt>Subclass.setting</tt>
+ # would read value assigned to parent class. Once Subclass assigns a value then
+ # the value assigned by Subclass would be returned.
+ #
# This matches normal Ruby method inheritance: think of writing an attribute
- # on a subclass as overriding the reader method.
+ # on a subclass as overriding the reader method. However, you need to be aware
+ # when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
+ # In such cases, you don't want to do changes in places but use setters:
+ #
+ # Base.setting = []
+ # Base.setting #=> []
+ # Subclass.setting #=> []
+ #
+ # # Appending in child changes both parent and child because it is the same object:
+ # Subclass.setting << :foo
+ # Base.setting #=> [:foo]
+ # Subclass.setting #=> [:foo]
+ #
+ # # Use setters to not propagate changes:
+ # Base.setting = []
+ # Subclass.setting += [:foo]
+ # Base.setting #=> []
+ # Subclass.setting #=> [:foo]
#
# For convenience, a query method is defined as well:
#
- # Subclass.setting? # => false
+ # Subclass.setting? # => false
#
# Instances may overwrite the class value in the same way:
#
diff --git a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
index feef5d2d57..4e35b1b488 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
@@ -3,11 +3,27 @@ require 'active_support/core_ext/array/extract_options'
# Extends the class object with class and instance accessors for class attributes,
# just like the native attr* accessors for instance attributes.
#
+# Note that unlike +class_attribute+, if a subclass changes the value then that would
+# also change the value for parent class. Similarly if parent class changes the value
+# then that would change the value of subclasses too.
+#
# class Person
# cattr_accessor :hair_colors
# end
#
# Person.hair_colors = [:brown, :black, :blonde, :red]
+# Person.hair_colors #=> [:brown, :black, :blonde, :red]
+# Person.new.hair_colors #=> [:brown, :black, :blonde, :red]
+#
+# To opt out of the instance writer method, pass :instance_writer => false.
+# To opt out of the instance reader method, pass :instance_reader => false.
+#
+# class Person
+# cattr_accessor :hair_colors, :instance_writer => false, :instance_reader => false
+# end
+#
+# Person.new.hair_colors = [:brown] # => NoMethodError
+# Person.new.hair_colors # => NoMethodError
class Class
def cattr_reader(*syms)
options = syms.extract_options!
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index e6a213625c..c5b54318ce 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -40,23 +40,23 @@ class Date
end
end
- # Tells whether the Date object's date lies in the past
+ # Returns true if the Date object's date lies in the past. Otherwise returns false.
def past?
self < ::Date.current
end
- # Tells whether the Date object's date is today
+ # Returns true if the Date object's date is today.
def today?
self.to_date == ::Date.current # we need the to_date because of DateTime
end
- # Tells whether the Date object's date lies in the future
+ # Returns true if the Date object's date lies in the future.
def future?
self > ::Date.current
end
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
- # and then subtracts the specified number of seconds
+ # and then subtracts the specified number of seconds.
def ago(seconds)
to_time_in_current_zone.since(-seconds)
end
@@ -127,22 +127,22 @@ class Date
)
end
- # Returns a new Date/DateTime representing the time a number of specified months ago
+ # Returns a new Date/DateTime representing the time a number of specified months ago.
def months_ago(months)
advance(:months => -months)
end
- # Returns a new Date/DateTime representing the time a number of specified months in the future
+ # Returns a new Date/DateTime representing the time a number of specified months in the future.
def months_since(months)
advance(:months => months)
end
- # Returns a new Date/DateTime representing the time a number of specified years ago
+ # Returns a new Date/DateTime representing the time a number of specified years ago.
def years_ago(years)
advance(:years => -years)
end
- # Returns a new Date/DateTime representing the time a number of specified years in the future
+ # Returns a new Date/DateTime representing the time a number of specified years in the future.
def years_since(years)
advance(:years => years)
end
@@ -152,22 +152,22 @@ class Date
years_ago(1)
end unless method_defined?(:prev_year)
- # Short-hand for years_since(1)
+ # Shorthand for years_since(1)
def next_year
years_since(1)
end unless method_defined?(:next_year)
- # Short-hand for months_ago(1)
+ # Shorthand for months_ago(1)
def prev_month
months_ago(1)
end unless method_defined?(:prev_month)
- # Short-hand for months_since(1)
+ # Shorthand for months_since(1)
def next_month
months_since(1)
end unless method_defined?(:next_month)
- # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
+ # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00).
def beginning_of_week
days_to_monday = self.wday!=0 ? self.wday-1 : 6
result = self - days_to_monday
@@ -176,7 +176,7 @@ class Date
alias :monday :beginning_of_week
alias :at_beginning_of_week :beginning_of_week
- # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59)
+ # Returns a new Date/DateTime representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59).
def end_of_week
days_to_sunday = self.wday!=0 ? 7-self.wday : 0
result = self + days_to_sunday.days
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index d14a531abe..6ee7a4220b 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -1135,21 +1135,6 @@ Since values are copied when a subclass is defined, if the base class changes th
NOTE: Defined in +active_support/core_ext/class/inheritable_attributes.rb+.
-There's a related macro called +superclass_delegating_accessor+, however, that does not copy the value when the base class is subclassed. Instead, it delegates reading to the superclass as long as the attribute is not set via its own writer. For example, +ActionMailer::Base+ defines +delivery_method+ this way:
-
-<ruby>
-module ActionMailer
- class Base
- superclass_delegating_accessor :delivery_method
- self.delivery_method = :smtp
- end
-end
-</ruby>
-
-If for whatever reason an application loads the definition of a mailer class and after that sets +ActionMailer::Base.delivery_method+, the mailer class will still see the new value. In addition, the mailer class is able to change the +delivery_method+ without affecting the value in the parent using its own inherited class attribute writer.
-
-NOTE: Defined in +active_support/core_ext/class/delegating_attributes.rb+.
-
h4. Subclasses & Descendants
h5. +subclasses+