diff options
author | Hongli Lai (Phusion) <hongli@phusion.nl> | 2008-07-19 12:05:16 +0200 |
---|---|---|
committer | Hongli Lai (Phusion) <hongli@phusion.nl> | 2008-07-19 12:05:16 +0200 |
commit | 038c7fdeea33d7aabc918b29304a262b663e3604 (patch) | |
tree | b2853b94e45763daa69640d5a1217ef8bcb19714 | |
parent | 4d719c185ac17d30c624add296872111570bf5b6 (diff) | |
download | rails-038c7fdeea33d7aabc918b29304a262b663e3604.tar.gz rails-038c7fdeea33d7aabc918b29304a262b663e3604.tar.bz2 rails-038c7fdeea33d7aabc918b29304a262b663e3604.zip |
Improve readability of other ActiveRecord association methods' documentation.
-rwxr-xr-x | activerecord/lib/active_record/associations.rb | 279 |
1 files changed, 190 insertions, 89 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 53ca17511e..a0d3c2b5bf 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) @@ -639,19 +640,19 @@ module ActiveRecord # [collection.size] # Returns the number of associated objects. # [collection.find(...)] - # Finds an associated object according to the same rules as Base.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 Base.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. *Note:* This only works if an associated object already exists, not if + # 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). *Note:* This only works if an associated + # 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 @@ -769,57 +770,89 @@ 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. + # [: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. # # Option examples: # has_one :credit_card, :dependent => :destroy # destroys the associated credit card @@ -859,18 +892,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). # - # Example: A Post class declares <tt>belongs_to :author</tt>, which will add: + # (+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: # * <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>) @@ -879,23 +928,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 @@ -903,12 +959,16 @@ 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. + # [: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. # # Option examples: # belongs_to :firm, :foreign_key => "client_of" @@ -994,8 +1054,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 @@ -1010,28 +1071,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> @@ -1042,44 +1123,64 @@ 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. + # [: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. # # Option examples: # has_and_belongs_to_many :projects |