aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2008-07-28 12:26:59 +0100
committerPratik Naik <pratiknaik@gmail.com>2008-07-28 12:33:24 +0100
commit6e754551254a8cc64e034163f5d0dc155b450388 (patch)
treee697e85d8699654f04a790e5dc323c7007e87e31 /activerecord/lib/active_record
parent10d9fe4bf3110c1d5de0c6b509fe0cbb9d5eda1d (diff)
downloadrails-6e754551254a8cc64e034163f5d0dc155b450388.tar.gz
rails-6e754551254a8cc64e034163f5d0dc155b450388.tar.bz2
rails-6e754551254a8cc64e034163f5d0dc155b450388.zip
Merge docrails changes
Diffstat (limited to 'activerecord/lib/active_record')
-rwxr-xr-xactiverecord/lib/active_record/associations.rb418
-rwxr-xr-xactiverecord/lib/active_record/base.rb29
-rw-r--r--activerecord/lib/active_record/transactions.rb9
3 files changed, 317 insertions, 139 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index d916275ab9..4e33dfe69f 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -73,6 +73,7 @@ module ActiveRecord
end
end
+ # See ActiveRecord::Associations::ClassMethods for documentation.
module Associations # :nodoc:
def self.included(base)
base.extend(ClassMethods)
@@ -150,6 +151,7 @@ module ActiveRecord
# #others.destroy_all | X | X | X
# #others.find(*args) | X | X | X
# #others.find_first | X | |
+ # #others.exist? | X | X | X
# #others.uniq | X | X | X
# #others.reset | X | X | X
#
@@ -612,31 +614,53 @@ module ActiveRecord
# All of the association macros can be specialized through options. This makes cases more complex than the simple and guessable ones
# possible.
module ClassMethods
- # 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
- # <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.
+ # Specifies a one-to-many association. The following methods for retrieval and query of
+ # collections of associated objects will be added:
+ #
+ # [collection(force_reload = false)]
+ # Returns an array of all the associated objects.
# 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.delete(object, ...)</tt> - Removes one or more objects from the collection by setting their foreign keys to +NULL+.
+ # [collection<<(object, ...)]
+ # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
+ # [collection.delete(object, ...)]
+ # 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.
- # * <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=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
- # 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+.
- # * <tt>collection.empty?</tt> - Returns +true+ if there are no 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.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
- # 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
- # 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+!
+ # [collection=objects]
+ # Replaces the collections content by deleting and adding objects as appropriate.
+ # [collection_singular_ids]
+ # Returns an array of the associated objects' ids
+ # [collection_singular_ids=ids]
+ # Replace the collection with the objects identified by the primary keys in +ids+
+ # [collection.clear]
+ # 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>, otherwise sets their foreign keys to +NULL+.
+ # [collection.empty?]
+ # Returns +true+ if there are no associated objects.
+ # [collection.size]
+ # Returns the number of associated objects.
+ # [collection.find(...)]
+ # Finds an associated object according to the same rules as ActiveRecord::Base.find.
+ # [collection.exist?(...)]
+ # Checks whether an associated object with the given conditions exists.
+ # Uses the same rules as ActiveRecord::Base.exists?.
+ # [collection.build(attributes = {}, ...)]
+ # 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. <b>Note:</b> This only works if an associated object already exists, not if
+ # it's +nil+!
+ # [collection.create(attributes = {})]
+ # 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). <b>Note:</b> This only works if an associated
+ # object already exists, not if it's +nil+!
+ #
+ # (*Note*: +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>.)
+ #
+ # === Example
#
- # Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
+ # 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>
# * <tt>Firm#clients.delete</tt>
@@ -647,54 +671,77 @@ module ActiveRecord
# * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
# * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
# * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>)
+ # * <tt>Firm#clients.exist?(:name => 'ACME')</tt> (similar to <tt>Client.exist?(:name => 'ACME', :firm_id => firm.id)</tt>)
# * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
# * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
# The declaration can also include an options hash to specialize the behavior of the association.
#
- # Options are:
- # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
+ # === Supported options
+ # [:class_name]
+ # 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
# 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+
+ # [:conditions]
+ # 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
# 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>.
- # * <tt>:order</tt> - Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
+ # [:order]
+ # 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>.
- # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
+ # [:foreign_key]
+ # 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"
# as the default <tt>:foreign_key</tt>.
- # * <tt>:primary_key</tt> - Specify the method that returns the primary key used for the association. By default this is +id+.
- # * <tt>:dependent</tt> - If set to <tt>:destroy</tt> all the associated objects are destroyed
+ # [:primary_key]
+ # Specify the method that returns the primary key used for the association. By default this is +id+.
+ # [:dependent]
+ # 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
# 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
# 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
+ # [:finder_sql]
+ # 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.
- # * <tt>:counter_sql</tt> - Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
+ # [:counter_sql]
+ # 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>.
- # * <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>: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>: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
+ # [:extend]
+ # Specify a named module for extending the proxy. See "Association extensions".
+ # [:include]
+ # Specify second-order associations that should be eager loaded when the collection is loaded.
+ # [:group]
+ # An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
+ # [:limit]
+ # An integer determining the limit on the number of rows that should be returned.
+ # [:offset]
+ # An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.
+ # [:select]
+ # 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. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
- # * <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>
+ # [:as]
+ # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
+ # [:through]
+ # 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>
# 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
+ # [:source]
+ # 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
# <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
+ # [:source_type]
+ # Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
# association is a polymorphic +belongs_to+.
- # * <tt>:uniq</tt> - If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
- # * <tt>:readonly</tt> - If true, all the associated objects are readonly through the association.
- # * <tt>:validate</tt> - If false, don't validate the associated objects when saving the parent object. true by default.
- # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
- #
+ # [:uniq]
+ # If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
+ # [:readonly]
+ # If true, all the associated objects are readonly through the association.
+ # [:validate]
+ # If false, don't validate the associated objects when saving the parent object. true by default.
+ # [:accessible]
+ # Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
+
# Option examples:
# has_many :comments, :order => "posted_on"
# has_many :comments, :include => :author
@@ -725,58 +772,91 @@ module ActiveRecord
end
end
- # 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
- # <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=(associate)</tt> - Assigns the associate object, extracts the primary key, sets it as the foreign key,
+ # Specifies a one-to-one association with another class. This method should only be used
+ # if the other class contains the foreign key. If the current class contains the foreign key,
+ # then you should use +belongs_to+ instead. See also ActiveRecord::Associations::ClassMethods's overview
+ # on when to use has_one and when to use belongs_to.
+ #
+ # The following methods for retrieval and query of a single associated object will be added:
+ #
+ # [association(force_reload = false)]
+ # Returns the associated object. +nil+ is returned if none is found.
+ # [association=(associate)]
+ # Assigns the associate object, extracts the primary key, sets it as the foreign key,
# and saves the associate 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
- # 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+.
- # * <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).
+ # [association.nil?]
+ # Returns +true+ if there is no associated object.
+ # [build_association(attributes = {})]
+ # 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. <b>Note:</b> This ONLY works if an association already exists.
+ # It will NOT work if the association is +nil+.
+ # [create_association(attributes = {})]
+ # 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).
+ #
+ # (+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>.)
#
- # 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:
# * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}")</tt>)
# * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
# * <tt>Account#beneficiary.nil?</tt>
# * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
#
+ # === Options
+ #
# The declaration can also include an options hash to specialize the behavior of the association.
#
# Options are:
- # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
+ # [:class_name]
+ # 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
# 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+
+ # [:conditions]
+ # 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>.
- # * <tt>:order</tt> - Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
+ # [:order]
+ # 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>.
- # * <tt>:dependent</tt> - If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
+ # [:dependent]
+ # 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
# 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
+ # [:foreign_key]
+ # 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"
# as the default <tt>:foreign_key</tt>.
- # * <tt>:primary_key</tt> - Specify the method that returns the primary key used for the association. By default this is +id+.
- # * <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>: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
+ # [:primary_key]
+ # Specify the method that returns the primary key used for the association. By default this is +id+.
+ # [:include]
+ # Specify second-order associations that should be eager loaded when this object is loaded.
+ # [:as]
+ # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
+ # [:select]
+ # 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. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
- # * <tt>:through</tt>: Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt>
+ # [:through]
+ # 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>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
+ # [:source]
+ # 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
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
- # * <tt>:source_type</tt> - Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
+ # [:source_type]
+ # Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
# association is a polymorphic +belongs_to+.
- # * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
- # * <tt>:validate</tt> - If false, don't validate the associated object when saving the parent object. +false+ by default.
- # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
+ # [:readonly]
+ # If true, the associated object is readonly through the association.
+ # [:validate]
+ # If false, don't validate the associated object when saving the parent object. +false+ by default.
+ # [:accessible]
+ # Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# has_one :credit_card, :dependent => :destroy # destroys the associated credit card
@@ -816,18 +896,34 @@ module ActiveRecord
end
end
- # 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
- # <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=(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>build_association(attributes = {})</tt> - Returns a new object of the associated type that has been instantiated
+ # Specifies a one-to-one association with another class. This method should only be used
+ # if this class contains the foreign key. If the other class contains the foreign key,
+ # then you should use +has_one+ instead. See also ActiveRecord::Associations::ClassMethods's overview
+ # on when to use +has_one+ and when to use +belongs_to+.
+ #
+ # Methods will be added for retrieval and query for a single associated object, for which
+ # this object holds an id:
+ #
+ # [association(force_reload = false)]
+ # Returns the associated object. +nil+ is returned if none is found.
+ # [association=(associate)]
+ # Assigns the associate object, extracts the primary key, and sets it as the foreign key.
+ # [association.nil?]
+ # Returns +true+ if there is no associated object.
+ # [build_association(attributes = {})]
+ # 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.
- # * <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).
+ # [create_association(attributes = {})]
+ # 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).
+ #
+ # (+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>.)
#
- # 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:
# * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
# * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
# * <tt>Post#author?</tt> (similar to <tt>post.author == some_author</tt>)
@@ -836,23 +932,30 @@ module ActiveRecord
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
# The declaration can also include an options hash to specialize the behavior of the association.
#
- # Options are:
- # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
+ # === Options
+ #
+ # [:class_name]
+ # 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
# 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+
+ # [:conditions]
+ # 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>.
- # * <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
+ # [:select]
+ # 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. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
- # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
+ # [:foreign_key]
+ # 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 <tt>belongs_to :person</tt> association will use
# "person_id" as the default <tt>:foreign_key</tt>. Similarly, <tt>belongs_to :favorite_person, :class_name => "Person"</tt>
# 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
+ # [:dependent]
+ # 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>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.
- # * <tt>:counter_cache</tt> - Caches the number of belonging objects on the associate class through the use of +increment_counter+
+ # [:counter_cache]
+ # 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
# 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
@@ -860,13 +963,18 @@ module ActiveRecord
# 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.
# 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>:polymorphic</tt> - Specify this association is a polymorphic association by passing +true+.
+ # [:include]
+ # Specify second-order associations that should be eager loaded when this object is loaded.
+ # [:polymorphic]
+ # 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
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
- # * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
- # * <tt>:validate</tt> - If false, don't validate the associated objects when saving the parent object. +false+ by default.
- # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
+ # [:readonly]
+ # If true, the associated object is readonly through the association.
+ # [:validate]
+ # If false, don't validate the associated objects when saving the parent object. +false+ by default.
+ # [:accessible]
+ # Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# belongs_to :firm, :foreign_key => "client_of"
@@ -952,8 +1060,9 @@ module ActiveRecord
configure_dependency_for_belongs_to(reflection)
end
- # 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
+ # Specifies a many-to-many relationship with another class. This 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
# 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 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
@@ -968,28 +1077,48 @@ module ActiveRecord
# associations with attributes to a real join model (see introduction).
#
# Adds the following methods for retrieval and query:
- # +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>collection(force_reload = false)</tt> - Returns an array of all the associated objects.
+ #
+ # [collection(force_reload = false)]
+ # Returns an array of all the associated objects.
# 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
+ # [collection<<(object, ...)]
+ # 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.delete(object, ...)</tt> - Removes one or more objects from the collection by removing their associations from the join table.
+ # [collection.delete(object, ...)]
+ # Removes one or more objects from the collection by removing their associations from the join table.
# This does not destroy the objects.
- # * <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=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.empty?</tt> - Returns +true+ if there are no 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
+ # [collection=objects]
+ # Replaces the collection's content by deleting and adding objects as appropriate.
+ # [collection_singular_ids]
+ # Returns an array of the associated objects' ids.
+ # [collection_singular_ids=ids]
+ # Replace the collection by the objects identified by the primary keys in +ids+.
+ # [collection.clear]
+ # Removes every object from the collection. This does not destroy the objects.
+ # [collection.empty?]
+ # Returns +true+ if there are no associated objects.
+ # [collection.size]
+ # Returns the number of associated objects.
+ # [collection.find(id)]
+ # Finds an associated object responding to the +id+ and that
# 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
+ # Uses the same rules as ActiveRecord::Base.find.
+ # [collection.exist?(...)]
+ # Checks whether an associated object with the given conditions exists.
+ # Uses the same rules as ActiveRecord::Base.exists?.
+ # [collection.build(attributes = {})]
+ # 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.
- # * <tt>collection.create(attributes = {})</tt> - Returns a new object of the collection type that has been instantiated
+ # [collection.create(attributes = {})]
+ # 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).
#
- # Example: A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
+ # (+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>.)
+ #
+ # === Example
+ #
+ # A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
# * <tt>Developer#projects</tt>
# * <tt>Developer#projects<<</tt>
# * <tt>Developer#projects.delete</tt>
@@ -1000,45 +1129,66 @@ module ActiveRecord
# * <tt>Developer#projects.empty?</tt>
# * <tt>Developer#projects.size</tt>
# * <tt>Developer#projects.find(id)</tt>
+ # * <tt>Developer#clients.exist?(...)</tt>
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>)
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>)
# The declaration may include an options hash to specialize the behavior of the association.
#
- # Options are:
- # * <tt>:class_name</tt> - Specify the class name of the association. Use it only if that name can't be inferred
+ # === Options
+ #
+ # [:class_name]
+ # 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
# 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.
- # 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.
- # * <tt>:foreign_key</tt> - Specify the foreign key used for the association. By default this is guessed to be the name
+ # [:join_table]
+ # Specify the name of the join table if the default based on lexical order isn't what you want.
+ # <b>WARNING:</b> 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.
+ # [:foreign_key]
+ # 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
# 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
+ # [:association_foreign_key]
+ # 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,
# 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+
+ # [:conditions]
+ # 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.
# <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</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,
+ # [:order]
+ # 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>
- # * <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>:delete_sql</tt> - Overwrite the default generated SQL statement used to remove links between the associated
+ # [:uniq]
+ # If true, duplicate associated objects will be ignored by accessors and query methods.
+ # [:finder_sql]
+ # Overwrite the default generated SQL statement used to fetch the association with a manual statement
+ # [:delete_sql]
+ # Overwrite the default generated SQL statement used to remove links between the associated
# classes with a manual statement.
- # * <tt>:insert_sql</tt> - Overwrite the default generated SQL statement used to add links between the associated classes
+ # [:insert_sql]
+ # Overwrite the default generated SQL statement used to add links between the associated classes
# with a manual statement.
- # * <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>: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>: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
+ # [:extend]
+ # Anonymous module for extending the proxy, see "Association extensions".
+ # [:include]
+ # Specify second-order associations that should be eager loaded when the collection is loaded.
+ # [:group]
+ # An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
+ # [:limit]
+ # An integer determining the limit on the number of rows that should be returned.
+ # [:offset]
+ # An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.
+ # [:select]
+ # 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. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
- # * <tt>:readonly</tt> - If true, all the associated objects are readonly through the association.
- # * <tt>:validate</tt> - If false, don't validate the associated objects when saving the parent object. +true+ by default.
- # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
+ # [:readonly]
+ # If true, all the associated objects are readonly through the association.
+ # [:validate]
+ # If false, don't validate the associated objects when saving the parent object. +true+ by default.
+ # [:accessible<]
+ # Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# has_and_belongs_to_many :projects
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 4f5d72a0be..9cb64223e2 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -83,8 +83,33 @@ module ActiveRecord #:nodoc:
class ReadOnlyRecord < ActiveRecordError
end
- # Used by Active Record transaction mechanism to distinguish rollback from other exceptional situations.
- # You can use it to roll your transaction back explicitly in the block passed to +transaction+ method.
+ # ActiveRecord::Transactions::ClassMethods.transaction uses this exception
+ # to distinguish a deliberate rollback from other exceptional situations.
+ # Normally, raising an exception will cause the +transaction+ method to rollback
+ # the database transaction *and* pass on the exception. But if you raise an
+ # ActiveRecord::Rollback exception, then the database transaction will be rolled back,
+ # without passing on the exception.
+ #
+ # For example, you could do this in your controller to rollback a transaction:
+ #
+ # class BooksController < ActionController::Base
+ # def create
+ # Book.transaction do
+ # book = Book.new(params[:book])
+ # book.save!
+ # if today_is_friday?
+ # # The system must fail on Friday so that our support department
+ # # won't be out of job. We silently rollback this transaction
+ # # without telling the user.
+ # raise ActiveRecord::Rollback, "Call tech support!"
+ # end
+ # end
+ # # ActiveRecord::Rollback is the only exception that won't be passed on
+ # # by ActiveRecord::Base.transaction, so this line will still be reached
+ # # even on Friday.
+ # redirect_to root_url
+ # end
+ # end
class Rollback < ActiveRecordError
end
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 354a6c83a2..0531afbb52 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -66,12 +66,15 @@ module ActiveRecord
# will happen under the protected cover of a transaction. So you can use validations to check for values that the transaction
# depends on or you can raise exceptions in the callbacks to rollback.
#
- # == Exception handling
+ # == Exception handling and rolling back
#
# Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you
- # should be ready to catch those in your application code. One exception is the ActiveRecord::Rollback exception, which will
- # trigger a ROLLBACK when raised, but not be re-raised by the transaction block.
+ # should be ready to catch those in your application code.
+ #
+ # One exception is the ActiveRecord::Rollback exception, which will trigger a ROLLBACK when raised,
+ # but not be re-raised by the transaction block.
module ClassMethods
+ # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
def transaction(&block)
connection.increment_open_transactions