1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge docrails:

commit e6afd8b273
Author: Xavier Noria <fxn@hashref.com>
Date:   Thu May 8 23:49:36 2008 +0200

    Overall documentation improvement and markup corrections. Zillion changes.

commit 2fead68b31
Author: Austin Putman <austin@emmanuel.local>
Date:   Wed May 7 19:35:46 2008 -0700

    Documented class methods on ActionController::Routing.  These are dangerous, and mostly used for testing.

commit f5b84182db
Author: Teflon Ted <github@rudiment.net>
Date:   Wed May 7 16:08:49 2008 -0400

    Added explanation about errant inflections not being patched in the future in order to avoid breaking legacy applications.

commit 370f4f5172
Author: Sunny Ripert <negatif@gmail.com>
Date:   Wed May 7 14:00:59 2008 +0200

    Applied list conventions in AR::Base

commit 5bd18429f0
Author: Sunny Ripert <negatif@gmail.com>
Date:   Wed May 7 13:53:35 2008 +0200

    Renamed Options list to Attributes list whenever they weren't option hashes in AR::Base

commit d912bd5672
Author: Yaroslav Markin <yaroslav@markin.net>
Date:   Wed May 7 13:50:28 2008 +0400

    Add a filter_parameter_logging usage hint to generated ApplicationController.
    This may help to remind the developer to filter sensitive information from application logs.
    Closes #11578

commit b243de0db3
Author: Jack Danger Canty <git@6brand.com>
Date:   Tue May 6 23:39:47 2008 -0700

    doc: disambiguating an example ActiveRecord class

commit f81d771f06
Author: Jack Danger Canty <git@6brand.com>
Date:   Tue May 6 23:35:05 2008 -0700

    doc: ActiveRecord::Reflection::AssociationReflection#through_reflection

    Added documentation demonstrating the use of #through_reflection for
    finding intervening reflection objects for HasManyThrough
    and HasOneThrough.

commit ae6b46f00b
Author: Cheah Chu Yeow <chuyeow@gmail.com>
Date:   Wed May 7 13:47:41 2008 +0800

    Document AttributeAssignmentError and MultiparameterAssignmentErrors.

commit 8f463550b5
Author: John Barnette <jbarnette@gmail.com>
Date:   Tue May 6 22:46:44 2008 -0700

    Killing/fixing a bunch of outdated language in the AR README.

commit aca44bcd92
Author: Cheah Chu Yeow <chuyeow@gmail.com>
Date:   Wed May 7 13:34:52 2008 +0800

    Make a note about ActiveResource::Timeouterror being raised when ARes calls timeout.

commit 284a930a93
Author: Jonathan Dance <jd@wuputah.com>
Date:   Tue May 6 14:58:26 2008 -0400

    improvements to the page caching docs

commit 9482da6213
Author: Sunny Ripert <negatif@gmail.com>
Date:   Mon May 5 18:13:40 2008 +0200

    validates_numericality_of() "integer" option really is "only_integer"

commit e9afd6790a
Author: Sunny Ripert <negatif@gmail.com>
Date:   Mon May 5 12:11:59 2008 +0200

    Harmonized hash notation in AR::Base

commit 67ebf14a91
Author: Sunny Ripert <negatif@gmail.com>
Date:   Mon May 5 12:06:19 2008 +0200

    Turned options into rdoc-lists in AR::Base

commit 0ec7c0a41d
Author: Marshall Huss <mwhuss@Macbook.local>
Date:   Sun May 4 23:21:33 2008 -0400

    Added information of how to set element_name in the case the user has a name confliction with an existing model

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
This commit is contained in:
Pratik Naik 2008-05-09 10:38:02 +01:00
parent bfbf03ecee
commit dc4eec1129
34 changed files with 658 additions and 570 deletions

View file

@ -95,7 +95,7 @@ module ActionMailer #:nodoc:
# #
# ActionMailer::Base.default_url_options[:host] = "example.com" # ActionMailer::Base.default_url_options[:host] = "example.com"
# #
# This can also be set as a configuration option in <tt>environment.rb</tt>: # This can also be set as a configuration option in <tt>config/environment.rb</tt>:
# #
# config.action_mailer.default_url_options = { :host => "example.com" } # config.action_mailer.default_url_options = { :host => "example.com" }
# #
@ -204,22 +204,23 @@ module ActionMailer #:nodoc:
# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
# #
# * <tt>smtp_settings</tt> - Allows detailed configuration for <tt>:smtp</tt> delivery method: # * <tt>smtp_settings</tt> - Allows detailed configuration for <tt>:smtp</tt> delivery method:
# * <tt>:address</tt> Allows you to use a remote mail server. Just change it from its default "localhost" setting. # * <tt>:address</tt> - Allows you to use a remote mail server. Just change it from its default "localhost" setting.
# * <tt>:port</tt> On the off chance that your mail server doesn't run on port 25, you can change it. # * <tt>:port</tt> - On the off chance that your mail server doesn't run on port 25, you can change it.
# * <tt>:domain</tt> If you need to specify a HELO domain, you can do it here. # * <tt>:domain</tt> - If you need to specify a HELO domain, you can do it here.
# * <tt>:user_name</tt> If your mail server requires authentication, set the username in this setting. # * <tt>:user_name</tt> - If your mail server requires authentication, set the username in this setting.
# * <tt>:password</tt> If your mail server requires authentication, set the password in this setting. # * <tt>:password</tt> - If your mail server requires authentication, set the password in this setting.
# * <tt>:authentication</tt> If your mail server requires authentication, you need to specify the authentication type here. # * <tt>:authentication</tt> - If your mail server requires authentication, you need to specify the authentication type here.
# This is a symbol and one of <tt>:plain</tt>, <tt>:login</tt>, <tt>:cram_md5</tt> # This is a symbol and one of <tt>:plain</tt>, <tt>:login</tt>, <tt>:cram_md5</tt>
# #
# * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method # * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method
# * <tt>:location</tt> The location of the sendmail executable, defaults to "/usr/sbin/sendmail" # * <tt>:location</tt> - The location of the sendmail executable, defaults to "/usr/sbin/sendmail"
# * <tt>:arguments</tt> The command line arguments # * <tt>:arguments</tt> - The command line arguments
# * <tt>raise_delivery_errors</tt> - whether or not errors should be raised if the email fails to be delivered. #
# * <tt>raise_delivery_errors</tt> - Whether or not errors should be raised if the email fails to be delivered.
# #
# * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default), <tt>:sendmail</tt>, and <tt>:test</tt>. # * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default), <tt>:sendmail</tt>, and <tt>:test</tt>.
# #
# * <tt>perform_deliveries</tt> - Determines whether deliver_* methods are actually carried out. By default they are, # * <tt>perform_deliveries</tt> - Determines whether <tt>deliver_*</tt> methods are actually carried out. By default they are,
# but this can be turned off to help functional testing. # but this can be turned off to help functional testing.
# #
# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with <tt>delivery_method :test</tt>. Most useful # * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with <tt>delivery_method :test</tt>. Most useful
@ -406,7 +407,7 @@ module ActionMailer #:nodoc:
# templating language other than rhtml or rxml are supported. # templating language other than rhtml or rxml are supported.
# To use this, include in your template-language plugin's init # To use this, include in your template-language plugin's init
# code or on a per-application basis, this can be invoked from # code or on a per-application basis, this can be invoked from
# config/environment.rb: # <tt>config/environment.rb</tt>:
# #
# ActionMailer::Base.register_template_extension('haml') # ActionMailer::Base.register_template_extension('haml')
def register_template_extension(extension) def register_template_extension(extension)

View file

@ -21,11 +21,11 @@ module ActionController
# from the response HTML or elements selected by the enclosing assertion. # from the response HTML or elements selected by the enclosing assertion.
# #
# In addition to HTML responses, you can make the following assertions: # In addition to HTML responses, you can make the following assertions:
# * #assert_select_rjs -- Assertions on HTML content of RJS update and # * +assert_select_rjs+ - Assertions on HTML content of RJS update and
# insertion operations. # insertion operations.
# * #assert_select_encoded -- Assertions on HTML encoded inside XML, # * +assert_select_encoded+ - Assertions on HTML encoded inside XML,
# for example for dealing with feed item descriptions. # for example for dealing with feed item descriptions.
# * #assert_select_email -- Assertions on the HTML body of an e-mail. # * +assert_select_email+ - Assertions on the HTML body of an e-mail.
# #
# Also see HTML::Selector to learn how to use selectors. # Also see HTML::Selector to learn how to use selectors.
module SelectorAssertions module SelectorAssertions
@ -136,27 +136,27 @@ module ActionController
# === Equality Tests # === Equality Tests
# #
# The equality test may be one of the following: # The equality test may be one of the following:
# * <tt>true</tt> -- Assertion is true if at least one element selected. # * <tt>true</tt> - Assertion is true if at least one element selected.
# * <tt>false</tt> -- Assertion is true if no element selected. # * <tt>false</tt> - Assertion is true if no element selected.
# * <tt>String/Regexp</tt> -- Assertion is true if the text value of at least # * <tt>String/Regexp</tt> - Assertion is true if the text value of at least
# one element matches the string or regular expression. # one element matches the string or regular expression.
# * <tt>Integer</tt> -- Assertion is true if exactly that number of # * <tt>Integer</tt> - Assertion is true if exactly that number of
# elements are selected. # elements are selected.
# * <tt>Range</tt> -- Assertion is true if the number of selected # * <tt>Range</tt> - Assertion is true if the number of selected
# elements fit the range. # elements fit the range.
# If no equality test specified, the assertion is true if at least one # If no equality test specified, the assertion is true if at least one
# element selected. # element selected.
# #
# To perform more than one equality tests, use a hash with the following keys: # To perform more than one equality tests, use a hash with the following keys:
# * <tt>:text</tt> -- Narrow the selection to elements that have this text # * <tt>:text</tt> - Narrow the selection to elements that have this text
# value (string or regexp). # value (string or regexp).
# * <tt>:html</tt> -- Narrow the selection to elements that have this HTML # * <tt>:html</tt> - Narrow the selection to elements that have this HTML
# content (string or regexp). # content (string or regexp).
# * <tt>:count</tt> -- Assertion is true if the number of selected elements # * <tt>:count</tt> - Assertion is true if the number of selected elements
# is equal to this value. # is equal to this value.
# * <tt>:minimum</tt> -- Assertion is true if the number of selected # * <tt>:minimum</tt> - Assertion is true if the number of selected
# elements is at least this value. # elements is at least this value.
# * <tt>:maximum</tt> -- Assertion is true if the number of selected # * <tt>:maximum</tt> - Assertion is true if the number of selected
# elements is at most this value. # elements is at most this value.
# #
# If the method is called with a block, once all equality tests are # If the method is called with a block, once all equality tests are

View file

@ -159,28 +159,34 @@ module ActionController #:nodoc:
# #
# Hello #{session[:person]} # Hello #{session[:person]}
# #
# For removing objects from the session, you can either assign a single key to nil, like <tt>session[:person] = nil</tt>, or you can # For removing objects from the session, you can either assign a single key to +nil+:
# remove the entire session with reset_session.
# #
# Sessions are stored in a browser cookie that's cryptographically signed, but unencrypted, by default. This prevents # # removes :person from session
# the user from tampering with the session but also allows him to see its contents. # session[:person] = nil
# #
# Do not put secret information in session! # or you can remove the entire session with +reset_session+.
#
# Sessions are stored by default in a browser cookie that's cryptographically signed, but unencrypted.
# This prevents the user from tampering with the session but also allows him to see its contents.
#
# Do not put secret information in cookie-based sessions!
# #
# Other options for session storage are: # Other options for session storage are:
# #
# ActiveRecordStore: sessions are stored in your database, which works better than PStore with multiple app servers and, # * ActiveRecordStore - Sessions are stored in your database, which works better than PStore with multiple app servers and,
# unlike CookieStore, hides your session contents from the user. To use ActiveRecordStore, set # unlike CookieStore, hides your session contents from the user. To use ActiveRecordStore, set
# #
# config.action_controller.session_store = :active_record_store # config.action_controller.session_store = :active_record_store
# #
# in your <tt>environment.rb</tt> and run <tt>rake db:sessions:create</tt>. # in your <tt>config/environment.rb</tt> and run <tt>rake db:sessions:create</tt>.
# #
# MemCacheStore: sessions are stored as entries in your memcached cache. Set the session store type in <tt>environment.rb</tt>: # * MemCacheStore - Sessions are stored as entries in your memcached cache.
# Set the session store type in <tt>config/environment.rb</tt>:
# #
# config.action_controller.session_store = :mem_cache_store # config.action_controller.session_store = :mem_cache_store
# #
# This assumes that memcached has been installed and configured properly. See the MemCacheStore docs for more information. # This assumes that memcached has been installed and configured properly.
# See the MemCacheStore docs for more information.
# #
# == Responses # == Responses
# #
@ -535,20 +541,20 @@ module ActionController #:nodoc:
# #
# <tt>url_for</tt> is used to: # <tt>url_for</tt> is used to:
# #
# All keys given to url_for are forwarded to the Route module, save for the following: # All keys given to +url_for+ are forwarded to the Route module, save for the following:
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example, # * <tt>:anchor</tt> - Specifies the anchor name to be appended to the path. For example,
# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt> # <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt>
# will produce "/posts/show/10#comments". # will produce "/posts/show/10#comments".
# * <tt>:only_path</tt> -- if true, returns the relative URL (omitting the protocol, host name, and port) (<tt>false</tt> by default) # * <tt>:only_path</tt> - If true, returns the relative URL (omitting the protocol, host name, and port) (<tt>false</tt> by default).
# * <tt>:trailing_slash</tt> -- if true, adds a trailing slash, as in "/archive/2005/". Note that this # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2005/". Note that this
# is currently not recommended since it breaks caching. # is currently not recommended since it breaks caching.
# * <tt>:host</tt> -- overrides the default (current) host if provided. # * <tt>:host</tt> - Overrides the default (current) host if provided.
# * <tt>:protocol</tt> -- overrides the default (current) protocol if provided. # * <tt>:protocol</tt> - Overrides the default (current) protocol if provided.
# * <tt>:port</tt> -- optionally specify the port to connect to. # * <tt>:port</tt> - Optionally specify the port to connect to.
# * <tt>:user</tt> -- Inline HTTP authentication (only plucked out if <tt>:password</tt> is also present). # * <tt>:user</tt> - Inline HTTP authentication (only plucked out if <tt>:password</tt> is also present).
# * <tt>:password</tt> -- Inline HTTP authentication (only plucked out if <tt>:user</tt> is also present). # * <tt>:password</tt> - Inline HTTP authentication (only plucked out if <tt>:user</tt> is also present).
# * <tt>:skip_relative_url_root</tt> -- if true, the url is not constructed using the relative_url_root of the request so the path # * <tt>:skip_relative_url_root</tt> - If true, the url is not constructed using the +relative_url_root+
# will include the web server relative installation directory. # of the request so the path will include the web server relative installation directory.
# #
# The URL is generated from the remaining keys in the hash. A URL contains two key parts: the <base> and a query string. # The URL is generated from the remaining keys in the hash. A URL contains two key parts: the <base> and a query string.
# Routes composes a query string as the key/value pairs not included in the <base>. # Routes composes a query string as the key/value pairs not included in the <base>.

View file

@ -20,7 +20,8 @@ module ActionController #:nodoc:
# #
# == Caching stores # == Caching stores
# #
# All the caching stores from ActiveSupport::Cache is available to be used as backends for Action Controller caching. # All the caching stores from ActiveSupport::Cache is available to be used as backends for Action Controller caching. This setting only
# affects action and fragment caching as page caching is always written to disk.
# #
# Configuration examples (MemoryStore is the default): # Configuration examples (MemoryStore is the default):
# #

View file

@ -4,23 +4,24 @@ require 'uri'
module ActionController #:nodoc: module ActionController #:nodoc:
module Caching module Caching
# Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server # Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server
# can serve without going through the Action Pack. This can be as much as 100 times faster than going through the process of dynamically # can serve without going through Action Pack. This is the fastest way to cache your content as opposed to going dynamically
# generating the content. Unfortunately, this incredible speed-up is only available to stateless pages where all visitors # through the process of generating the content. Unfortunately, this incredible speed-up is only available to stateless pages
# are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are a great fit # where all visitors are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are
# for this approach, but account-based systems where people log in and manipulate their own data are often less likely candidates. # a great fit for this approach, but account-based systems where people log in and manipulate their own data are often less
# likely candidates.
# #
# Specifying which actions to cache is done through the <tt>caches</tt> class method: # Specifying which actions to cache is done through the <tt>caches_page</tt> class method:
# #
# class WeblogController < ActionController::Base # class WeblogController < ActionController::Base
# caches_page :show, :new # caches_page :show, :new
# end # end
# #
# This will generate cache files such as weblog/show/5 and weblog/new, which match the URLs used to trigger the dynamic # This will generate cache files such as <tt>weblog/show/5.html</tt> and <tt>weblog/new.html</tt>,
# generation. This is how the web server is able pick up a cache file when it exists and otherwise let the request pass on to # which match the URLs used to trigger the dynamic generation. This is how the web server is able
# the Action Pack to generate it. # pick up a cache file when it exists and otherwise let the request pass on to Action Pack to generate it.
# #
# Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache # Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache
# is not restored before another hit is made against it. The API for doing so mimics the options from url_for and friends: # is not restored before another hit is made against it. The API for doing so mimics the options from +url_for+ and friends:
# #
# class WeblogController < ActionController::Base # class WeblogController < ActionController::Base
# def update # def update
@ -35,13 +36,17 @@ module ActionController #:nodoc:
# #
# == Setting the cache directory # == Setting the cache directory
# #
# The cache directory should be the document root for the web server and is set using Base.page_cache_directory = "/document/root". # The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
# For Rails, this directory has already been set to Rails.public_path (which is usually set to RAILS_ROOT + "/public"). # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
# this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
# web server to look in the new location for cached files.
# #
# == Setting the cache extension # == Setting the cache extension
# #
# By default, the cache extension is .html, which makes it easy for the cached files to be picked up by the web server. If you want # Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
# something else, like .php or .shtml, just set Base.page_cache_extension. # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
# If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
# extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
module Pages module Pages
def self.included(base) #:nodoc: def self.included(base) #:nodoc:
base.extend(ClassMethods) base.extend(ClassMethods)

View file

@ -47,25 +47,27 @@ module ActionController
# Constructs a call to a named RESTful route for the given record and returns the # Constructs a call to a named RESTful route for the given record and returns the
# resulting URL string. For example: # resulting URL string. For example:
# #
# polymorphic_url(post) # # calls post_url(post)
# # calls post_url(post) #=> "http://example.com/posts/1" # polymorphic_url(post) # => "http://example.com/posts/1"
# #
# ==== Options # ==== Options
# * <tt>:action</tt> -- specifies the action prefix for the named route: #
# <tt>:new</tt>, <tt>:edit</tt> or <tt>:formatted</tt>. Default is no prefix. # * <tt>:action</tt> - Specifies the action prefix for the named route:
# * <tt>:routing_type</tt> -- <tt>:path</tt> or <tt>:url</tt> (default <tt>:url</tt>). # <tt>:new</tt>, <tt>:edit</tt>, or <tt>:formatted</tt>. Default is no prefix.
# * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
# Default is <tt>:url</tt>.
# #
# ==== Examples # ==== Examples
# #
# # an Article record # # an Article record
# polymorphic_url(record) #-> article_url(record) # polymorphic_url(record) # same as article_url(record)
# #
# # a Comment record # # a Comment record
# polymorphic_url(record) #-> comment_url(record) # polymorphic_url(record) # same as comment_url(record)
# #
# # it recognizes new records and maps to the collection # # it recognizes new records and maps to the collection
# record = Comment.new # record = Comment.new
# polymorphic_url(record) #-> comments_url() # polymorphic_url(record) # same as comments_url()
# #
def polymorphic_url(record_or_hash_or_array, options = {}) def polymorphic_url(record_or_hash_or_array, options = {})
if record_or_hash_or_array.kind_of?(Array) if record_or_hash_or_array.kind_of?(Array)

View file

@ -69,10 +69,10 @@ module ActionController #:nodoc:
# #
# Valid Options: # Valid Options:
# #
# * <tt>:only/:except</tt> - passed to the <tt>before_filter</tt> call. Set which actions are verified. # * <tt>:only/:except</tt> - Passed to the <tt>before_filter</tt> call. Set which actions are verified.
# * <tt>:secret</tt> - Custom salt used to generate the <tt>form_authenticity_token</tt>. # * <tt>:secret</tt> - Custom salt used to generate the <tt>form_authenticity_token</tt>.
# Leave this off if you are using the cookie session store. # Leave this off if you are using the cookie session store.
# * <tt>:digest</tt> - Message digest used for hashing. Defaults to 'SHA1' # * <tt>:digest</tt> - Message digest used for hashing. Defaults to 'SHA1'.
def protect_from_forgery(options = {}) def protect_from_forgery(options = {})
self.request_forgery_protection_token ||= :authenticity_token self.request_forgery_protection_token ||= :authenticity_token
before_filter :verify_authenticity_token, :only => options.delete(:only), :except => options.delete(:except) before_filter :verify_authenticity_token, :only => options.delete(:only), :except => options.delete(:except)

View file

@ -236,27 +236,27 @@ module ActionController
# which takes into account whether <tt>@message</tt> is a new record or not and generates the # which takes into account whether <tt>@message</tt> is a new record or not and generates the
# path and method accordingly. # path and method accordingly.
# #
# The #resources method accepts the following options to customize the resulting routes: # The +resources+ method accepts the following options to customize the resulting routes:
# * <tt>:collection</tt> - add named routes for other actions that operate on the collection. # * <tt>:collection</tt> - Add named routes for other actions that operate on the collection.
# Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt> # Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt>
# or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages/rss, with a route of rss_messages_url. # or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages/rss, with a route of +rss_messages_url+.
# * <tt>:member</tt> - same as <tt>:collection</tt>, but for actions that operate on a specific member. # * <tt>:member</tt> - Same as <tt>:collection</tt>, but for actions that operate on a specific member.
# * <tt>:new</tt> - same as <tt>:collection</tt>, but for actions that operate on the new resource action. # * <tt>:new</tt> - Same as <tt>:collection</tt>, but for actions that operate on the new resource action.
# * <tt>:controller</tt> - specify the controller name for the routes. # * <tt>:controller</tt> - Specify the controller name for the routes.
# * <tt>:singular</tt> - specify the singular name used in the member routes. # * <tt>:singular</tt> - Specify the singular name used in the member routes.
# * <tt>:requirements</tt> - set custom routing parameter requirements. # * <tt>:requirements</tt> - Set custom routing parameter requirements.
# * <tt>:conditions</tt> - specify custom routing recognition conditions. Resources sets the <tt>:method</tt> value for the method-specific routes. # * <tt>:conditions</tt> - Specify custom routing recognition conditions. Resources sets the <tt>:method</tt> value for the method-specific routes.
# * <tt>:as</tt> - specify a different resource name to use in the URL path. For example: # * <tt>:as</tt> - Specify a different resource name to use in the URL path. For example:
# # products_path == '/productos' # # products_path == '/productos'
# map.resources :products, :as => 'productos' do |product| # map.resources :products, :as => 'productos' do |product|
# # product_reviews_path(product) == '/productos/1234/comentarios' # # product_reviews_path(product) == '/productos/1234/comentarios'
# product.resources :product_reviews, :as => 'comentarios' # product.resources :product_reviews, :as => 'comentarios'
# end # end
# #
# * <tt>:has_one</tt> - specify nested resources, this is a shorthand for mapping singleton resources beneath the current. # * <tt>:has_one</tt> - Specify nested resources, this is a shorthand for mapping singleton resources beneath the current.
# * <tt>:has_many</tt> - same has <tt>:has_one</tt>, but for plural resources. # * <tt>:has_many</tt> - Same has <tt>:has_one</tt>, but for plural resources.
# #
# You may directly specify the routing association with has_one and has_many like: # You may directly specify the routing association with +has_one+ and +has_many+ like:
# #
# map.resources :notes, :has_one => :author, :has_many => [:comments, :attachments] # map.resources :notes, :has_one => :author, :has_many => [:comments, :attachments]
# #
@ -268,14 +268,14 @@ module ActionController
# notes.resources :attachments # notes.resources :attachments
# end # end
# #
# * <tt>:path_names</tt> - specify different names for the 'new' and 'edit' actions. For example: # * <tt>:path_names</tt> - Specify different names for the 'new' and 'edit' actions. For example:
# # new_products_path == '/productos/nuevo' # # new_products_path == '/productos/nuevo'
# map.resources :products, :as => 'productos', :path_names => { :new => 'nuevo', :edit => 'editar' } # map.resources :products, :as => 'productos', :path_names => { :new => 'nuevo', :edit => 'editar' }
# #
# You can also set default action names from an environment, like this: # You can also set default action names from an environment, like this:
# config.action_controller.resources_path_names = { :new => 'nuevo', :edit => 'editar' } # config.action_controller.resources_path_names = { :new => 'nuevo', :edit => 'editar' }
# #
# * <tt>:path_prefix</tt> - set a prefix to the routes with required route variables. # * <tt>:path_prefix</tt> - Set a prefix to the routes with required route variables.
# #
# Weblog comments usually belong to a post, so you might use resources like: # Weblog comments usually belong to a post, so you might use resources like:
# #
@ -296,7 +296,7 @@ module ActionController
# article_comments_url(:article_id => @article) # article_comments_url(:article_id => @article)
# article_comment_url(:article_id => @article, :id => @comment) # article_comment_url(:article_id => @article, :id => @comment)
# #
# * <tt>:name_prefix</tt> - define a prefix for all generated routes, usually ending in an underscore. # * <tt>:name_prefix</tt> - Define a prefix for all generated routes, usually ending in an underscore.
# Use this if you have named routes that may clash. # Use this if you have named routes that may clash.
# #
# map.resources :tags, :path_prefix => '/books/:book_id', :name_prefix => 'book_' # map.resources :tags, :path_prefix => '/books/:book_id', :name_prefix => 'book_'
@ -343,7 +343,7 @@ module ActionController
# # --> GET /categories/7/messages/1 # # --> GET /categories/7/messages/1
# # has named route "category_message" # # has named route "category_message"
# #
# The #resources method sets HTTP method restrictions on the routes it generates. For example, making an # The +resources+ method sets HTTP method restrictions on the routes it generates. For example, making an
# HTTP POST on <tt>new_message_url</tt> will raise a RoutingError exception. The default route in # HTTP POST on <tt>new_message_url</tt> will raise a RoutingError exception. The default route in
# <tt>config/routes.rb</tt> overrides this and allows invalid HTTP methods for resource routes. # <tt>config/routes.rb</tt> overrides this and allows invalid HTTP methods for resource routes.
def resources(*entities, &block) def resources(*entities, &block)

View file

@ -15,7 +15,7 @@ module ActionController
# The routing module provides URL rewriting in native Ruby. It's a way to # The routing module provides URL rewriting in native Ruby. It's a way to
# redirect incoming requests to controllers and actions. This replaces # redirect incoming requests to controllers and actions. This replaces
# mod_rewrite rules. Best of all, Rails' Routing works with any web server. # mod_rewrite rules. Best of all, Rails' Routing works with any web server.
# Routes are defined in routes.rb in your RAILS_ROOT/config directory. # Routes are defined in <tt>config/routes.rb</tt>.
# #
# Consider the following route, installed by Rails when you generate your # Consider the following route, installed by Rails when you generate your
# application: # application:
@ -53,7 +53,7 @@ module ActionController
# == Route priority # == Route priority
# #
# Not all routes are created equally. Routes have priority defined by the # Not all routes are created equally. Routes have priority defined by the
# order of appearance of the routes in the routes.rb file. The priority goes # order of appearance of the routes in the <tt>config/routes.rb</tt> file. The priority goes
# from top to bottom. The last route in that file is at the lowest priority # from top to bottom. The last route in that file is at the lowest priority
# and will be applied last. If no route matches, 404 is returned. # and will be applied last. If no route matches, 404 is returned.
# #
@ -118,7 +118,7 @@ module ActionController
# root_url # => 'http://www.example.com/' # root_url # => 'http://www.example.com/'
# root_path # => '' # root_path # => ''
# #
# You can also specify an already-defined named route in your map.root call: # You can also specify an already-defined named route in your <tt>map.root</tt> call:
# #
# # In routes.rb # # In routes.rb
# map.new_session :controller => 'sessions', :action => 'new' # map.new_session :controller => 'sessions', :action => 'new'
@ -217,7 +217,7 @@ module ActionController
# ActionController::Routing::Routes.reload # ActionController::Routing::Routes.reload
# #
# This will clear all named routes and reload routes.rb if the file has been modified from # This will clear all named routes and reload routes.rb if the file has been modified from
# last load. To absolutely force reloading, use +reload!+. # last load. To absolutely force reloading, use <tt>reload!</tt>.
# #
# == Testing Routes # == Testing Routes
# #
@ -277,6 +277,9 @@ module ActionController
end end
class << self class << self
# Expects an array of controller names as the first argument.
# Executes the passed block with only the named controllers named available.
# This method is used in internal Rails testing.
def with_controllers(names) def with_controllers(names)
prior_controllers = @possible_controllers prior_controllers = @possible_controllers
use_controllers! names use_controllers! names
@ -285,6 +288,10 @@ module ActionController
use_controllers! prior_controllers use_controllers! prior_controllers
end end
# Returns an array of paths, cleaned of double-slashes and relative path references.
# * "\\\" and "//" become "\\" or "/".
# * "/foo/bar/../config" becomes "/foo/config".
# The returned array is sorted by length, descending.
def normalize_paths(paths) def normalize_paths(paths)
# do the hokey-pokey of path normalization... # do the hokey-pokey of path normalization...
paths = paths.collect do |path| paths = paths.collect do |path|
@ -303,6 +310,7 @@ module ActionController
paths = paths.uniq.sort_by { |path| - path.length } paths = paths.uniq.sort_by { |path| - path.length }
end end
# Returns the array of controller names currently available to ActionController::Routing.
def possible_controllers def possible_controllers
unless @possible_controllers unless @possible_controllers
@possible_controllers = [] @possible_controllers = []
@ -327,10 +335,28 @@ module ActionController
@possible_controllers @possible_controllers
end end
# Replaces the internal list of controllers available to ActionController::Routing with the passed argument.
# ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ])
def use_controllers!(controller_names) def use_controllers!(controller_names)
@possible_controllers = controller_names @possible_controllers = controller_names
end end
# Returns a controller path for a new +controller+ based on a +previous+ controller path.
# Handles 4 scenarios:
#
# * stay in the previous controller:
# controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
#
# * stay in the previous namespace:
# controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
#
# * forced move to the root namespace:
# controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
#
# * previous namespace is root:
# controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
#
def controller_relative_to(controller, previous) def controller_relative_to(controller, previous)
if controller.nil? then previous if controller.nil? then previous
elsif controller[0] == ?/ then controller[1..-1] elsif controller[0] == ?/ then controller[1..-1]
@ -344,6 +370,7 @@ module ActionController
Routes = RouteSet.new Routes = RouteSet.new
::Inflector.module_eval do ::Inflector.module_eval do
# Ensures that routes are reloaded when Rails inflections are updated.
def inflections_with_route_reloading(&block) def inflections_with_route_reloading(&block)
returning(inflections_without_route_reloading(&block)) { returning(inflections_without_route_reloading(&block)) {
ActionController::Routing::Routes.reload! if block_given? ActionController::Routing::Routes.reload! if block_given?

View file

@ -13,7 +13,7 @@ class CGI
# A session store backed by an Active Record class. A default class is # A session store backed by an Active Record class. A default class is
# provided, but any object duck-typing to an Active Record +Session+ class # provided, but any object duck-typing to an Active Record Session class
# with text +session_id+ and +data+ attributes is sufficient. # with text +session_id+ and +data+ attributes is sufficient.
# #
# The default assumes a +sessions+ tables with columns: # The default assumes a +sessions+ tables with columns:
@ -26,13 +26,13 @@ class CGI
# ActionController::SessionOverflowError will be raised. # ActionController::SessionOverflowError will be raised.
# #
# You may configure the table name, primary key, and data column. # You may configure the table name, primary key, and data column.
# For example, at the end of config/environment.rb: # For example, at the end of <tt>config/environment.rb</tt>:
# CGI::Session::ActiveRecordStore::Session.table_name = 'legacy_session_table' # CGI::Session::ActiveRecordStore::Session.table_name = 'legacy_session_table'
# CGI::Session::ActiveRecordStore::Session.primary_key = 'session_id' # CGI::Session::ActiveRecordStore::Session.primary_key = 'session_id'
# CGI::Session::ActiveRecordStore::Session.data_column_name = 'legacy_session_data' # CGI::Session::ActiveRecordStore::Session.data_column_name = 'legacy_session_data'
# Note that setting the primary key to the session_id frees you from # Note that setting the primary key to the +session_id+ frees you from
# having a separate id column if you don't want it. However, you must # having a separate +id+ column if you don't want it. However, you must
# set session.model.id = session.session_id by hand! A before_filter # set <tt>session.model.id = session.session_id</tt> by hand! A before filter
# on ApplicationController is a good place. # on ApplicationController is a good place.
# #
# Since the default class is a simple Active Record, you get timestamps # Since the default class is a simple Active Record, you get timestamps
@ -42,7 +42,7 @@ class CGI
# You may provide your own session class implementation, whether a # You may provide your own session class implementation, whether a
# feature-packed Active Record or a bare-metal high-performance SQL # feature-packed Active Record or a bare-metal high-performance SQL
# store, by setting # store, by setting
# +CGI::Session::ActiveRecordStore.session_class = MySessionClass+ # CGI::Session::ActiveRecordStore.session_class = MySessionClass
# You must implement these methods: # You must implement these methods:
# self.find_by_session_id(session_id) # self.find_by_session_id(session_id)
# initialize(hash_of_session_id_and_data) # initialize(hash_of_session_id_and_data)
@ -154,8 +154,13 @@ class CGI
# The database connection, table name, and session id and data columns # The database connection, table name, and session id and data columns
# are configurable class attributes. Marshaling and unmarshaling # are configurable class attributes. Marshaling and unmarshaling
# are implemented as class methods that you may override. By default, # are implemented as class methods that you may override. By default,
# marshaling data is +ActiveSupport::Base64.encode64(Marshal.dump(data))+ and # marshaling data is
# unmarshaling data is +Marshal.load(ActiveSupport::Base64.decode64(data))+. #
# ActiveSupport::Base64.encode64(Marshal.dump(data))
#
# and unmarshaling data is
#
# Marshal.load(ActiveSupport::Base64.decode64(data))
# #
# This marshaling behavior is intended to store the widest range of # This marshaling behavior is intended to store the widest range of
# binary session data in a +text+ column. For higher performance, # binary session data in a +text+ column. For higher performance,

View file

@ -29,16 +29,16 @@ module ActionController
# Generate a url based on the options provided, default_url_options and the # Generate a url based on the options provided, default_url_options and the
# routes defined in routes.rb. The following options are supported: # routes defined in routes.rb. The following options are supported:
# #
# * <tt>:only_path</tt> If true, the relative url is returned. Defaults to +false+. # * <tt>:only_path</tt> - If true, the relative url is returned. Defaults to +false+.
# * <tt>:protocol</tt> The protocol to connect to. Defaults to 'http'. # * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
# * <tt>:host</tt> Specifies the host the link should be targetted at. # * <tt>:host</tt> - Specifies the host the link should be targetted at.
# If <tt>:only_path</tt> is false, this option must be # If <tt>:only_path</tt> is false, this option must be
# provided either explicitly, or via +default_url_options+. # provided either explicitly, or via +default_url_options+.
# * <tt>:port</tt> Optionally specify the port to connect to. # * <tt>:port</tt> - Optionally specify the port to connect to.
# * <tt>:anchor</tt> An anchor name to be appended to the path. # * <tt>:anchor</tt> - An anchor name to be appended to the path.
# * <tt>:skip_relative_url_root</tt> If true, the url is not constructed using the # * <tt>:skip_relative_url_root</tt> - If true, the url is not constructed using the
# +relative_url_root+ set in ActionController::AbstractRequest.relative_url_root. # +relative_url_root+ set in ActionController::AbstractRequest.relative_url_root.
# * <tt>:trailing_slash</tt> If true, adds a trailing slash, as in "/archive/2009/" # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
# #
# Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to # Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
# +url_for+ is forwarded to the Routes module. # +url_for+ is forwarded to the Routes module.

View file

@ -5,9 +5,9 @@ module ActionView #:nodoc:
class MissingTemplate < ActionViewError #:nodoc: class MissingTemplate < ActionViewError #:nodoc:
end end
# Action View templates can be written in three ways. If the template file has a +.erb+ (or +.rhtml+) extension then it uses a mixture of ERb # Action View templates can be written in three ways. If the template file has a <tt>.erb</tt> (or <tt>.rhtml</tt>) extension then it uses a mixture of ERb
# (included in Ruby) and HTML. If the template file has a +.builder+ (or +.rxml+) extension then Jim Weirich's Builder::XmlMarkup library is used. # (included in Ruby) and HTML. If the template file has a <tt>.builder</tt> (or <tt>.rxml</tt>) extension then Jim Weirich's Builder::XmlMarkup library is used.
# If the template file has a +.rjs+ extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator. # If the template file has a <tt>.rjs</tt> extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.
# #
# = ERb # = ERb
# #
@ -24,7 +24,7 @@ module ActionView #:nodoc:
# #
# Hi, Mr. <% puts "Frodo" %> # Hi, Mr. <% puts "Frodo" %>
# #
# If you absolutely must write from within a function, you can use the TextHelper#concat # If you absolutely must write from within a function, you can use the TextHelper#concat.
# #
# <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>. # <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>.
# #
@ -46,7 +46,7 @@ module ActionView #:nodoc:
# <% @page_title = "A Wonderful Hello" %> # <% @page_title = "A Wonderful Hello" %>
# <%= render "shared/header" %> # <%= render "shared/header" %>
# #
# Now the header can pick up on the @page_title variable and use it for outputting a title tag: # Now the header can pick up on the <tt>@page_title</tt> variable and use it for outputting a title tag:
# #
# <title><%= @page_title %></title> # <title><%= @page_title %></title>
# #
@ -56,7 +56,7 @@ module ActionView #:nodoc:
# #
# <%= render "shared/header", { :headline => "Welcome", :person => person } %> # <%= render "shared/header", { :headline => "Welcome", :person => person } %>
# #
# These can now be accessed in shared/header with: # These can now be accessed in <tt>shared/header</tt> with:
# #
# Headline: <%= headline %> # Headline: <%= headline %>
# First name: <%= person.first_name %> # First name: <%= person.first_name %>
@ -77,13 +77,13 @@ module ActionView #:nodoc:
# #
# == Builder # == Builder
# #
# Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An +XmlMarkup+ object # Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An XmlMarkup object
# named +xml+ is automatically made available to templates with a +.builder+ extension. # named +xml+ is automatically made available to templates with a <tt>.builder</tt> extension.
# #
# Here are some basic examples: # Here are some basic examples:
# #
# xml.em("emphasized") # => <em>emphasized</em> # xml.em("emphasized") # => <em>emphasized</em>
# xml.em { xml.b("emph & bold") } # => <em><b>emph &amp; bold</b></em> # xml.em { xml.b("emph & bold") } # => <em><b>emph &amp; bold</b></em>
# xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a> # xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a>
# xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\> # xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\>
# # NOTE: order of attributes is not specified. # # NOTE: order of attributes is not specified.
@ -130,18 +130,18 @@ module ActionView #:nodoc:
# #
# == JavaScriptGenerator # == JavaScriptGenerator
# #
# JavaScriptGenerator templates end in +.rjs+. Unlike conventional templates which are used to # JavaScriptGenerator templates end in <tt>.rjs</tt>. Unlike conventional templates which are used to
# render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to
# modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax
# and make updates to the page where the request originated from. # and make updates to the page where the request originated from.
# #
# An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block. # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block.
# #
# When an .rjs action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example: # When an <tt>.rjs</tt> action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example:
# #
# link_to_remote :url => {:action => 'delete'} # link_to_remote :url => {:action => 'delete'}
# #
# The subsequently rendered +delete.rjs+ might look like: # The subsequently rendered <tt>delete.rjs</tt> might look like:
# #
# page.replace_html 'sidebar', :partial => 'sidebar' # page.replace_html 'sidebar', :partial => 'sidebar'
# page.remove "person-#{@person.id}" # page.remove "person-#{@person.id}"

View file

@ -316,12 +316,12 @@ module ActionView
# Creates a submit button with the text <tt>value</tt> as the caption. # Creates a submit button with the text <tt>value</tt> as the caption.
# #
# ==== Options # ==== Options
# * <tt>:confirm => 'question?'</tt> -- This will add a JavaScript confirm # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm
# prompt with the question specified. If the user accepts, the form is # prompt with the question specified. If the user accepts, the form is
# processed normally, otherwise no action is taken. # processed normally, otherwise no action is taken.
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input. # * <tt>:disabled</tt> - If true, the user will not be able to use this input.
# * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version # * <tt>:disable_with</tt> - Value of this parameter will be used as the value for a disabled version
# of the submit button when the form is submitted. # of the submit button when the form is submitted.
# * Any other key creates standard HTML options for the tag. # * Any other key creates standard HTML options for the tag.
# #
# ==== Examples # ==== Examples

View file

@ -631,6 +631,27 @@ module ActionView
# render(:update) { |page| page.update_time } # render(:update) { |page| page.update_time }
# end # end
# #
# Calls to JavaScriptGenerator not matching a helper method below
# generate a proxy to the JavaScript Class named by the method called.
#
# Examples:
#
# # Generates:
# # Foo.init();
# update_page do |page|
# page.foo.init
# end
#
# # Generates:
# # Event.observe('one', 'click', function () {
# # $('two').show();
# # });
# update_page do |page|
# page.event.observe('one', 'click') do |p|
# p[:two].show
# end
# end
#
# You can also use PrototypeHelper#update_page_tag instead of # You can also use PrototypeHelper#update_page_tag instead of
# PrototypeHelper#update_page to wrap the generated JavaScript in a # PrototypeHelper#update_page to wrap the generated JavaScript in a
# <script> tag. # <script> tag.
@ -855,12 +876,21 @@ module ActionView
# #
# Examples: # Examples:
# #
# # Generates: Element.replace(my_element, "My content to replace with.") # # Generates: Element.replace(my_element, "My content to replace with.")
# page.call 'Element.replace', 'my_element', "My content to replace with." # page.call 'Element.replace', 'my_element', "My content to replace with."
# #
# # Generates: alert('My message!') # # Generates: alert('My message!')
# page.call 'alert', 'My message!' # page.call 'alert', 'My message!'
# #
# # Generates:
# # my_method(function() {
# # $("one").show();
# # $("two").hide();
# # });
# page.call(:my_method) do |p|
# p[:one].show
# p[:two].hide
# end
def call(function, *arguments, &block) def call(function, *arguments, &block)
record "#{function}(#{arguments_for_call(arguments, block)})" record "#{function}(#{arguments_for_call(arguments, block)})"
end end

View file

@ -19,15 +19,15 @@ module ActionView
# need an unescaped url, pass <tt>:escape => false</tt> in the +options+. # need an unescaped url, pass <tt>:escape => false</tt> in the +options+.
# #
# ==== Options # ==== Options
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. # * <tt>:anchor</tt> - Specifies the anchor name to be appended to the path.
# * <tt>:only_path</tt> -- if true, returns the relative URL (omitting the protocol, host name, and port) (<tt>true</tt> by default unless <tt>:host</tt> is specified) # * <tt>:only_path</tt> - If true, returns the relative URL (omitting the protocol, host name, and port) (<tt>true</tt> by default unless <tt>:host</tt> is specified).
# * <tt>:trailing_slash</tt> -- if true, adds a trailing slash, as in "/archive/2005/". Note that this # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2005/". Note that this
# is currently not recommended since it breaks caching. # is currently not recommended since it breaks caching.
# * <tt>:host</tt> -- overrides the default (current) host if provided # * <tt>:host</tt> - Overrides the default (current) host if provided.
# * <tt>:protocol</tt> -- overrides the default (current) protocol if provided # * <tt>:protocol</tt> - Overrides the default (current) protocol if provided.
# * <tt>:user</tt> -- Inline HTTP authentication (only plucked out if <tt>:password</tt> is also present) # * <tt>:user</tt> - Inline HTTP authentication (only plucked out if <tt>:password</tt> is also present).
# * <tt>:password</tt> -- Inline HTTP authentication (only plucked out if <tt>:user</tt> is also present) # * <tt>:password</tt> - Inline HTTP authentication (only plucked out if <tt>:user</tt> is also present).
# * <tt>:escape</tt> -- Determines whether the returned URL will be HTML escaped or not (<tt>true</tt> by default) # * <tt>:escape</tt> - Determines whether the returned URL will be HTML escaped or not (<tt>true</tt> by default).
# #
# ==== Relying on named routes # ==== Relying on named routes
# #
@ -91,14 +91,14 @@ module ActionView
# a name, the link itself will become the name. # a name, the link itself will become the name.
# #
# ==== Options # ==== Options
# * <tt>:confirm => 'question?'</tt> -- This will add a JavaScript confirm # * <tt>:confirm => 'question?'</tt> - This will add a JavaScript confirm
# prompt with the question specified. If the user accepts, the link is # prompt with the question specified. If the user accepts, the link is
# processed normally, otherwise no action is taken. # processed normally, otherwise no action is taken.
# * <tt>:popup => true || array of window options</tt> -- This will force the # * <tt>:popup => true || array of window options</tt> - This will force the
# link to open in a popup window. By passing true, a default browser window # link to open in a popup window. By passing true, a default browser window
# will be opened with the URL. You can also specify an array of options # will be opened with the URL. You can also specify an array of options
# that are passed-thru to JavaScripts window.open method. # that are passed-thru to JavaScripts window.open method.
# * <tt>:method => symbol of HTTP verb</tt> -- This modifier will dynamically # * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically
# create an HTML form and immediately submit the form for processing using # create an HTML form and immediately submit the form for processing using
# the HTTP verb specified. Useful for having links perform a POST operation # the HTTP verb specified. Useful for having links perform a POST operation
# in dangerous actions like deleting a record (which search bots can follow # in dangerous actions like deleting a record (which search bots can follow
@ -178,9 +178,9 @@ module ActionView
# The +options+ hash accepts the same options at url_for. # The +options+ hash accepts the same options at url_for.
# #
# There are a few special +html_options+: # There are a few special +html_options+:
# * <tt>:method</tt> -- specifies the anchor name to be appended to the path. # * <tt>:method</tt> - Specifies the anchor name to be appended to the path.
# * <tt>:disabled</tt> -- specifies the anchor name to be appended to the path. # * <tt>:disabled</tt> - Specifies the anchor name to be appended to the path.
# * <tt>:confirm</tt> -- This will add a JavaScript confirm # * <tt>:confirm</tt> - This will add a JavaScript confirm
# prompt with the question specified. If the user accepts, the link is # prompt with the question specified. If the user accepts, the link is
# processed normally, otherwise no action is taken. # processed normally, otherwise no action is taken.
# #

View file

@ -25,7 +25,7 @@ module ActiveModel
# #
# Configuration options: # Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "is invalid") # * <tt>:message</tt> - A custom error message (default is: "is invalid")
# * <tt>:on</tt> Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>) # * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>)
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value. # method, proc or string should return or evaluate to a true or false value.

View file

@ -15,17 +15,17 @@ module ActiveModel
# end # end
# #
# Configuration options: # Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "is not a number") # * <tt>:message</tt> - A custom error message (default is: "is not a number").
# * <tt>:on</tt> Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>) # * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
# * <tt>:only_integer</tt> Specifies whether the value has to be an integer, e.g. an integral value (default is +false+) # * <tt>:only_integer</tt> - Specifies whether the value has to be an integer, e.g. an integral value (default is +false+).
# * <tt>:allow_nil</tt> Skip validation if attribute is +nil+ (default is +false+). Notice that for fixnum and float columns empty strings are converted to +nil+ # * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default is +false+). Notice that for fixnum and float columns empty strings are converted to +nil+.
# * <tt>:greater_than</tt> Specifies the value must be greater than the supplied value # * <tt>:greater_than</tt> - Specifies the value must be greater than the supplied value.
# * <tt>:greater_than_or_equal_to</tt> Specifies the value must be greater than or equal the supplied value # * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be greater than or equal the supplied value.
# * <tt>:equal_to</tt> Specifies the value must be equal to the supplied value # * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied value.
# * <tt>:less_than</tt> Specifies the value must be less than the supplied value # * <tt>:less_than</tt> - Specifies the value must be less than the supplied value.
# * <tt>:less_than_or_equal_to</tt> Specifies the value must be less than or equal the supplied value # * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less than or equal the supplied value.
# * <tt>:odd</tt> Specifies the value must be an odd number # * <tt>:odd</tt> - Specifies the value must be an odd number.
# * <tt>:even</tt> Specifies the value must be an even number # * <tt>:even</tt> - Specifies the value must be an even number.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value. # method, proc or string should return or evaluate to a true or false value.

View file

@ -169,10 +169,10 @@ A short rundown of the major features:
class AddSystemSettings < ActiveRecord::Migration class AddSystemSettings < ActiveRecord::Migration
def self.up def self.up
create_table :system_settings do |t| create_table :system_settings do |t|
t.string :name t.string :name
t.string :label t.string :label
t.text :value t.text :value
t.string :type t.string :type
t.integer :position t.integer :position
end end
@ -289,16 +289,6 @@ Bi-directional associations thanks to the "belongs_to" macro
thirty_seven_signals.firm.nil? # true thirty_seven_signals.firm.nil? # true
== Examples
Active Record ships with a couple of examples that should give you a good feel for
operating usage. Be sure to edit the <tt>examples/shared_setup.rb</tt> file for your
own database before running the examples. Possibly also the table definition SQL in
the examples themselves.
It's also highly recommended to have a look at the unit tests. Read more in link:files/RUNNING_UNIT_TESTS.html
== Philosophy == Philosophy
Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is
@ -336,7 +326,7 @@ then use:
% [sudo] gem install activerecord-1.10.0.gem % [sudo] gem install activerecord-1.10.0.gem
You can also install Active Record the old-fashion way with the following command: You can also install Active Record the old-fashioned way with the following command:
% [sudo] ruby install.rb % [sudo] ruby install.rb
@ -357,5 +347,5 @@ RubyForge page at http://rubyforge.org/projects/activerecord. And as Jim from Ra
remember to update the corresponding unit tests. If fact, I prefer remember to update the corresponding unit tests. If fact, I prefer
new feature to be submitted in the form of new unit tests. new feature to be submitted in the form of new unit tests.
For other information, feel free to ask on the ruby-talk mailing list For other information, feel free to ask on the rubyonrails-talk
(which is mirrored to comp.lang.ruby) or contact mailto:david@loudthinking.com. (http://groups.google.com/group/rubyonrails-talk) mailing list.

View file

@ -110,7 +110,7 @@ module ActiveRecord
# #
# Don't create associations that have the same name as instance methods of ActiveRecord::Base. Since the association # Don't create associations that have the same name as instance methods of ActiveRecord::Base. Since the association
# adds a method with that name to its model, it will override the inherited method and break things. # adds a method with that name to its model, it will override the inherited method and break things.
# For instance, #attributes and #connection would be bad choices for association names. # For instance, +attributes+ and +connection+ would be bad choices for association names.
# #
# == Auto-generated methods # == Auto-generated methods
# #
@ -258,7 +258,7 @@ module ActiveRecord
# order to update their primary keys - except if the parent object is unsaved (<tt>new_record? == true</tt>). # order to update their primary keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
# * If either of these saves fail (due to one of the objects being invalid) the assignment statement returns +false+ and the assignment # * If either of these saves fail (due to one of the objects being invalid) the assignment statement returns +false+ and the assignment
# is cancelled. # is cancelled.
# * If you wish to assign an object to a +has_one+ association without saving it, use the <tt>#association.build</tt> method (documented below). # * If you wish to assign an object to a +has_one+ association without saving it, use the <tt>association.build</tt> method (documented below).
# * Assigning an object to a +belongs_to+ association does not save the object, since the foreign key field belongs on the parent. It # * Assigning an object to a +belongs_to+ association does not save the object, since the foreign key field belongs on the parent. It
# does not save the parent either. # does not save the parent either.
# #
@ -266,8 +266,8 @@ module ActiveRecord
# #
# * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically saves that object, except if the parent object # * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically saves that object, except if the parent object
# (the owner of the collection) is not yet stored in the database. # (the owner of the collection) is not yet stored in the database.
# * If saving any of the objects being added to a collection (via <tt>#push</tt> or similar) fails, then <tt>#push</tt> returns +false+. # * If saving any of the objects being added to a collection (via <tt>push</tt> or similar) fails, then <tt>push</tt> returns +false+.
# * You can add an object to a collection without automatically saving it by using the <tt>#collection.build</tt> method (documented below). # * You can add an object to a collection without automatically saving it by using the <tt>collection.build</tt> method (documented below).
# * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically saved when the parent is saved. # * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically saved when the parent is saved.
# #
# === Association callbacks # === Association callbacks
@ -504,8 +504,8 @@ module ActiveRecord
# #
# Address.find(:all, :include => :addressable) # INVALID # Address.find(:all, :include => :addressable) # INVALID
# #
# will raise <tt>ActiveRecord::EagerLoadPolymorphicError</tt>. The reason is that the parent model's type # will raise ActiveRecord::EagerLoadPolymorphicError. The reason is that the parent model's type
# is a column value so its corresponding table name cannot be put in the FROM/JOIN clauses of that early query. # is a column value so its corresponding table name cannot be put in the +FROM+/+JOIN+ clauses of that early query.
# #
# In versions greater than 2.0.2 eager loading in polymorphic associations is supported # In versions greater than 2.0.2 eager loading in polymorphic associations is supported
# thanks to a change in the overall preloading strategy. # thanks to a change in the overall preloading strategy.
@ -575,7 +575,7 @@ module ActiveRecord
# end # end
# end # end
# #
# When <tt>Firm#clients</tt> is called, it will in turn call <tt>MyApplication::Business::Company.find(firm.id)</tt>. If you want to associate # When Firm#clients is called, it will in turn call <tt>MyApplication::Business::Company.find(firm.id)</tt>. If you want to associate
# with a class in another module scope, this can be done by specifying the complete class name. Example: # with a class in another module scope, this can be done by specifying the complete class name. Example:
# #
# module MyApplication # module MyApplication
@ -603,28 +603,28 @@ module ActiveRecord
# Adds the following methods for retrieval and query of collections of associated objects: # Adds the following methods for retrieval and query of collections of associated objects:
# +collection+ is replaced with the symbol passed as the first argument, so # +collection+ is replaced with the symbol passed as the first argument, so
# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>. # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
# * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. # * <tt>collection(force_reload = false)</tt> - Returns an array of all the associated objects.
# An empty array is returned if none are found. # An empty array is returned if none are found.
# * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by setting their foreign keys to the collection's primary key. # * <tt>collection<<(object, ...)</tt> - Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
# * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by setting their foreign keys to NULL. # * <tt>collection.delete(object, ...)</tt> - Removes one or more objects from the collection by setting their foreign keys to +NULL+.
# This will also destroy the objects if they're declared as +belongs_to+ and dependent on this model. # This will also destroy the objects if they're declared as +belongs_to+ and dependent on this model.
# * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate. # * <tt>collection=objects</tt> - Replaces the collections content by deleting and adding objects as appropriate.
# * <tt>collection_singular_ids</tt> - returns an array of the associated objects' ids # * <tt>collection_singular_ids</tt> - Returns an array of the associated objects' ids
# * <tt>collection_singular_ids=ids</tt> - replace the collection with the objects identified by the primary keys in +ids+ # * <tt>collection_singular_ids=ids</tt> - Replace the collection with the objects identified by the primary keys in +ids+
# * <tt>collection.clear</tt> - removes every object from the collection. This destroys the associated objects if they # * <tt>collection.clear</tt> - Removes every object from the collection. This destroys the associated objects if they
# are associated with <tt>:dependent => :destroy</tt>, deletes them directly from the database if <tt>:dependent => :delete_all</tt>, # are associated with <tt>:dependent => :destroy</tt>, deletes them directly from the database if <tt>:dependent => :delete_all</tt>,
# otherwise sets their foreign keys to NULL. # otherwise sets their foreign keys to +NULL+.
# * <tt>collection.empty?</tt> - returns +true+ if there are no associated objects. # * <tt>collection.empty?</tt> - Returns +true+ if there are no associated objects.
# * <tt>collection.size</tt> - returns the number of associated objects. # * <tt>collection.size</tt> - Returns the number of associated objects.
# * <tt>collection.find</tt> - finds an associated object according to the same rules as Base.find. # * <tt>collection.find</tt> - Finds an associated object according to the same rules as Base.find.
# * <tt>collection.build(attributes = {}, ...)</tt> - returns one or more new objects of the collection type that have been instantiated # * <tt>collection.build(attributes = {}, ...)</tt> - Returns one or more new objects of the collection type that have been instantiated
# with +attributes+ and linked to this object through a foreign key, but have not yet been saved. *Note:* This only works if an # with +attributes+ and linked to this object through a foreign key, but have not yet been saved. *Note:* This only works if an
# associated object already exists, not if it's +nil+! # associated object already exists, not if it's +nil+!
# * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated # * <tt>collection.create(attributes = {})</tt> - Returns a new object of the collection type that has been instantiated
# with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation). # with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation).
# *Note:* This only works if an associated object already exists, not if it's +nil+! # *Note:* This only works if an associated object already exists, not if it's +nil+!
# #
# Example: A +Firm+ class declares <tt>has_many :clients</tt>, which will add: # Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
# * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => "firm_id = #{id}"</tt>) # * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => "firm_id = #{id}"</tt>)
# * <tt>Firm#clients<<</tt> # * <tt>Firm#clients<<</tt>
# * <tt>Firm#clients.delete</tt> # * <tt>Firm#clients.delete</tt>
@ -640,45 +640,45 @@ module ActiveRecord
# The declaration can also include an options hash to specialize the behavior of the association. # The declaration can also include an options hash to specialize the behavior of the association.
# #
# Options are: # Options are:
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
# from the association name. So <tt>has_many :products</tt> will by default be linked to the +Product+ class, but # from the association name. So <tt>has_many :products</tt> will by default be linked to the Product class, but
# if the real class name is +SpecialProduct+, you'll have to specify it with this option. # if the real class name is SpecialProduct, you'll have to specify it with this option.
# * <tt>:conditions</tt> - specify the conditions that the associated objects must meet in order to be included as a +WHERE+ # * <tt>:conditions</tt> - Specify the conditions that the associated objects must meet in order to be included as a +WHERE+
# SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from the association are scoped if a hash # SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from the association are scoped if a hash
# is used. <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt> # is used. <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
# or <tt>@blog.posts.build</tt>. # or <tt>@blog.posts.build</tt>.
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, # * <tt>:order</tt> - Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
# such as <tt>last_name, first_name DESC</tt> # such as <tt>last_name, first_name DESC</tt>.
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
# of this class in lower-case and +_id+ suffixed. So a +Person+ class that makes a +has_many+ association will use +person_id+ # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+ association will use "person_id"
# as the default +foreign_key+. # as the default <tt>:foreign_key</tt>.
# * <tt>:dependent</tt> - if set to <tt>:destroy</tt> all the associated objects are destroyed # * <tt>:dependent</tt> - If set to <tt>:destroy</tt> all the associated objects are destroyed
# alongside this object by calling their destroy method. If set to <tt>:delete_all</tt> all associated # alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated
# objects are deleted *without* calling their destroy method. If set to <tt>:nullify</tt> all associated # objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
# objects' foreign keys are set to +NULL+ *without* calling their save callbacks. *Warning:* This option is ignored when also using # objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. *Warning:* This option is ignored when also using
# the <tt>through</tt> option. # the <tt>:through</tt> option.
# * <tt>:finder_sql</tt> - specify a complete SQL statement to fetch the association. This is a good way to go for complex # * <tt>:finder_sql</tt> - Specify a complete SQL statement to fetch the association. This is a good way to go for complex
# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added. # associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added.
# * <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is # * <tt>:counter_sql</tt> - Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
# specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>. # specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
# * <tt>:extend</tt> - specify a named module for extending the proxy. See "Association extensions". # * <tt>:extend</tt> - Specify a named module for extending the proxy. See "Association extensions".
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. # * <tt>:include</tt> - Specify second-order associations that should be eager loaded when the collection is loaded.
# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause. # * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. # * <tt>:limit</tt> - An integer determining the limit on the number of rows that should be returned.
# * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. # * <tt>:offset</tt> - An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.
# * <tt>:select</tt>: By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if you, for example, want to do a join # * <tt>:select</tt> - By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if you, for example, want to do a join
# but not include the joined columns. # but not include the joined columns.
# * <tt>:as</tt>: Specifies a polymorphic interface (See <tt>#belongs_to</tt>). # * <tt>:as</tt> - Specifies a polymorphic interface (See <tt>belongs_to</tt>).
# * <tt>:through</tt>: Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt> # * <tt>:through</tt> - Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt>
# are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt> # are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt>
# or <tt>has_many</tt> association on the join model. # or <tt>has_many</tt> association on the join model.
# * <tt>:source</tt>: Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be # * <tt>:source</tt> - Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be
# inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or # inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or
# <tt>:subscriber</tt> on +Subscription+, unless a <tt>:source</tt> is given. # <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
# * <tt>:source_type</tt>: Specifies type of the source association used by <tt>has_many :through</tt> queries where the source # * <tt>:source_type</tt> - Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
# association is a polymorphic +belongs_to+. # association is a polymorphic +belongs_to+.
# * <tt>:uniq</tt> - if set to +true+, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>. # * <tt>:uniq</tt> - If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
# * <tt>:readonly</tt> - if set to +true+, all the associated objects are readonly through the association. # * <tt>:readonly</tt> - If true, all the associated objects are readonly through the association.
# #
# Option examples: # Option examples:
# has_many :comments, :order => "posted_on" # has_many :comments, :order => "posted_on"
@ -712,14 +712,14 @@ module ActiveRecord
# Adds the following methods for retrieval and query of a single associated object: # Adds the following methods for retrieval and query of a single associated object:
# +association+ is replaced with the symbol passed as the first argument, so # +association+ is replaced with the symbol passed as the first argument, so
# <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>. # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
# * <tt>association(force_reload = false)</tt> - returns the associated object. +nil+ is returned if none is found. # * <tt>association(force_reload = false)</tt> - Returns the associated object. +nil+ is returned if none is found.
# * <tt>association=(associate)</tt> - assigns the associate object, extracts the primary key, sets it as the foreign key, # * <tt>association=(associate)</tt> - Assigns the associate object, extracts the primary key, sets it as the foreign key,
# and saves the associate object. # and saves the associate object.
# * <tt>association.nil?</tt> - returns +true+ if there is no associated object. # * <tt>association.nil?</tt> - Returns +true+ if there is no associated object.
# * <tt>build_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated # * <tt>build_association(attributes = {})</tt> - Returns a new object of the associated type that has been instantiated
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved. Note: This ONLY works if # with +attributes+ and linked to this object through a foreign key, but has not yet been saved. Note: This ONLY works if
# an association already exists. It will NOT work if the association is +nil+. # an association already exists. It will NOT work if the association is +nil+.
# * <tt>create_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated # * <tt>create_association(attributes = {})</tt> - Returns a new object of the associated type that has been instantiated
# with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation). # with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation).
# #
# Example: An Account class declares <tt>has_one :beneficiary</tt>, which will add: # Example: An Account class declares <tt>has_one :beneficiary</tt>, which will add:
@ -732,28 +732,28 @@ module ActiveRecord
# The declaration can also include an options hash to specialize the behavior of the association. # The declaration can also include an options hash to specialize the behavior of the association.
# #
# Options are: # Options are:
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
# from the association name. So <tt>has_one :manager</tt> will by default be linked to the +Manager+ class, but # from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
# if the real class name is +Person+, you'll have to specify it with this option. # if the real class name is Person, you'll have to specify it with this option.
# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a +WHERE+ # * <tt>:conditions</tt> - Specify the conditions that the associated object must meet in order to be included as a +WHERE+
# SQL fragment, such as <tt>rank = 5</tt>. # SQL fragment, such as <tt>rank = 5</tt>.
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, # * <tt>:order</tt> - Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
# such as <tt>last_name, first_name DESC</tt> # such as <tt>last_name, first_name DESC</tt>.
# * <tt>:dependent</tt> - if set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to # * <tt>:dependent</tt> - If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to <tt>:nullify</tt>, the associated # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to <tt>:nullify</tt>, the associated
# object's foreign key is set to +NULL+. Also, association is assigned. # object's foreign key is set to +NULL+. Also, association is assigned.
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
# of this class in lower-case and +_id+ suffixed. So a +Person+ class that makes a +has_one+ association will use +person_id+ # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association will use "person_id"
# as the default +foreign_key+. # as the default <tt>:foreign_key</tt>.
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. # * <tt>:include</tt> - Specify second-order associations that should be eager loaded when this object is loaded.
# * <tt>:as</tt>: Specifies a polymorphic interface (See <tt>#belongs_to</tt>). # * <tt>:as</tt> - Specifies a polymorphic interface (See <tt>belongs_to</tt>).
# * <tt>:through</tt>: Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt> # * <tt>:through</tt>: Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt>
# are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a # are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a
# <tt>has_one</tt> or <tt>belongs_to</tt> association on the join model. # <tt>has_one</tt> or <tt>belongs_to</tt> association on the join model.
# * <tt>:source</tt>: Specifies the source association name used by <tt>has_one :through</tt> queries. Only use it if the name cannot be # * <tt>:source</tt> - Specifies the source association name used by <tt>has_one :through</tt> queries. Only use it if the name cannot be
# inferred from the association. <tt>has_one :favorite, :through => :favorites</tt> will look for a # inferred from the association. <tt>has_one :favorite, :through => :favorites</tt> will look for a
# <tt>:favorite</tt> on +Favorite+, unless a <tt>:source</tt> is given. # <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
# * <tt>:readonly</tt> - if set to +true+, the associated object is readonly through the association. # * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
# #
# Option examples: # Option examples:
# has_one :credit_card, :dependent => :destroy # destroys the associated credit card # has_one :credit_card, :dependent => :destroy # destroys the associated credit card
@ -796,12 +796,12 @@ module ActiveRecord
# Adds the following methods for retrieval and query for a single associated object for which this object holds an id: # Adds the following methods for retrieval and query for a single associated object for which this object holds an id:
# +association+ is replaced with the symbol passed as the first argument, so # +association+ is replaced with the symbol passed as the first argument, so
# <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>. # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
# * <tt>association(force_reload = false)</tt> - returns the associated object. +nil+ is returned if none is found. # * <tt>association(force_reload = false)</tt> - Returns the associated object. +nil+ is returned if none is found.
# * <tt>association=(associate)</tt> - assigns the associate object, extracts the primary key, and sets it as the foreign key. # * <tt>association=(associate)</tt> - Assigns the associate object, extracts the primary key, and sets it as the foreign key.
# * <tt>association.nil?</tt> - returns +true+ if there is no associated object. # * <tt>association.nil?</tt> - Returns +true+ if there is no associated object.
# * <tt>build_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated # * <tt>build_association(attributes = {})</tt> - Returns a new object of the associated type that has been instantiated
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved. # with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
# * <tt>create_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated # * <tt>create_association(attributes = {})</tt> - Returns a new object of the associated type that has been instantiated
# with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation). # with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation).
# #
# Example: A Post class declares <tt>belongs_to :author</tt>, which will add: # Example: A Post class declares <tt>belongs_to :author</tt>, which will add:
@ -814,34 +814,35 @@ module ActiveRecord
# The declaration can also include an options hash to specialize the behavior of the association. # The declaration can also include an options hash to specialize the behavior of the association.
# #
# Options are: # Options are:
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
# from the association name. So <tt>has_one :author</tt> will by default be linked to the +Author+ class, but # from the association name. So <tt>has_one :author</tt> will by default be linked to the Author class, but
# if the real class name is +Person+, you'll have to specify it with this option. # if the real class name is Person, you'll have to specify it with this option.
# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a +WHERE+ # * <tt>:conditions</tt> - Specify the conditions that the associated object must meet in order to be included as a +WHERE+
# SQL fragment, such as <tt>authorized = 1</tt>. # SQL fragment, such as <tt>authorized = 1</tt>.
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, # * <tt>:order</tt> - Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
# such as <tt>last_name, first_name DESC</tt> # such as <tt>last_name, first_name DESC</tt>.
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
# of the association with an +_id+ suffix. So a class that defines a +belongs_to :person+ association will use +person_id+ as the default +foreign_key+. # of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt> association will use
# Similarly, +belongs_to :favorite_person, :class_name => "Person"+ will use a foreign key of +favorite_person_id+. # "person_id" as the default <tt>:foreign_key</tt>. Similarly, <tt>belongs_to :favorite_person, :class_name => "Person"</tt>
# * <tt>:dependent</tt> - if set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to # will use a foreign key of "favorite_person_id".
# * <tt>:dependent</tt> - If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. This option should not be specified when # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. This option should not be specified when
# <tt>belongs_to</tt> is used in conjunction with a <tt>has_many</tt> relationship on another class because of the potential to leave # <tt>belongs_to</tt> is used in conjunction with a <tt>has_many</tt> relationship on another class because of the potential to leave
# orphaned records behind. # orphaned records behind.
# * <tt>:counter_cache</tt> - caches the number of belonging objects on the associate class through the use of +increment_counter+ # * <tt>:counter_cache</tt> - Caches the number of belonging objects on the associate class through the use of +increment_counter+
# and +decrement_counter+. The counter cache is incremented when an object of this class is created and decremented when it's # and +decrement_counter+. The counter cache is incremented when an object of this class is created and decremented when it's
# destroyed. This requires that a column named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging +Comment+ class) # destroyed. This requires that a column named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
# is used on the associate class (such as a +Post+ class). You can also specify a custom counter cache column by providing # is used on the associate class (such as a Post class). You can also specify a custom counter cache column by providing
# a column name instead of a +true+/+false+ value to this option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.) # a column name instead of a +true+/+false+ value to this option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.)
# When creating a counter cache column, the database statement or migration must specify a default value of <tt>0</tt>, failing to do # When creating a counter cache column, the database statement or migration must specify a default value of <tt>0</tt>, failing to do
# this results in a counter with NULL value, which will never increment. # this results in a counter with +NULL+ value, which will never increment.
# Note: Specifying a counter_cache will add it to that model's list of readonly attributes using #attr_readonly. # Note: Specifying a counter cache will add it to that model's list of readonly attributes using +attr_readonly+.
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. # * <tt>:include</tt> - Specify second-order associations that should be eager loaded when this object is loaded.
# Not allowed if the association is polymorphic. # Not allowed if the association is polymorphic.
# * <tt>:polymorphic</tt> - specify this association is a polymorphic association by passing +true+. # * <tt>:polymorphic</tt> - Specify this association is a polymorphic association by passing +true+.
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
# to the attr_readonly list in the associated classes (e.g. class Post; attr_readonly :comments_count; end). # to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
# * <tt>:readonly</tt> - if set to +true+, the associated object is readonly through the association. # * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
# #
# Option examples: # Option examples:
# belongs_to :firm, :foreign_key => "client_of" # belongs_to :firm, :foreign_key => "client_of"
@ -926,14 +927,14 @@ module ActiveRecord
end end
# Associates two classes via an intermediate join table. Unless the join table is explicitly specified as # Associates two classes via an intermediate join table. Unless the join table is explicitly specified as
# an option, it is guessed using the lexical order of the class names. So a join between +Developer+ and +Project+ # an option, it is guessed using the lexical order of the class names. So a join between Developer and Project
# will give the default join table name of +developers_projects+ because "D" outranks "P". Note that this precedence # will give the default join table name of "developers_projects" because "D" outranks "P". Note that this precedence
# is calculated using the <tt><</tt> operator for <tt>String</tt>. This means that if the strings are of different lengths, # is calculated using the <tt><</tt> operator for String. This means that if the strings are of different lengths,
# and the strings are equal when compared up to the shortest length, then the longer string is considered of higher # and the strings are equal when compared up to the shortest length, then the longer string is considered of higher
# lexical precedence than the shorter one. For example, one would expect the tables <tt>paper_boxes</tt> and <tt>papers</tt> # lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers"
# to generate a join table name of <tt>papers_paper_boxes</tt> because of the length of the name <tt>paper_boxes</tt>, # to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes",
# but it in fact generates a join table name of <tt>paper_boxes_papers</tt>. Be aware of this caveat, and use the # but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
# custom <tt>join_table</tt> option if you need to. # custom <tt>:join_table</tt> option if you need to.
# #
# Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through # Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through
# +has_and_belongs_to_many+ associations. Records returned from join tables with additional attributes will be marked as # +has_and_belongs_to_many+ associations. Records returned from join tables with additional attributes will be marked as
@ -943,23 +944,23 @@ module ActiveRecord
# Adds the following methods for retrieval and query: # Adds the following methods for retrieval and query:
# +collection+ is replaced with the symbol passed as the first argument, so # +collection+ is replaced with the symbol passed as the first argument, so
# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>. # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
# * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. # * <tt>collection(force_reload = false)</tt> - Returns an array of all the associated objects.
# An empty array is returned if none are found. # An empty array is returned if none are found.
# * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by creating associations in the join table # * <tt>collection<<(object, ...)</tt> - Adds one or more objects to the collection by creating associations in the join table
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method). # (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
# * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by removing their associations from the join table. # * <tt>collection.delete(object, ...)</tt> - Removes one or more objects from the collection by removing their associations from the join table.
# This does not destroy the objects. # This does not destroy the objects.
# * <tt>collection=objects</tt> - replaces the collection's content by deleting and adding objects as appropriate. # * <tt>collection=objects</tt> - Replaces the collection's content by deleting and adding objects as appropriate.
# * <tt>collection_singular_ids</tt> - returns an array of the associated objects' ids # * <tt>collection_singular_ids</tt> - Returns an array of the associated objects' ids.
# * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+ # * <tt>collection_singular_ids=ids</tt> - Replace the collection by the objects identified by the primary keys in +ids+.
# * <tt>collection.clear</tt> - removes every object from the collection. This does not destroy the objects. # * <tt>collection.clear</tt> - Removes every object from the collection. This does not destroy the objects.
# * <tt>collection.empty?</tt> - returns +true+ if there are no associated objects. # * <tt>collection.empty?</tt> - Returns +true+ if there are no associated objects.
# * <tt>collection.size</tt> - returns the number of associated objects. # * <tt>collection.size</tt> - Returns the number of associated objects.
# * <tt>collection.find(id)</tt> - finds an associated object responding to the +id+ and that # * <tt>collection.find(id)</tt> - Finds an associated object responding to the +id+ and that
# meets the condition that it has to be associated with this object. # meets the condition that it has to be associated with this object.
# * <tt>collection.build(attributes = {})</tt> - returns a new object of the collection type that has been instantiated # * <tt>collection.build(attributes = {})</tt> - Returns a new object of the collection type that has been instantiated
# with +attributes+ and linked to this object through the join table, but has not yet been saved. # with +attributes+ and linked to this object through the join table, but has not yet been saved.
# * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated # * <tt>collection.create(attributes = {})</tt> - Returns a new object of the collection type that has been instantiated
# with +attributes+, linked to this object through the join table, and that has already been saved (if it passed the validation). # with +attributes+, linked to this object through the join table, and that has already been saved (if it passed the validation).
# #
# Example: A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add: # Example: A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
@ -978,38 +979,38 @@ module ActiveRecord
# The declaration may include an options hash to specialize the behavior of the association. # The declaration may include an options hash to specialize the behavior of the association.
# #
# Options are: # Options are:
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
# from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the # from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
# +Project+ class, but if the real class name is +SuperProject+, you'll have to specify it with this option. # Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
# * <tt>:join_table</tt> - specify the name of the join table if the default based on lexical order isn't what you want. # * <tt>:join_table</tt> - Specify the name of the join table if the default based on lexical order isn't what you want.
# WARNING: If you're overwriting the table name of either class, the +table_name+ method MUST be declared underneath any # WARNING: If you're overwriting the table name of either class, the +table_name+ method MUST be declared underneath any
# +has_and_belongs_to_many+ declaration in order to work. # +has_and_belongs_to_many+ declaration in order to work.
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
# of this class in lower-case and +_id+ suffixed. So a +Person+ class that makes a +has_and_belongs_to_many+ association # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_and_belongs_to_many+ association
# will use +person_id+ as the default +foreign_key+. # will use "person_id" as the default <tt>:foreign_key</tt>.
# * <tt>:association_foreign_key</tt> - specify the association foreign key used for the association. By default this is # * <tt>:association_foreign_key</tt> - Specify the association foreign key used for the association. By default this is
# guessed to be the name of the associated class in lower-case and +_id+ suffixed. So if the associated class is +Project+, # guessed to be the name of the associated class in lower-case and "_id" suffixed. So if the associated class is Project,
# the +has_and_belongs_to_many+ association will use +project_id+ as the default association +foreign_key+. # the +has_and_belongs_to_many+ association will use "project_id" as the default <tt>:association_foreign_key</tt>.
# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a +WHERE+ # * <tt>:conditions</tt> - Specify the conditions that the associated object must meet in order to be included as a +WHERE+
# SQL fragment, such as <tt>authorized = 1</tt>. Record creations from the association are scoped if a hash is used. # SQL fragment, such as <tt>authorized = 1</tt>. Record creations from the association are scoped if a hash is used.
# <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt> # <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
# or <tt>@blog.posts.build</tt>. # or <tt>@blog.posts.build</tt>.
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, # * <tt>:order</tt> - Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
# such as <tt>last_name, first_name DESC</tt> # such as <tt>last_name, first_name DESC</tt>
# * <tt>:uniq</tt> - if set to +true+, duplicate associated objects will be ignored by accessors and query methods # * <tt>:uniq</tt> - If true, duplicate associated objects will be ignored by accessors and query methods.
# * <tt>:finder_sql</tt> - overwrite the default generated SQL statement used to fetch the association with a manual statement # * <tt>:finder_sql</tt> - Overwrite the default generated SQL statement used to fetch the association with a manual statement
# * <tt>:delete_sql</tt> - overwrite the default generated SQL statement used to remove links between the associated # * <tt>:delete_sql</tt> - Overwrite the default generated SQL statement used to remove links between the associated
# classes with a manual statement # classes with a manual statement.
# * <tt>:insert_sql</tt> - overwrite the default generated SQL statement used to add links between the associated classes # * <tt>:insert_sql</tt> - Overwrite the default generated SQL statement used to add links between the associated classes
# with a manual statement # with a manual statement.
# * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions". # * <tt>:extend</tt> - Anonymous module for extending the proxy, see "Association extensions".
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. # * <tt>:include</tt> - Specify second-order associations that should be eager loaded when the collection is loaded.
# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause. # * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. # * <tt>:limit</tt> - An integer determining the limit on the number of rows that should be returned.
# * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. # * <tt>:offset</tt> - An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.
# * <tt>:select</tt>: By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example, you want to do a join # * <tt>:select</tt> - By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example, you want to do a join
# but not include the joined columns. # but not include the joined columns.
# * <tt>:readonly</tt> - if set to +true+, all the associated objects are readonly through the association. # * <tt>:readonly</tt> - If true, all the associated objects are readonly through the association.
# #
# Option examples: # Option examples:
# has_and_belongs_to_many :projects # has_and_belongs_to_many :projects

View file

@ -92,13 +92,15 @@ module ActiveRecord #:nodoc:
class DangerousAttributeError < ActiveRecordError class DangerousAttributeError < ActiveRecordError
end end
# Raised when you've tried to access a column which wasn't # Raised when you've tried to access a column which wasn't loaded by your finder.
# loaded by your finder. Typically this is because <tt>:select</tt> # Typically this is because <tt>:select</tt> has been specified.
# has been specified.
class MissingAttributeError < NoMethodError class MissingAttributeError < NoMethodError
end end
class AttributeAssignmentError < ActiveRecordError #:nodoc: # Raised when an error occured while doing a mass assignment to an attribute through the
# <tt>attributes=</tt> method. The exception has an +attribute+ property that is the name of the
# offending attribute.
class AttributeAssignmentError < ActiveRecordError
attr_reader :exception, :attribute attr_reader :exception, :attribute
def initialize(message, exception, attribute) def initialize(message, exception, attribute)
@exception = exception @exception = exception
@ -107,7 +109,10 @@ module ActiveRecord #:nodoc:
end end
end end
class MultiparameterAssignmentErrors < ActiveRecordError #:nodoc: # Raised when there are multiple errors while doing a mass assignment through the +attributes+
# method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
# objects, each corresponding to the error while assigning to an attribute.
class MultiparameterAssignmentErrors < ActiveRecordError
attr_reader :errors attr_reader :errors
def initialize(errors) def initialize(errors)
@errors = errors @errors = errors
@ -230,8 +235,8 @@ module ActiveRecord #:nodoc:
# == Accessing attributes before they have been typecasted # == Accessing attributes before they have been typecasted
# #
# Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first. # Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first.
# That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model # That can be done by using the <tt><attribute>_before_type_cast</tt> accessors that all attributes have. For example, if your Account model
# has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast. # has a balance attribute, you can call <tt>account.balance_before_type_cast</tt> or <tt>account.id_before_type_cast</tt>.
# #
# This is especially useful in validation situations where the user might supply a string for an integer field and you want to display # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display
# the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you # the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you
@ -332,26 +337,26 @@ module ActiveRecord #:nodoc:
# #
# == Exceptions # == Exceptions
# #
# * +ActiveRecordError+ -- generic error class and superclass of all other errors raised by Active Record # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
# * +AdapterNotSpecified+ -- the configuration hash used in <tt>establish_connection</tt> didn't include an # * AdapterNotSpecified - The configuration hash used in <tt>establish_connection</tt> didn't include an
# <tt>:adapter</tt> key. # <tt>:adapter</tt> key.
# * +AdapterNotFound+ -- the <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a non-existent adapter # * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a non-existent adapter
# (or a bad spelling of an existing one). # (or a bad spelling of an existing one).
# * +AssociationTypeMismatch+ -- the object assigned to the association wasn't of the type specified in the association definition. # * AssociationTypeMismatch - The object assigned to the association wasn't of the type specified in the association definition.
# * +SerializationTypeMismatch+ -- the serialized object wasn't of the class specified as the second parameter. # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
# * +ConnectionNotEstablished+ -- no connection has been established. Use <tt>establish_connection</tt> before querying. # * ConnectionNotEstablished+ - No connection has been established. Use <tt>establish_connection</tt> before querying.
# * +RecordNotFound+ -- no record responded to the find* method. # * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
# Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions. # or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
# * +StatementInvalid+ -- the database server rejected the SQL statement. The precise error is added in the message. # nothing was found, please check its documentation for further details.
# Either the record with the given ID doesn't exist or the record didn't meet the additional restrictions. # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
# * +MultiparameterAssignmentErrors+ -- collection of errors that occurred during a mass assignment using the # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
# +attributes=+ method. The +errors+ property of this exception contains an array of +AttributeAssignmentError+ # <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of AttributeAssignmentError
# objects that should be inspected to determine which attributes triggered the errors. # objects that should be inspected to determine which attributes triggered the errors.
# * +AttributeAssignmentError+ -- an error occurred while doing a mass assignment through the +attributes=+ method. # * AttributeAssignmentError - An error occurred while doing a mass assignment through the <tt>attributes=</tt> method.
# You can inspect the +attribute+ property of the exception object to determine which attribute triggered the error. # You can inspect the +attribute+ property of the exception object to determine which attribute triggered the error.
# #
# *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level). # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level).
# So it's possible to assign a logger to the class through Base.logger= which will then be used by all # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
# instances in the current object space. # instances in the current object space.
class Base class Base
# Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed
@ -601,7 +606,7 @@ module ActiveRecord #:nodoc:
# User.create(:first_name => 'Jamie') # User.create(:first_name => 'Jamie')
# #
# # Create an Array of new objects # # Create an Array of new objects
# User.create([{:first_name => 'Jamie'}, {:first_name => 'Jeremy'}]) # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
# #
# # Create a single object and pass it into a block to set other attributes. # # Create a single object and pass it into a block to set other attributes.
# User.create(:first_name => 'Jamie') do |u| # User.create(:first_name => 'Jamie') do |u|
@ -609,7 +614,7 @@ module ActiveRecord #:nodoc:
# end # end
# #
# # Creating an Array of new objects using a block, where the block is executed for each object: # # Creating an Array of new objects using a block, where the block is executed for each object:
# User.create([{:first_name => 'Jamie'}, {:first_name => 'Jeremy'}]) do |u| # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
# u.is_admin = false # u.is_admin = false
# end # end
def create(attributes = nil, &block) def create(attributes = nil, &block)
@ -626,18 +631,18 @@ module ActiveRecord #:nodoc:
# Updates an object (or multiple objects) and saves it to the database, if validations pass. # Updates an object (or multiple objects) and saves it to the database, if validations pass.
# The resulting object is returned whether the object was saved successfully to the database or not. # The resulting object is returned whether the object was saved successfully to the database or not.
# #
# ==== Options # ==== Attributes
# #
# +id+ This should be the id or an array of ids to be updated # * +id+ - This should be the id or an array of ids to be updated.
# +attributes+ This should be a Hash of attributes to be set on the object, or an array of Hashes. # * +attributes+ - This should be a Hash of attributes to be set on the object, or an array of Hashes.
# #
# ==== Examples # ==== Examples
# #
# # Updating one record: # # Updating one record:
# Person.update(15, {:user_name => 'Samuel', :group => 'expert'}) # Person.update(15, { :user_name => 'Samuel', :group => 'expert' })
# #
# # Updating multiple records: # # Updating multiple records:
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} } # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
# Person.update(people.keys, people.values) # Person.update(people.keys, people.values)
def update(id, attributes) def update(id, attributes)
if id.is_a?(Array) if id.is_a?(Array)
@ -656,9 +661,9 @@ module ActiveRecord #:nodoc:
# #
# Objects are _not_ instantiated with this method. # Objects are _not_ instantiated with this method.
# #
# ==== Options # ==== Attributes
# #
# +id+ Can be either an Integer or an Array of Integers # * +id+ - Can be either an Integer or an Array of Integers.
# #
# ==== Examples # ==== Examples
# #
@ -679,9 +684,9 @@ module ActiveRecord #:nodoc:
# This essentially finds the object (or multiple objects) with the given id, creates a new object # This essentially finds the object (or multiple objects) with the given id, creates a new object
# from the attributes, and then calls destroy on it. # from the attributes, and then calls destroy on it.
# #
# ==== Options # ==== Attributes
# #
# +id+ Can be either an Integer or an Array of Integers # * +id+ - Can be either an Integer or an Array of Integers.
# #
# ==== Examples # ==== Examples
# #
@ -702,12 +707,12 @@ module ActiveRecord #:nodoc:
# Updates all records with details given if they match a set of conditions supplied, limits and order can # Updates all records with details given if they match a set of conditions supplied, limits and order can
# also be supplied. # also be supplied.
# #
# ==== Options # ==== Attributes
# #
# +updates+ A String of column and value pairs that will be set on any records that match conditions # * +updates+ - A String of column and value pairs that will be set on any records that match conditions.
# +conditions+ An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. # * +conditions+ - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ].
# See conditions in the intro for more info. # See conditions in the intro for more info.
# +options+ Additional options are <tt>:limit</tt> and/or <tt>:order</tt>, see the examples for usage. # * +options+ - Additional options are <tt>:limit</tt> and/or <tt>:order</tt>, see the examples for usage.
# #
# ==== Examples # ==== Examples
# #
@ -734,9 +739,9 @@ module ActiveRecord #:nodoc:
# many records. If you want to simply delete records without worrying about dependent associations or # many records. If you want to simply delete records without worrying about dependent associations or
# callbacks, use the much faster +delete_all+ method instead. # callbacks, use the much faster +delete_all+ method instead.
# #
# ==== Options # ==== Attributes
# #
# +conditions+ Conditions are specified the same way as with +find+ method. # * +conditions+ - Conditions are specified the same way as with +find+ method.
# #
# ==== Example # ==== Example
# #
@ -752,9 +757,9 @@ module ActiveRecord #:nodoc:
# calling the destroy method and invoking callbacks. This is a single SQL query, much more efficient # calling the destroy method and invoking callbacks. This is a single SQL query, much more efficient
# than destroy_all. # than destroy_all.
# #
# ==== Options # ==== Attributes
# #
# +conditions+ Conditions are specified the same way as with +find+ method. # * +conditions+ - Conditions are specified the same way as with +find+ method.
# #
# ==== Example # ==== Example
# #
@ -772,9 +777,9 @@ module ActiveRecord #:nodoc:
# The use of this method should be restricted to complicated SQL queries that can't be executed # The use of this method should be restricted to complicated SQL queries that can't be executed
# using the ActiveRecord::Calculations class methods. Look into those before using this. # using the ActiveRecord::Calculations class methods. Look into those before using this.
# #
# ==== Options # ==== Attributes
# #
# +sql+: An SQL statement which should return a count query from the database, see the example below # * +sql+ - An SQL statement which should return a count query from the database, see the example below.
# #
# ==== Examples # ==== Examples
# #
@ -790,12 +795,11 @@ module ActiveRecord #:nodoc:
# with the given ID, altering the given hash of counters by the amount # with the given ID, altering the given hash of counters by the amount
# given by the corresponding value: # given by the corresponding value:
# #
# ==== Options # ==== Attributes
# #
# +id+ The id of the object you wish to update a counter on # * +id+ - The id of the object you wish to update a counter on.
# +counters+ An Array of Hashes containing the names of the fields # * +counters+ - An Array of Hashes containing the names of the fields
# to update as keys and the amount to update the field by as # to update as keys and the amount to update the field by as values.
# values
# #
# ==== Examples # ==== Examples
# #
@ -821,10 +825,10 @@ module ActiveRecord #:nodoc:
# For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is # For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is
# shown it would have to run an SQL query to find how many posts and comments there are. # shown it would have to run an SQL query to find how many posts and comments there are.
# #
# ==== Options # ==== Attributes
# #
# +counter_name+ The name of the field that should be incremented # * +counter_name+ - The name of the field that should be incremented.
# +id+ The id of the object that should be incremented # * +id+ - The id of the object that should be incremented.
# #
# ==== Examples # ==== Examples
# #
@ -838,10 +842,10 @@ module ActiveRecord #:nodoc:
# #
# This works the same as increment_counter but reduces the column value by 1 instead of increasing it. # This works the same as increment_counter but reduces the column value by 1 instead of increasing it.
# #
# ==== Options # ==== Attributes
# #
# +counter_name+ The name of the field that should be decremented # * +counter_name+ - The name of the field that should be decremented.
# +id+ The id of the object that should be decremented # * +id+ - The id of the object that should be decremented.
# #
# ==== Examples # ==== Examples
# #
@ -886,9 +890,9 @@ module ActiveRecord #:nodoc:
# overwritten by URL/form hackers. If you'd rather start from an all-open default and restrict # overwritten by URL/form hackers. If you'd rather start from an all-open default and restrict
# attributes as needed, have a look at attr_protected. # attributes as needed, have a look at attr_protected.
# #
# ==== Options # ==== Attributes
# #
# <tt>*attributes</tt> A comma separated list of symbols that represent columns _not_ to be protected # * <tt>*attributes</tt> A comma separated list of symbols that represent columns _not_ to be protected
# #
# ==== Examples # ==== Examples
# #
@ -927,10 +931,10 @@ module ActiveRecord #:nodoc:
# The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that # The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
# class on retrieval or +SerializationTypeMismatch+ will be raised. # class on retrieval or +SerializationTypeMismatch+ will be raised.
# #
# ==== Options # ==== Attributes
# #
# +attr_name+ The field name that should be serialized # * +attr_name+ - The field name that should be serialized.
# +class_name+ Optional, class name that the object type should be equal to # * +class_name+ - Optional, class name that the object type should be equal to.
# #
# ==== Example # ==== Example
# # Serialize a preferences attribute # # Serialize a preferences attribute
@ -1757,7 +1761,7 @@ module ActiveRecord #:nodoc:
# class Article < ActiveRecord::Base # class Article < ActiveRecord::Base
# def self.find_with_scope # def self.find_with_scope
# with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do # with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do
# with_scope(:find => { :limit => 10}) # with_scope(:find => { :limit => 10 })
# find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10 # find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
# end # end
# with_scope(:find => { :conditions => "author_id = 3" }) # with_scope(:find => { :conditions => "author_id = 3" })
@ -2238,40 +2242,53 @@ module ActiveRecord #:nodoc:
save! save!
end end
# Initializes the +attribute+ to zero if nil and adds the value passed as +by+ (default is one). Only makes sense for number-based attributes. Returns self. # Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
# The increment is performed directly on the underlying attribute, no setter is invoked.
# Only makes sense for number-based attributes. Returns +self+.
def increment(attribute, by = 1) def increment(attribute, by = 1)
self[attribute] ||= 0 self[attribute] ||= 0
self[attribute] += by self[attribute] += by
self self
end end
# Increments the +attribute+ and saves the record. # Wrapper around +increment+ that saves the record. This method differs from
# Note: Updates made with this method aren't subjected to validation checks # its non-bang version in that it passes through the attribute setter.
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def increment!(attribute, by = 1) def increment!(attribute, by = 1)
increment(attribute, by).update_attribute(attribute, self[attribute]) increment(attribute, by).update_attribute(attribute, self[attribute])
end end
# Initializes the +attribute+ to zero if nil and subtracts the value passed as +by+ (default is one). Only makes sense for number-based attributes. Returns self. # Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
# The decrement is performed directly on the underlying attribute, no setter is invoked.
# Only makes sense for number-based attributes. Returns +self+.
def decrement(attribute, by = 1) def decrement(attribute, by = 1)
self[attribute] ||= 0 self[attribute] ||= 0
self[attribute] -= by self[attribute] -= by
self self
end end
# Decrements the +attribute+ and saves the record. # Wrapper around +decrement+ that saves the record. This method differs from
# Note: Updates made with this method aren't subjected to validation checks # its non-bang version in that it passes through the attribute setter.
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def decrement!(attribute, by = 1) def decrement!(attribute, by = 1)
decrement(attribute, by).update_attribute(attribute, self[attribute]) decrement(attribute, by).update_attribute(attribute, self[attribute])
end end
# Turns an +attribute+ that's currently true into false and vice versa. Returns self. # Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
# if the predicate returns +true+ the attribute will become +false+. This
# method toggles directly the underlying value without calling any setter.
# Returns +self+.
def toggle(attribute) def toggle(attribute)
self[attribute] = !send("#{attribute}?") self[attribute] = !send("#{attribute}?")
self self
end end
# Toggles the +attribute+ and saves the record. # Wrapper around +toggle+ that saves the record. This method differs from
# Note: Updates made with this method aren't subjected to validation checks # its non-bang version in that it passes through the attribute setter.
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def toggle!(attribute) def toggle!(attribute)
toggle(attribute).update_attribute(attribute, self[attribute]) toggle(attribute).update_attribute(attribute, self[attribute])
end end

View file

@ -44,6 +44,12 @@ module ActiveRecord
@query_cache_enabled = old @query_cache_enabled = old
end end
# Clears the query cache.
#
# One reason you may wish to call this method explicitly is between queries
# that ask the database to randomize results. Otherwise the cache would see
# the same SQL query and repeatedly return the same result each time, silently
# undermining the randomness you were expecting.
def clear_query_cache def clear_query_cache
@query_cache.clear if @query_cache @query_cache.clear if @query_cache
end end

View file

@ -73,7 +73,7 @@ module ActiveRecord
# REFERENTIAL INTEGRITY ==================================== # REFERENTIAL INTEGRITY ====================================
# Override to turn off referential integrity while executing +&block+ # Override to turn off referential integrity while executing <tt>&block</tt>.
def disable_referential_integrity(&block) def disable_referential_integrity(&block)
yield yield
end end
@ -101,7 +101,7 @@ module ActiveRecord
false false
end end
# Lazily verify this connection, calling +active?+ only if it hasn't # Lazily verify this connection, calling <tt>active?</tt> only if it hasn't
# been called for +timeout+ seconds. # been called for +timeout+ seconds.
def verify!(timeout) def verify!(timeout)
now = Time.now.to_i now = Time.now.to_i

View file

@ -146,19 +146,19 @@ module ActiveRecord
# #
# Options: # Options:
# #
# * <tt>:host</tt> -- Defaults to localhost # * <tt>:host</tt> - Defaults to "localhost".
# * <tt>:port</tt> -- Defaults to 3306 # * <tt>:port</tt> - Defaults to 3306.
# * <tt>:socket</tt> -- Defaults to /tmp/mysql.sock # * <tt>:socket</tt> - Defaults to "/tmp/mysql.sock".
# * <tt>:username</tt> -- Defaults to root # * <tt>:username</tt> - Defaults to "root"
# * <tt>:password</tt> -- Defaults to nothing # * <tt>:password</tt> - Defaults to nothing.
# * <tt>:database</tt> -- The name of the database. No default, must be provided. # * <tt>:database</tt> - The name of the database. No default, must be provided.
# * <tt>:encoding</tt> -- (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection # * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
# * <tt>:sslkey</tt> -- Necessary to use MySQL with an SSL connection # * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
# * <tt>:sslcert</tt> -- Necessary to use MySQL with an SSL connection # * <tt>:sslcert</tt> - Necessary to use MySQL with an SSL connection.
# * <tt>:sslcapath</tt> -- Necessary to use MySQL with an SSL connection # * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
# * <tt>:sslcipher</tt> -- Necessary to use MySQL with an SSL connection # * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
# #
# By default, the MysqlAdapter will consider all columns of type tinyint(1) # By default, the MysqlAdapter will consider all columns of type <tt>tinyint(1)</tt>
# as boolean. If you wish to disable this emulation (which was the default # as boolean. If you wish to disable this emulation (which was the default
# behavior in versions 0.13.1 and earlier) you can add the following line # behavior in versions 0.13.1 and earlier) you can add the following line
# to your environment.rb file: # to your environment.rb file:

View file

@ -228,15 +228,15 @@ module ActiveRecord
# #
# Options: # Options:
# #
# * <tt>:host</tt> -- Defaults to localhost # * <tt>:host</tt> - Defaults to "localhost".
# * <tt>:port</tt> -- Defaults to 5432 # * <tt>:port</tt> - Defaults to 5432.
# * <tt>:username</tt> -- Defaults to nothing # * <tt>:username</tt> - Defaults to nothing.
# * <tt>:password</tt> -- Defaults to nothing # * <tt>:password</tt> - Defaults to nothing.
# * <tt>:database</tt> -- The name of the database. No default, must be provided. # * <tt>:database</tt> - The name of the database. No default, must be provided.
# * <tt>:schema_search_path</tt> -- An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the <tt>:schema_order</tt> option. # * <tt>:schema_search_path</tt> - An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the <tt>:schema_order</tt> option.
# * <tt>:encoding</tt> -- An optional client encoding that is used in a SET client_encoding TO <encoding> call on the connection. # * <tt>:encoding</tt> - An optional client encoding that is used in a <tt>SET client_encoding TO <encoding></tt> call on the connection.
# * <tt>:min_messages</tt> -- An optional client min messages that is used in a SET client_min_messages TO <min_messages> call on the connection. # * <tt>:min_messages</tt> - An optional client min messages that is used in a <tt>SET client_min_messages TO <min_messages></tt> call on the connection.
# * <tt>:allow_concurrency</tt> -- If true, use async query methods so Ruby threads don't deadlock; otherwise, use blocking query methods. # * <tt>:allow_concurrency</tt> - If true, use async query methods so Ruby threads don't deadlock; otherwise, use blocking query methods.
class PostgreSQLAdapter < AbstractAdapter class PostgreSQLAdapter < AbstractAdapter
# Returns 'PostgreSQL' as adapter name for identification purposes. # Returns 'PostgreSQL' as adapter name for identification purposes.
def adapter_name def adapter_name

View file

@ -70,7 +70,7 @@ module ActiveRecord
# #
# Options: # Options:
# #
# * <tt>:database</tt> -- Path to the database file. # * <tt>:database</tt> - Path to the database file.
class SQLiteAdapter < AbstractAdapter class SQLiteAdapter < AbstractAdapter
def adapter_name #:nodoc: def adapter_name #:nodoc:
'SQLite' 'SQLite'

View file

@ -426,7 +426,7 @@ end
# == Support for YAML defaults # == Support for YAML defaults
# #
# You probably already know how to use YAML to set and reuse defaults in # You probably already know how to use YAML to set and reuse defaults in
# your +database.yml+ file,. You can use the same technique in your fixtures: # your <tt>database.yml</tt> file. You can use the same technique in your fixtures:
# #
# DEFAULTS: &DEFAULTS # DEFAULTS: &DEFAULTS
# created_on: <%= 3.weeks.ago.to_s(:db) %> # created_on: <%= 3.weeks.ago.to_s(:db) %>

View file

@ -153,6 +153,17 @@ module ActiveRecord
end end
end end
# Returns the AssociationReflection object specified in the <tt>:through</tt> option
# of a HasManyThrough or HasOneThrough association. Example:
#
# class Post < ActiveRecord::Base
# has_many :taggings
# has_many :tags, :through => :taggings
# end
#
# tags_reflection = Post.reflect_on_association(:tags)
# taggings_reflection = tags_reflection.through_reflection
#
def through_reflection def through_reflection
@through_reflection ||= options[:through] ? active_record.reflect_on_association(options[:through]) : false @through_reflection ||= options[:through] ? active_record.reflect_on_association(options[:through]) : false
end end
@ -168,7 +179,8 @@ module ActiveRecord
# Gets the source of the through reflection. It checks both a singularized and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>. # Gets the source of the through reflection. It checks both a singularized and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>.
# (The <tt>:tags</tt> association on Tagging below.) # (The <tt>:tags</tt> association on Tagging below.)
# #
# class Post # class Post < ActiveRecord::Base
# has_many :taggings
# has_many :tags, :through => :taggings # has_many :tags, :through => :taggings
# end # end
# #

View file

@ -678,7 +678,7 @@ module ActiveRecord
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+). # * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+). # * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
# * <tt>:with</tt> - The regular expression used to validate the format with (note: must be supplied!). # * <tt>:with</tt> - The regular expression used to validate the format with (note: must be supplied!).
# * <tt>:on</tt> Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>). # * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value. # method, proc or string should return or evaluate to a true or false value.
@ -784,7 +784,7 @@ module ActiveRecord
# #
# Configuration options: # Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "is invalid") # * <tt>:message</tt> - A custom error message (default is: "is invalid")
# * <tt>:on</tt> Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>) # * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
# method, proc or string should return or evaluate to a true or false value. # method, proc or string should return or evaluate to a true or false value.
@ -802,8 +802,8 @@ module ActiveRecord
end end
# Validates whether the value of the specified attribute is numeric by trying to convert it to # Validates whether the value of the specified attribute is numeric by trying to convert it to
# a float with Kernel.Float (if <tt>integer</tt> is false) or applying it to the regular expression # a float with Kernel.Float (if <tt>only_integer</tt> is false) or applying it to the regular expression
# <tt>/\A[\+\-]?\d+\Z/</tt> (if <tt>integer</tt> is set to true). # <tt>/\A[\+\-]?\d+\Z/</tt> (if <tt>only_integer</tt> is set to true).
# #
# class Person < ActiveRecord::Base # class Person < ActiveRecord::Base
# validates_numericality_of :value, :on => :create # validates_numericality_of :value, :on => :create

View file

@ -14,12 +14,19 @@ module ActiveResource
# Person maps to the resources people, very similarly to Active Record) and a +site+ value, which holds the # Person maps to the resources people, very similarly to Active Record) and a +site+ value, which holds the
# URI of the resources. # URI of the resources.
# #
# class Person < ActiveResource::Base # class Person < ActiveResource::Base
# self.site = "http://api.people.com:3000/" # self.site = "http://api.people.com:3000/"
# end # end
# #
# Now the Person class is mapped to RESTful resources located at <tt>http://api.people.com:3000/people/</tt>, and # Now the Person class is mapped to RESTful resources located at <tt>http://api.people.com:3000/people/</tt>, and
# you can now use Active Resource's lifecycles methods to manipulate resources. # you can now use Active Resource's lifecycles methods to manipulate resources. In the case where you already have
# an existing model with the same name as the desired RESTful resource you can set the +element_name+ value.
#
# class PersonResource < ActiveResource::Base
# self.site = "http://api.people.com:3000/"
# self.element_name = "person"
# end
#
# #
# == Lifecycle methods # == Lifecycle methods
# #
@ -72,13 +79,13 @@ module ActiveResource
# #
# You can validate resources client side by overriding validation methods in the base class. # You can validate resources client side by overriding validation methods in the base class.
# #
# class Person < ActiveResource::Base # class Person < ActiveResource::Base
# self.site = "http://api.people.com:3000/" # self.site = "http://api.people.com:3000/"
# protected # protected
# def validate # def validate
# errors.add("last", "has invalid characters") unless last =~ /[a-zA-Z]*/ # errors.add("last", "has invalid characters") unless last =~ /[a-zA-Z]*/
# end # end
# end # end
# #
# See the ActiveResource::Validations documentation for more information. # See the ActiveResource::Validations documentation for more information.
# #
@ -118,18 +125,17 @@ module ActiveResource
# exception. # exception.
# #
# # GET http://api.people.com:3000/people/999.xml # # GET http://api.people.com:3000/people/999.xml
# ryan = Person.find(999) # => Raises ActiveResource::ResourceNotFound # ryan = Person.find(999) # 404, raises ActiveResource::ResourceNotFound
# # => Response = 404
# #
# <tt>404</tt> is just one of the HTTP error response codes that ActiveResource will handle with its own exception. The # <tt>404</tt> is just one of the HTTP error response codes that ActiveResource will handle with its own exception. The
# following HTTP response codes will also result in these exceptions: # following HTTP response codes will also result in these exceptions:
# #
# 200 - 399:: Valid response, no exception # * 200..399 - Valid response, no exception
# 404:: ActiveResource::ResourceNotFound # * 404 - ActiveResource::ResourceNotFound
# 409:: ActiveResource::ResourceConflict # * 409 - ActiveResource::ResourceConflict
# 422:: ActiveResource::ResourceInvalid (rescued by save as validation errors) # * 422 - ActiveResource::ResourceInvalid (rescued by save as validation errors)
# 401 - 499:: ActiveResource::ClientError # * 401..499 - ActiveResource::ClientError
# 500 - 599:: ActiveResource::ServerError # * 500..599 - ActiveResource::ServerError
# #
# These custom exceptions allow you to deal with resource errors more naturally and with more precision # These custom exceptions allow you to deal with resource errors more naturally and with more precision
# rather than returning a general HTTP error. For example: # rather than returning a general HTTP error. For example:
@ -177,12 +183,15 @@ module ActiveResource
# self.timeout = 5 # self.timeout = 5
# end # end
# #
# This sets the +timeout+ to 5 seconds. You can adjust the timeout to a value suitable for the RESTful API # This sets the +timeout+ to 5 seconds. You can adjust the +timeout+ to a value suitable for the RESTful API
# you are accessing. It is recommended to set this to a reasonably low value to allow your Active Resource # you are accessing. It is recommended to set this to a reasonably low value to allow your Active Resource
# clients (especially if you are using Active Resource in a Rails application) to fail-fast (see # clients (especially if you are using Active Resource in a Rails application) to fail-fast (see
# http://en.wikipedia.org/wiki/Fail-fast) rather than cause cascading failures that could incapacitate your # http://en.wikipedia.org/wiki/Fail-fast) rather than cause cascading failures that could incapacitate your
# server. # server.
# #
# When a timeout occurs, an ActiveResource::TimeoutError is raised. You should rescue from
# ActiveResource::TimeoutError in your Active Resource method calls.
#
# Internally, Active Resource relies on Ruby's Net::HTTP library to make HTTP requests. Setting +timeout+ # Internally, Active Resource relies on Ruby's Net::HTTP library to make HTTP requests. Setting +timeout+
# sets the <tt>read_timeout</tt> of the internal Net::HTTP instance to the same value. The default # sets the <tt>read_timeout</tt> of the internal Net::HTTP instance to the same value. The default
# <tt>read_timeout</tt> is 60 seconds on most Ruby implementations. # <tt>read_timeout</tt> is 60 seconds on most Ruby implementations.
@ -229,7 +238,7 @@ module ActiveResource
end end
end end
# Gets the user for REST HTTP authentication # Gets the user for REST HTTP authentication.
def user def user
# Not using superclass_delegating_reader. See +site+ for explanation # Not using superclass_delegating_reader. See +site+ for explanation
if defined?(@user) if defined?(@user)
@ -239,13 +248,13 @@ module ActiveResource
end end
end end
# Sets the user for REST HTTP authentication # Sets the user for REST HTTP authentication.
def user=(user) def user=(user)
@connection = nil @connection = nil
@user = user @user = user
end end
# Gets the password for REST HTTP authentication # Gets the password for REST HTTP authentication.
def password def password
# Not using superclass_delegating_reader. See +site+ for explanation # Not using superclass_delegating_reader. See +site+ for explanation
if defined?(@password) if defined?(@password)
@ -255,13 +264,13 @@ module ActiveResource
end end
end end
# Sets the password for REST HTTP authentication # Sets the password for REST HTTP authentication.
def password=(password) def password=(password)
@connection = nil @connection = nil
@password = password @password = password
end end
# Sets the format that attributes are sent and received in from a mime type reference. Example: # Sets the format that attributes are sent and received in from a mime type reference:
# #
# Person.format = :json # Person.format = :json
# Person.find(1) # => GET /people/1.json # Person.find(1) # => GET /people/1.json
@ -269,7 +278,7 @@ module ActiveResource
# Person.format = ActiveResource::Formats::XmlFormat # Person.format = ActiveResource::Formats::XmlFormat
# Person.find(1) # => GET /people/1.xml # Person.find(1) # => GET /people/1.xml
# #
# Default format is :xml. # Default format is <tt>:xml</tt>.
def format=(mime_type_reference_or_format) def format=(mime_type_reference_or_format)
format = mime_type_reference_or_format.is_a?(Symbol) ? format = mime_type_reference_or_format.is_a?(Symbol) ?
ActiveResource::Formats[mime_type_reference_or_format] : mime_type_reference_or_format ActiveResource::Formats[mime_type_reference_or_format] : mime_type_reference_or_format
@ -278,7 +287,7 @@ module ActiveResource
connection.format = format if site connection.format = format if site
end end
# Returns the current format, default is ActiveResource::Formats::XmlFormat # Returns the current format, default is ActiveResource::Formats::XmlFormat.
def format # :nodoc: def format # :nodoc:
read_inheritable_attribute("format") || ActiveResource::Formats[:xml] read_inheritable_attribute("format") || ActiveResource::Formats[:xml]
end end
@ -367,9 +376,9 @@ module ActiveResource
# will split from the prefix options. # will split from the prefix options.
# #
# ==== Options # ==== Options
# +prefix_options+:: A hash to add a prefix to the request for nested URL's (e.g., <tt>:account_id => 19</tt> # +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
# would yield a URL like <tt>/accounts/19/purchases.xml</tt>). # would yield a URL like <tt>/accounts/19/purchases.xml</tt>).
# +query_options+:: A hash to add items to the query string for the request. # +query_options+ - A hash to add items to the query string for the request.
# #
# ==== Examples # ==== Examples
# Post.element_path(1) # Post.element_path(1)
@ -393,9 +402,9 @@ module ActiveResource
# will split from the +prefix_options+. # will split from the +prefix_options+.
# #
# ==== Options # ==== Options
# +prefix_options+:: A hash to add a prefix to the request for nested URL's (e.g., <tt>:account_id => 19</tt> # * +prefix_options+ - A hash to add a prefix to the request for nested URL's (e.g., <tt>:account_id => 19</tt>
# would yield a URL like <tt>/accounts/19/purchases.xml</tt>). # would yield a URL like <tt>/accounts/19/purchases.xml</tt>).
# +query_options+:: A hash to add items to the query string for the request. # * +query_options+ - A hash to add items to the query string for the request.
# #
# ==== Examples # ==== Examples
# Post.collection_path # Post.collection_path
@ -431,40 +440,34 @@ module ActiveResource
# ==== Examples # ==== Examples
# Person.create(:name => 'Jeremy', :email => 'myname@nospam.com', :enabled => true) # Person.create(:name => 'Jeremy', :email => 'myname@nospam.com', :enabled => true)
# my_person = Person.find(:first) # my_person = Person.find(:first)
# my_person.email # my_person.email # => myname@nospam.com
# # => myname@nospam.com
# #
# dhh = Person.create(:name => 'David', :email => 'dhh@nospam.com', :enabled => true) # dhh = Person.create(:name => 'David', :email => 'dhh@nospam.com', :enabled => true)
# dhh.valid? # dhh.valid? # => true
# # => true # dhh.new? # => false
# dhh.new?
# # => false
# #
# # We'll assume that there's a validation that requires the name attribute # # We'll assume that there's a validation that requires the name attribute
# that_guy = Person.create(:name => '', :email => 'thatguy@nospam.com', :enabled => true) # that_guy = Person.create(:name => '', :email => 'thatguy@nospam.com', :enabled => true)
# that_guy.valid? # that_guy.valid? # => false
# # => false # that_guy.new? # => true
# that_guy.new?
# # => true
#
def create(attributes = {}) def create(attributes = {})
returning(self.new(attributes)) { |res| res.save } returning(self.new(attributes)) { |res| res.save }
end end
# Core method for finding resources. Used similarly to Active Record's find method. # Core method for finding resources. Used similarly to Active Record's +find+ method.
# #
# ==== Arguments # ==== Arguments
# The first argument is considered to be the scope of the query. That is, how many # The first argument is considered to be the scope of the query. That is, how many
# resources are returned from the request. It can be one of the following. # resources are returned from the request. It can be one of the following.
# #
# * <tt>:one</tt>: Returns a single resource. # * <tt>:one</tt> - Returns a single resource.
# * <tt>:first</tt>: Returns the first resource found. # * <tt>:first</tt> - Returns the first resource found.
# * <tt>:all</tt>: Returns every resource that matches the request. # * <tt>:all</tt> - Returns every resource that matches the request.
# #
# ==== Options # ==== Options
# #
# * +from+: Sets the path or custom method that resources will be fetched from. # * <tt>:from</tt> - Sets the path or custom method that resources will be fetched from.
# * +params+: Sets query and prefix (nested URL) parameters. # * <tt>:params</tt> - Sets query and prefix (nested URL) parameters.
# #
# ==== Examples # ==== Examples
# Person.find(1) # Person.find(1)
@ -511,19 +514,14 @@ module ActiveResource
# All options specify prefix and query parameters. # All options specify prefix and query parameters.
# #
# ==== Examples # ==== Examples
# Event.delete(2) # Event.delete(2) # sends DELETE /events/2
# # => DELETE /events/2
# #
# Event.create(:name => 'Free Concert', :location => 'Community Center') # Event.create(:name => 'Free Concert', :location => 'Community Center')
# my_event = Event.find(:first) # my_event = Event.find(:first) # let's assume this is event with ID 7
# # => Events (id: 7) # Event.delete(my_event.id) # sends DELETE /events/7
# Event.delete(my_event.id)
# # => DELETE /events/7
# #
# # Let's assume a request to events/5/cancel.xml # # Let's assume a request to events/5/cancel.xml
# Event.delete(params[:id]) # Event.delete(params[:id]) # sends DELETE /events/5
# # => DELETE /events/5
#
def delete(id, options = {}) def delete(id, options = {})
connection.delete(element_path(id, options)) connection.delete(element_path(id, options))
end end
@ -532,11 +530,9 @@ module ActiveResource
# #
# ==== Examples # ==== Examples
# Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...') # Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...')
# Note.exists?(1) # Note.exists?(1) # => true
# # => true
# #
# Note.exists(1349) # Note.exists(1349) # => false
# # => false
def exists?(id, options = {}) def exists?(id, options = {})
if id if id
prefix_options, query_options = split_options(options[:params]) prefix_options, query_options = split_options(options[:params])
@ -626,7 +622,7 @@ module ActiveResource
attr_accessor :attributes #:nodoc: attr_accessor :attributes #:nodoc:
attr_accessor :prefix_options #:nodoc: attr_accessor :prefix_options #:nodoc:
# Constructor method for new resources; the optional +attributes+ parameter takes a +Hash+ # Constructor method for new resources; the optional +attributes+ parameter takes a hash
# of attributes for the new resource. # of attributes for the new resource.
# #
# ==== Examples # ==== Examples
@ -643,27 +639,26 @@ module ActiveResource
load(attributes) load(attributes)
end end
# Returns a clone of the resource that hasn't been assigned an id yet and # Returns a clone of the resource that hasn't been assigned an +id+ yet and
# is treated as a new resource. # is treated as a new resource.
# #
# ryan = Person.find(1) # ryan = Person.find(1)
# not_ryan = ryan.clone # not_ryan = ryan.clone
# not_ryan.new? # => true # not_ryan.new? # => true
# #
# Any active resource member attributes will NOT be cloned, though all other # Any active resource member attributes will NOT be cloned, though all other
# attributes are. This is to prevent the conflict between any prefix_options # attributes are. This is to prevent the conflict between any +prefix_options+
# that refer to the original parent resource and the newly cloned parent # that refer to the original parent resource and the newly cloned parent
# resource that does not exist. # resource that does not exist.
# #
# ryan = Person.find(1) # ryan = Person.find(1)
# ryan.address = StreetAddress.find(1, :person_id => ryan.id) # ryan.address = StreetAddress.find(1, :person_id => ryan.id)
# ryan.hash = {:not => "an ARes instance"} # ryan.hash = {:not => "an ARes instance"}
# #
# not_ryan = ryan.clone # not_ryan = ryan.clone
# not_ryan.new? # => true # not_ryan.new? # => true
# not_ryan.address # => NoMethodError # not_ryan.address # => NoMethodError
# not_ryan.hash # => {:not => "an ARes instance"} # not_ryan.hash # => {:not => "an ARes instance"}
#
def clone def clone
# Clone all attributes except the pk and any nested ARes # Clone all attributes except the pk and any nested ARes
cloned = attributes.reject {|k,v| k == self.class.primary_key || v.is_a?(ActiveResource::Base)}.inject({}) do |attrs, (k, v)| cloned = attributes.reject {|k,v| k == self.class.primary_key || v.is_a?(ActiveResource::Base)}.inject({}) do |attrs, (k, v)|
@ -684,16 +679,13 @@ module ActiveResource
# #
# ==== Examples # ==== Examples
# not_new = Computer.create(:brand => 'Apple', :make => 'MacBook', :vendor => 'MacMall') # not_new = Computer.create(:brand => 'Apple', :make => 'MacBook', :vendor => 'MacMall')
# not_new.new? # not_new.new? # => false
# # => false
# #
# is_new = Computer.new(:brand => 'IBM', :make => 'Thinkpad', :vendor => 'IBM') # is_new = Computer.new(:brand => 'IBM', :make => 'Thinkpad', :vendor => 'IBM')
# is_new.new? # is_new.new? # => true
# # => true
# #
# is_new.save # is_new.save
# is_new.new? # is_new.new? # => false
# # => false
# #
def new? def new?
id.nil? id.nil?
@ -715,7 +707,7 @@ module ActiveResource
end end
# Test for equality. Resource are equal if and only if +other+ is the same object or # Test for equality. Resource are equal if and only if +other+ is the same object or
# is an instance of the same class, is not +new?+, and has the same +id+. # is an instance of the same class, is not <tt>new?</tt>, and has the same +id+.
# #
# ==== Examples # ==== Examples
# ryan = Person.create(:name => 'Ryan') # ryan = Person.create(:name => 'Ryan')
@ -756,17 +748,13 @@ module ActiveResource
# ==== Examples # ==== Examples
# my_invoice = Invoice.create(:customer => 'That Company') # my_invoice = Invoice.create(:customer => 'That Company')
# next_invoice = my_invoice.dup # next_invoice = my_invoice.dup
# next_invoice.new? # next_invoice.new? # => true
# # => true
# #
# next_invoice.save # next_invoice.save
# next_invoice == my_invoice # next_invoice == my_invoice # => false (different id attributes)
# # => false (different id attributes)
# #
# my_invoice.customer # my_invoice.customer # => That Company
# # => That Company # next_invoice.customer # => That Company
# next_invoice.customer
# # => That Company
def dup def dup
returning self.class.new do |resource| returning self.class.new do |resource|
resource.attributes = @attributes resource.attributes = @attributes
@ -781,16 +769,12 @@ module ActiveResource
# #
# ==== Examples # ==== Examples
# my_company = Company.new(:name => 'RoleModel Software', :owner => 'Ken Auer', :size => 2) # my_company = Company.new(:name => 'RoleModel Software', :owner => 'Ken Auer', :size => 2)
# my_company.new? # my_company.new? # => true
# # => true # my_company.save # sends POST /companies/ (create)
# my_company.save
# # => POST /companies/ (create)
# #
# my_company.new? # my_company.new? # => false
# # => false
# my_company.size = 10 # my_company.size = 10
# my_company.save # my_company.save # sends PUT /companies/1 (update)
# # => PUT /companies/1 (update)
def save def save
new? ? create : update new? ? create : update
end end
@ -801,20 +785,17 @@ module ActiveResource
# my_id = 3 # my_id = 3
# my_person = Person.find(my_id) # my_person = Person.find(my_id)
# my_person.destroy # my_person.destroy
# Person.find(my_id) # Person.find(my_id) # 404 (Resource Not Found)
# # => 404 (Resource Not Found)
# #
# new_person = Person.create(:name => 'James') # new_person = Person.create(:name => 'James')
# new_id = new_person.id # new_id = new_person.id # => 7
# # => 7
# new_person.destroy # new_person.destroy
# Person.find(new_id) # Person.find(new_id) # 404 (Resource Not Found)
# # => 404 (Resource Not Found)
def destroy def destroy
connection.delete(element_path, self.class.headers) connection.delete(element_path, self.class.headers)
end end
# Evaluates to <tt>true</tt> if this resource is not +new?+ and is # Evaluates to <tt>true</tt> if this resource is not <tt>new?</tt> and is
# found on the remote service. Using this method, you can check for # found on the remote service. Using this method, you can check for
# resources that may have been deleted between the object's instantiation # resources that may have been deleted between the object's instantiation
# and actions on it. # and actions on it.
@ -822,17 +803,14 @@ module ActiveResource
# ==== Examples # ==== Examples
# Person.create(:name => 'Theodore Roosevelt') # Person.create(:name => 'Theodore Roosevelt')
# that_guy = Person.find(:first) # that_guy = Person.find(:first)
# that_guy.exists? # that_guy.exists? # => true
# # => true
# #
# that_lady = Person.new(:name => 'Paul Bean') # that_lady = Person.new(:name => 'Paul Bean')
# that_lady.exists? # that_lady.exists? # => false
# # => false
# #
# guys_id = that_guy.id # guys_id = that_guy.id
# Person.delete(guys_id) # Person.delete(guys_id)
# that_guy.exists? # that_guy.exists? # => false
# # => false
def exists? def exists?
!new? && self.class.exists?(to_param, :params => prefix_options) !new? && self.class.exists?(to_param, :params => prefix_options)
end end
@ -844,11 +822,11 @@ module ActiveResource
# attribute, so it has the same options as the +to_xml+ methods in # attribute, so it has the same options as the +to_xml+ methods in
# ActiveSupport. # ActiveSupport.
# #
# indent:: Set the indent level for the XML output (default is +2+). # * <tt>:indent</tt> - Set the indent level for the XML output (default is +2+).
# dasherize:: Boolean option to determine whether or not element names should # * <tt>:dasherize</tt> - Boolean option to determine whether or not element names should
# replace underscores with dashes (default is <tt>false</tt>). # replace underscores with dashes (default is <tt>false</tt>).
# skip_instruct:: Toggle skipping the +instruct!+ call on the XML builder # * <tt>:skip_instruct</tt> - Toggle skipping the +instruct!+ call on the XML builder
# that generates the XML declaration (default is <tt>false</tt>). # that generates the XML declaration (default is <tt>false</tt>).
# #
# ==== Examples # ==== Examples
# my_group = SubsidiaryGroup.find(:first) # my_group = SubsidiaryGroup.find(:first)
@ -870,30 +848,26 @@ module ActiveResource
# #
# ==== Examples # ==== Examples
# my_branch = Branch.find(:first) # my_branch = Branch.find(:first)
# my_branch.name # my_branch.name # => "Wislon Raod"
# # => Wislon Raod
# #
# # Another client fixes the typo... # # Another client fixes the typo...
# #
# my_branch.name # my_branch.name # => "Wislon Raod"
# # => Wislon Raod
# my_branch.reload # my_branch.reload
# my_branch.name # my_branch.name # => "Wilson Road"
# # => Wilson Road
def reload def reload
self.load(self.class.find(to_param, :params => @prefix_options).attributes) self.load(self.class.find(to_param, :params => @prefix_options).attributes)
end end
# A method to manually load attributes from a hash. Recursively loads collections of # A method to manually load attributes from a hash. Recursively loads collections of
# resources. This method is called in initialize and create when a +Hash+ of attributes # resources. This method is called in +initialize+ and +create+ when a hash of attributes
# is provided. # is provided.
# #
# ==== Examples # ==== Examples
# my_attrs = {:name => 'J&J Textiles', :industry => 'Cloth and textiles'} # my_attrs = {:name => 'J&J Textiles', :industry => 'Cloth and textiles'}
# #
# the_supplier = Supplier.find(:first) # the_supplier = Supplier.find(:first)
# the_supplier.name # the_supplier.name # => 'J&M Textiles'
# # => 'J&M Textiles'
# the_supplier.load(my_attrs) # the_supplier.load(my_attrs)
# the_supplier.name('J&J Textiles') # the_supplier.name('J&J Textiles')
# #
@ -924,10 +898,10 @@ module ActiveResource
self self
end end
# For checking respond_to? without searching the attributes (which is faster). # For checking <tt>respond_to?</tt> without searching the attributes (which is faster).
alias_method :respond_to_without_attributes?, :respond_to? alias_method :respond_to_without_attributes?, :respond_to?
# A method to determine if an object responds to a message (e.g., a method call). In Active Resource, a +Person+ object with a # A method to determine if an object responds to a message (e.g., a method call). In Active Resource, a Person object with a
# +name+ attribute can answer <tt>true</tt> to <tt>my_person.respond_to?("name")</tt>, <tt>my_person.respond_to?("name=")</tt>, and # +name+ attribute can answer <tt>true</tt> to <tt>my_person.respond_to?("name")</tt>, <tt>my_person.respond_to?("name=")</tt>, and
# <tt>my_person.respond_to?("name?")</tt>. # <tt>my_person.respond_to?("name?")</tt>.
def respond_to?(method, include_priv = false) def respond_to?(method, include_priv = false)

View file

@ -23,10 +23,7 @@ class HashWithIndifferentAccess < Hash
alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
alias_method :regular_update, :update unless method_defined?(:regular_update) alias_method :regular_update, :update unless method_defined?(:regular_update)
# # Assigns a new value to the hash:
# Assigns a new value to the hash.
#
# Example:
# #
# hash = HashWithIndifferentAccess.new # hash = HashWithIndifferentAccess.new
# hash[:key] = "value" # hash[:key] = "value"
@ -35,25 +32,15 @@ class HashWithIndifferentAccess < Hash
regular_writer(convert_key(key), convert_value(value)) regular_writer(convert_key(key), convert_value(value))
end end
# Updates the instantized hash with values from the second:
# #
# Updates the instantized hash with values from the second. # hash_1 = HashWithIndifferentAccess.new
# hash_1[:key] = "value"
# #
# Example: # hash_2 = HashWithIndifferentAccess.new
# hash_2[:key] = "New Value!"
# #
# >> hash_1 = HashWithIndifferentAccess.new # hash_1.update(hash_2) # => {"key"=>"New Value!"}
# => {}
#
# >> hash_1[:key] = "value"
# => "value"
#
# >> hash_2 = HashWithIndifferentAccess.new
# => {}
#
# >> hash_2[:key] = "New Value!"
# => "New Value!"
#
# >> hash_1.update(hash_2)
# => {"key"=>"New Value!"}
# #
def update(other_hash) def update(other_hash)
other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
@ -62,7 +49,13 @@ class HashWithIndifferentAccess < Hash
alias_method :merge!, :update alias_method :merge!, :update
# Checks the hash for a key matching the argument passed in # Checks the hash for a key matching the argument passed in:
#
# hash = HashWithIndifferentAccess.new
# hash["key"] = "value"
# hash.key? :key # => true
# hash.key? "key" # => true
#
def key?(key) def key?(key)
super(convert_key(key)) super(convert_key(key))
end end
@ -76,7 +69,13 @@ class HashWithIndifferentAccess < Hash
super(convert_key(key), *extras) super(convert_key(key), *extras)
end end
# Returns an array of the values at the specified indicies. # Returns an array of the values at the specified indices:
#
# hash = HashWithIndifferentAccess.new
# hash[:a] = "x"
# hash[:b] = "y"
# hash.values_at("a", "b") # => ["x", "y"]
#
def values_at(*indices) def values_at(*indices)
indices.collect {|key| self[convert_key(key)]} indices.collect {|key| self[convert_key(key)]}
end end

View file

@ -3,6 +3,11 @@ require 'singleton'
# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without, # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
# in inflections.rb. # in inflections.rb.
#
# The Rails core team has stated patches for the inflections library will not be accepted
# in order to avoid breaking legacy applications which may be relying on errant inflections.
# If you discover an incorrect inflection and require it for your application, you'll need
# to correct it yourself (explained below).
module Inflector module Inflector
# A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
# inflection rules. Examples: # inflection rules. Examples:

View file

@ -7,4 +7,9 @@ class ApplicationController < ActionController::Base
# See ActionController::RequestForgeryProtection for details # See ActionController::RequestForgeryProtection for details
# Uncomment the :secret if you're not using the cookie session store # Uncomment the :secret if you're not using the cookie session store
protect_from_forgery # :secret => '<%= app_secret %>' protect_from_forgery # :secret => '<%= app_secret %>'
# See ActionController::Base for details
# Uncomment this to filter the contents of submitted sensitive data parameters
# from your application log (in this case, all fields with names like "password").
# filter_parameter_logging :password
end end

View file

@ -572,11 +572,13 @@ module Rails
attr_accessor :plugin_loader attr_accessor :plugin_loader
# Enables or disables plugin reloading. You can get around this setting per plugin. # Enables or disables plugin reloading. You can get around this setting per plugin.
# If <tt>reload_plugins?</tt> is false, add this to your plugin's init.rb to make it reloadable: # If <tt>reload_plugins?</tt> is false, add this to your plugin's <tt>init.rb</tt>
# to make it reloadable:
# #
# Dependencies.load_once_paths.delete lib_path # Dependencies.load_once_paths.delete lib_path
# #
# If <tt>reload_plugins?</tt> is true, add this to your plugin's init.rb to only load it once: # If <tt>reload_plugins?</tt> is true, add this to your plugin's <tt>init.rb</tt>
# to only load it once:
# #
# Dependencies.load_once_paths << lib_path # Dependencies.load_once_paths << lib_path
# #
@ -676,7 +678,7 @@ module Rails
YAML::load(ERB.new(IO.read(database_configuration_file)).result) YAML::load(ERB.new(IO.read(database_configuration_file)).result)
end end
# The path to the current environment's file (development.rb, etc.). By # The path to the current environment's file (<tt>development.rb</tt>, etc.). By
# default the file is at <tt>config/environments/#{environment}.rb</tt>. # default the file is at <tt>config/environments/#{environment}.rb</tt>.
def environment_path def environment_path
"#{root_path}/config/environments/#{environment}.rb" "#{root_path}/config/environments/#{environment}.rb"

View file

@ -1,14 +1,14 @@
module Rails module Rails
# The Plugin class should be an object which provides the following methods: # The Plugin class should be an object which provides the following methods:
# #
# * +name+ - used during initialisation to order the plugin (based on name and # * +name+ - Used during initialisation to order the plugin (based on name and
# the contents of <tt>config.plugins</tt>) # the contents of <tt>config.plugins</tt>).
# * +valid?+ - returns true if this plugin can be loaded # * +valid?+ - Returns true if this plugin can be loaded.
# * +load_paths+ - each path within the returned array will be added to the $LOAD_PATH # * +load_paths+ - Each path within the returned array will be added to the <tt>$LOAD_PATH</tt>.
# * +load+ - finally 'load' the plugin. # * +load+ - Finally 'load' the plugin.
# #
# These methods are expected by the Rails::Plugin::Locator and Rails::Plugin::Loader classes. # These methods are expected by the Rails::Plugin::Locator and Rails::Plugin::Loader classes.
# The default implementation returns the <tt>lib</tt> directory as its </tt>load_paths</tt>, # The default implementation returns the <tt>lib</tt> directory as its <tt>load_paths</tt>,
# and evaluates <tt>init.rb</tt> when <tt>load</tt> is called. # and evaluates <tt>init.rb</tt> when <tt>load</tt> is called.
# #
# You can also inspect the about.yml data programmatically: # You can also inspect the about.yml data programmatically:
@ -31,13 +31,13 @@ module Rails
File.directory?(directory) && (has_lib_directory? || has_init_file?) File.directory?(directory) && (has_lib_directory? || has_init_file?)
end end
# Returns a list of paths this plugin wishes to make available in $LOAD_PATH # Returns a list of paths this plugin wishes to make available in <tt>$LOAD_PATH</tt>.
def load_paths def load_paths
report_nonexistant_or_empty_plugin! unless valid? report_nonexistant_or_empty_plugin! unless valid?
has_lib_directory? ? [lib_path] : [] has_lib_directory? ? [lib_path] : []
end end
# Evaluates a plugin's init.rb file # Evaluates a plugin's init.rb file.
def load(initializer) def load(initializer)
return if loaded? return if loaded?
report_nonexistant_or_empty_plugin! unless valid? report_nonexistant_or_empty_plugin! unless valid?