aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/association_basics.textile
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source/association_basics.textile')
-rw-r--r--guides/source/association_basics.textile615
1 files changed, 311 insertions, 304 deletions
diff --git a/guides/source/association_basics.textile b/guides/source/association_basics.textile
index 8ddc56bef1..151752eee9 100644
--- a/guides/source/association_basics.textile
+++ b/guides/source/association_basics.textile
@@ -88,6 +88,8 @@ end
!images/belongs_to.png(belongs_to Association Diagram)!
+NOTE: +belongs_to+ associations _must_ use the singular term. If you used the pluralized form in the above example for the +customer+ association in the +Order+ model, you would be told that there was an "uninitialized constant Order::Customers". This is because Rails automatically infers the class name from the association name. If the association name is wrongly pluralized, then the inferred class will be wrongly pluralized too.
+
h4. The +has_one+ Association
A +has_one+ association also sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model. For example, if each supplier in your application has only one account, you'd declare the supplier model like this:
@@ -630,12 +632,12 @@ The <tt>create_<em>association</em></tt> method returns a new object of the asso
h5. Options for +belongs_to+
-While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the +belongs_to+ association reference. Such customizations can easily be accomplished by passing options when you create the association. For example, this assocation uses two such options:
+While Rails uses intelligent defaults that will work well in most situations, there may be times when you want to customize the behavior of the +belongs_to+ association reference. Such customizations can easily be accomplished by passing options and scope blocks when you create the association. For example, this assocation uses two such options:
<ruby>
class Order < ActiveRecord::Base
- belongs_to :customer, :counter_cache => true,
- :conditions => "active = 1"
+ belongs_to :customer, :dependent => :destroy,
+ :counter_cache => true
end
</ruby>
@@ -643,15 +645,11 @@ The +belongs_to+ association supports these options:
* +:autosave+
* +:class_name+
-* +:conditions+
* +:counter_cache+
* +:dependent+
* +:foreign_key+
-* +:include+
* +:inverse_of+
* +:polymorphic+
-* +:readonly+
-* +:select+
* +:touch+
* +:validate+
@@ -669,16 +667,6 @@ class Order < ActiveRecord::Base
end
</ruby>
-h6(#belongs_to-conditions). +:conditions+
-
-The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by an SQL +WHERE+ clause).
-
-<ruby>
-class Order < ActiveRecord::Base
- belongs_to :customer, :conditions => "active = 1"
-end
-</ruby>
-
h6(#belongs_to-counter_cache). +:counter_cache+
The +:counter_cache+ option can be used to make finding the number of belonging objects more efficient. Consider these models:
@@ -737,35 +725,31 @@ end
TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
-h6(#belongs_to-includes). +:include+
+h6(#belongs_to-inverse_of). +:inverse_of+
-You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
+The +:inverse_of+ option specifies the name of the +has_many+ or +has_one+ association that is the inverse of this association. Does not work in combination with the +:polymorphic+ options.
<ruby>
-class LineItem < ActiveRecord::Base
- belongs_to :order
+class Customer < ActiveRecord::Base
+ has_many :orders, :inverse_of => :customer
end
class Order < ActiveRecord::Base
- belongs_to :customer
- has_many :line_items
-end
-
-class Customer < ActiveRecord::Base
- has_many :orders
+ belongs_to :customer, :inverse_of => :orders
end
</ruby>
-If you frequently retrieve customers directly from line items (+@line_item.order.customer+), then you can make your code somewhat more efficient by including customers in the association from line items to orders:
+h6(#belongs_to-polymorphic). +:polymorphic+
-<ruby>
-class LineItem < ActiveRecord::Base
- belongs_to :order, :include => :customer
-end
+Passing +true+ to the +:polymorphic+ option indicates that this is a polymorphic association. Polymorphic associations were discussed in detail <a href="#polymorphic-associations">earlier in this guide</a>.
+
+h6(#belongs_to-touch). +:touch+
+
+If you set the +:touch+ option to +:true+, then the +updated_at+ or +updated_on+ timestamp on the associated object will be set to the current time whenever this object is saved or destroyed:
+<ruby>
class Order < ActiveRecord::Base
- belongs_to :customer
- has_many :line_items
+ belongs_to :customer, :touch => true
end
class Customer < ActiveRecord::Base
@@ -773,43 +757,58 @@ class Customer < ActiveRecord::Base
end
</ruby>
-NOTE: There's no need to use +:include+ for immediate associations - that is, if you have +Order belongs_to :customer+, then the customer is eager-loaded automatically when it's needed.
-
-h6(#belongs_to-inverse_of). +:inverse_of+
-
-The +:inverse_of+ option specifies the name of the +has_many+ or +has_one+ association that is the inverse of this association. Does not work in combination with the +:polymorphic+ options.
+In this case, saving or destroying an order will update the timestamp on the associated customer. You can also specify a particular timestamp attribute to update:
<ruby>
-class Customer < ActiveRecord::Base
- has_many :orders, :inverse_of => :customer
-end
-
class Order < ActiveRecord::Base
- belongs_to :customer, :inverse_of => :orders
+ belongs_to :customer, :touch => :orders_updated_at
end
</ruby>
-h6(#belongs_to-polymorphic). +:polymorphic+
+h6(#belongs_to-validate). +:validate+
-Passing +true+ to the +:polymorphic+ option indicates that this is a polymorphic association. Polymorphic associations were discussed in detail <a href="#polymorphic-associations">earlier in this guide</a>.
+If you set the +:validate+ option to +true+, then associated objects will be validated whenever you save this object. By default, this is +false+: associated objects will not be validated when this object is saved.
-h6(#belongs_to-readonly). +:readonly+
+h5(#belongs_to-scopes_for_belongs_to). Scopes for +belongs_to+
-If you set the +:readonly+ option to +true+, then the associated object will be read-only when retrieved via the association.
+There may be times when you wish to customize the query used by +belongs_to+. Such customizations can be achieved via a scope block. For example:
-h6(#belongs_to-select). +:select+
+<ruby>
+class Order < ActiveRecord::Base
+ belongs_to :customer, -> { where :active => true },
+ :dependent => :destroy
+end
+</ruby>
-The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.
+You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
-TIP: If you set the +:select+ option on a +belongs_to+ association, you should also set the +foreign_key+ option to guarantee the correct results.
+* +where+
+* +includes+
+* +readonly+
+* +select+
-h6(#belongs_to-touch). +:touch+
+h6(#belongs_to-where). +where+
-If you set the +:touch+ option to +:true+, then the +updated_at+ or +updated_on+ timestamp on the associated object will be set to the current time whenever this object is saved or destroyed:
+The +where+ method lets you specify the conditions that the associated object must meet.
<ruby>
class Order < ActiveRecord::Base
- belongs_to :customer, :touch => true
+ belongs_to :customer, -> { where :active => true }
+end
+</ruby>
+
+h6(#belongs_to-includes). +includes+
+
+You can use the +includes+ method let you specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
+
+<ruby>
+class LineItem < ActiveRecord::Base
+ belongs_to :order
+end
+
+class Order < ActiveRecord::Base
+ belongs_to :customer
+ has_many :line_items
end
class Customer < ActiveRecord::Base
@@ -817,17 +816,34 @@ class Customer < ActiveRecord::Base
end
</ruby>
-In this case, saving or destroying an order will update the timestamp on the associated customer. You can also specify a particular timestamp attribute to update:
+If you frequently retrieve customers directly from line items (+@line_item.order.customer+), then you can make your code somewhat more efficient by including customers in the association from line items to orders:
<ruby>
+class LineItem < ActiveRecord::Base
+ belongs_to :order, -> { includes :customer }
+end
+
class Order < ActiveRecord::Base
- belongs_to :customer, :touch => :orders_updated_at
+ belongs_to :customer
+ has_many :line_items
+end
+
+class Customer < ActiveRecord::Base
+ has_many :orders
end
</ruby>
-h6(#belongs_to-validate). +:validate+
+NOTE: There's no need to use +includes+ for immediate associations - that is, if you have +Order belongs_to :customer+, then the customer is eager-loaded automatically when it's needed.
-If you set the +:validate+ option to +true+, then associated objects will be validated whenever you save this object. By default, this is +false+: associated objects will not be validated when this object is saved.
+h6(#belongs_to-readonly). +readonly+
+
+If you use +readonly+, then the associated object will be read-only when retrieved via the association.
+
+h6(#belongs_to-select). +select+
+
+The +select+ method lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.
+
+TIP: If you use the +select+ method on a +belongs_to+ association, you should also set the +:foreign_key+ option to guarantee the correct results.
h5(#belongs_to-do_any_associated_objects_exist). Do Any Associated Objects Exist?
@@ -924,15 +940,10 @@ The +has_one+ association supports these options:
* +:as+
* +:autosave+
* +:class_name+
-* +:conditions+
* +:dependent+
* +:foreign_key+
-* +:include+
* +:inverse_of+
-* +:order+
* +:primary_key+
-* +:readonly+
-* +:select+
* +:source+
* +:source_type+
* +:through+
@@ -956,22 +967,15 @@ class Supplier < ActiveRecord::Base
end
</ruby>
-h6(#has_one-conditions). +:conditions+
-
-The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by an SQL +WHERE+ clause).
-
-<ruby>
-class Supplier < ActiveRecord::Base
- has_one :account, :conditions => "confirmed = 1"
-end
-</ruby>
-
h6(#has_one-dependent). +:dependent+
-If you set the +:dependent+ option to +:destroy+, then deleting this object will call the +destroy+ method on the associated object to delete that object. If you set the +:dependent+ option to +:delete+, then deleting this object will delete the associated object _without_ calling its +destroy+ method. If you set the +:dependent+ option to +:nullify+, then deleting this object will set the foreign key in the association object to +NULL+.
-If you set the +:dependent+ option to +:restrict+, then the deletion of the object is restricted if a dependent associated object exist and a +DeleteRestrictionError+ exception is raised.
+Controls what happens to the associated object when its owner is destroyed:
-NOTE: The default behavior for +:dependent => :restrict+ is to raise a +DeleteRestrictionError+ when associated objects exist. Since Rails 4.0 this behavior is being deprecated in favor of adding an error to the base model. To silence the warning in Rails 4.0, you should fix your code to not expect this Exception and add +config.active_record.dependent_restrict_raises = false+ to your application config.
+* +:destroy+ causes the associated object to also be destroyed
+* +:delete+ causes the asssociated object to be deleted directly from the database (so callbacks will not execute)
+* +:nullify+ causes the foreign key to be set to +NULL+. Callbacks are not executed.
+* +:restrict_with_exception+ causes an exception to be raised if there is an associated record
+* +:restrict_with_error+ causes an error to be added to the owner if there is an associated object
h6(#has_one-foreign_key). +:foreign_key+
@@ -985,30 +989,74 @@ end
TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
-h6(#has_one-include). +:include+
+h6(#has_one-inverse_of). +:inverse_of+
-You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
+The +:inverse_of+ option specifies the name of the +belongs_to+ association that is the inverse of this association. Does not work in combination with the +:through+ or +:as+ options.
<ruby>
class Supplier < ActiveRecord::Base
- has_one :account
+ has_one :account, :inverse_of => :supplier
end
class Account < ActiveRecord::Base
- belongs_to :supplier
- belongs_to :representative
+ belongs_to :supplier, :inverse_of => :account
end
+</ruby>
-class Representative < ActiveRecord::Base
- has_many :accounts
+h6(#has_one-primary_key). +:primary_key+
+
+By convention, Rails assumes that the column used to hold the primary key of this model is +id+. You can override this and explicitly specify the primary key with the +:primary_key+ option.
+
+h6(#has_one-source). +:source+
+
+The +:source+ option specifies the source association name for a +has_one :through+ association.
+
+h6(#has_one-source_type). +:source_type+
+
+The +:source_type+ option specifies the source association type for a +has_one :through+ association that proceeds through a polymorphic association.
+
+h6(#has_one-through). +:through+
+
+The +:through+ option specifies a join model through which to perform the query. +has_one :through+ associations were discussed in detail <a href="#the-has_one-through-association">earlier in this guide</a>.
+
+h6(#has_one-validate). +:validate+
+
+If you set the +:validate+ option to +true+, then associated objects will be validated whenever you save this object. By default, this is +false+: associated objects will not be validated when this object is saved.
+
+h5(#belongs_to-scopes_for_has_one). Scopes for +has_one+
+
+There may be times when you wish to customize the query used by +has_one+. Such customizations can be achieved via a scope block. For example:
+
+<ruby>
+class Supplier < ActiveRecord::Base
+ has_one :account, -> { where :active => true }
end
</ruby>
-If you frequently retrieve representatives directly from suppliers (+@supplier.account.representative+), then you can make your code somewhat more efficient by including representatives in the association from suppliers to accounts:
+You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
+
+* +where+
+* +includes+
+* +readonly+
+* +select+
+
+h6(#has_one-where). +where+
+
+The +where+ method lets you specify the conditions that the associated object must meet.
+
+<ruby>
+class Supplier < ActiveRecord::Base
+ has_one :account, -> { where "confirmed = 1" }
+end
+</ruby>
+
+h6(#has_one-includes). +includes+
+
+You can use the +includes+ method to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
<ruby>
class Supplier < ActiveRecord::Base
- has_one :account, :include => :representative
+ has_one :account
end
class Account < ActiveRecord::Base
@@ -1021,51 +1069,30 @@ class Representative < ActiveRecord::Base
end
</ruby>
-h6(#has_one-inverse_of). +:inverse_of+
-
-The +:inverse_of+ option specifies the name of the +belongs_to+ association that is the inverse of this association. Does not work in combination with the +:through+ or +:as+ options.
+If you frequently retrieve representatives directly from suppliers (+@supplier.account.representative+), then you can make your code somewhat more efficient by including representatives in the association from suppliers to accounts:
<ruby>
class Supplier < ActiveRecord::Base
- has_one :account, :inverse_of => :supplier
+ has_one :account, -> { includes :representative }
end
class Account < ActiveRecord::Base
- belongs_to :supplier, :inverse_of => :account
+ belongs_to :supplier
+ belongs_to :representative
end
-</ruby>
-
-h6(#has_one-order). +:order+
-
-The +:order+ option dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause). Because a +has_one+ association will only retrieve a single associated object, this option should not be needed.
-
-h6(#has_one-primary_key). +:primary_key+
-
-By convention, Rails assumes that the column used to hold the primary key of this model is +id+. You can override this and explicitly specify the primary key with the +:primary_key+ option.
-
-h6(#has_one-readonly). +:readonly+
-
-If you set the +:readonly+ option to +true+, then the associated object will be read-only when retrieved via the association.
-
-h6(#has_one-select). +:select+
-
-The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.
-h6(#has_one-source). +:source+
-
-The +:source+ option specifies the source association name for a +has_one :through+ association.
-
-h6(#has_one-source_type). +:source_type+
-
-The +:source_type+ option specifies the source association type for a +has_one :through+ association that proceeds through a polymorphic association.
+class Representative < ActiveRecord::Base
+ has_many :accounts
+end
+</ruby>
-h6(#has_one-through). +:through+
+h6(#has_one-readonly). +readonly+
-The +:through+ option specifies a join model through which to perform the query. +has_one :through+ associations were discussed in detail <a href="#the-has_one-through-association">earlier in this guide</a>.
+If you use the +readonly+ method, then the associated object will be read-only when retrieved via the association.
-h6(#has_one-validate). +:validate+
+h6(#has_one-select). +select+
-If you set the +:validate+ option to +true+, then associated objects will be validated whenever you save this object. By default, this is +false+: associated objects will not be validated when this object is saved.
+The +select+ method lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.
h5(#has_one-do_any_associated_objects_exist). Do Any Associated Objects Exist?
@@ -1256,25 +1283,13 @@ The +has_many+ association supports these options:
* +:as+
* +:autosave+
* +:class_name+
-* +:conditions+
-* +:counter_sql+
* +:dependent+
-* +:extend+
-* +:finder_sql+
* +:foreign_key+
-* +:group+
-* +:include+
* +:inverse_of+
-* +:limit+
-* +:offset+
-* +:order+
* +:primary_key+
-* +:readonly+
-* +:select+
* +:source+
* +:source_type+
* +:through+
-* +:uniq+
* +:validate+
h6(#has_many-as). +:as+
@@ -1295,85 +1310,127 @@ class Customer < ActiveRecord::Base
end
</ruby>
-h6(#has_many-conditions). +:conditions+
+h6(#has_many-dependent). +:dependent+
-The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by an SQL +WHERE+ clause).
+Controls what happens to the associated objects when their owner is destroyed:
-<ruby>
-class Customer < ActiveRecord::Base
- has_many :confirmed_orders, :class_name => "Order",
- :conditions => "confirmed = 1"
-end
-</ruby>
+* +:destroy+ causes all the associated objects to also be destroyed
+* +:delete_all+ causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute)
+* +:nullify+ causes the foreign keys to be set to +NULL+. Callbacks are not executed.
+* +:restrict_with_exception+ causes an exception to be raised if there are any associated records
+* +:restrict_with_error+ causes an error to be added to the owner if there are any associated objects
-You can also set conditions via a hash:
+NOTE: This option is ignored when you use the +:through+ option on the association.
+
+h6(#has_many-foreign_key). +:foreign_key+
+
+By convention, Rails assumes that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
<ruby>
class Customer < ActiveRecord::Base
- has_many :confirmed_orders, :class_name => "Order",
- :conditions => { :confirmed => true }
+ has_many :orders, :foreign_key => "cust_id"
end
</ruby>
-If you use a hash-style +:conditions+ option, then record creation via this association will be automatically scoped using the hash. In this case, using +@customer.confirmed_orders.create+ or +@customer.confirmed_orders.build+ will create orders where the confirmed column has the value +true+.
+TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
+
+h6(#has_many-inverse_of). +:inverse_of+
-If you need to evaluate conditions dynamically at runtime, use a proc:
+The +:inverse_of+ option specifies the name of the +belongs_to+ association that is the inverse of this association. Does not work in combination with the +:through+ or +:as+ options.
<ruby>
class Customer < ActiveRecord::Base
- has_many :latest_orders, :class_name => "Order",
- :conditions => proc { ["orders.created_at > ?", 10.hours.ago] }
+ has_many :orders, :inverse_of => :customer
+end
+
+class Order < ActiveRecord::Base
+ belongs_to :customer, :inverse_of => :orders
end
</ruby>
-h6(#has_many-counter_sql). +:counter_sql+
+h6(#has_many-primary_key). +:primary_key+
-Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself.
+By convention, Rails assumes that the column used to hold the primary key of the association is +id+. You can override this and explicitly specify the primary key with the +:primary_key+ option.
-NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting the +SELECT ... FROM+ clause of your +:finder_sql+ statement by +SELECT COUNT(*) FROM+.
+h6(#has_many-source). +:source+
-h6(#has_many-dependent). +:dependent+
+The +:source+ option specifies the source association name for a +has_many :through+ association. You only need to use this option if the name of the source association cannot be automatically inferred from the association name.
-If you set the +:dependent+ option to +:destroy+, then deleting this object will call the +destroy+ method on the associated objects to delete those objects. If you set the +:dependent+ option to +:delete_all+, then deleting this object will delete the associated objects _without_ calling their +destroy+ method. If you set the +:dependent+ option to +:nullify+, then deleting this object will set the foreign key in the associated objects to +NULL+.
-If you set the +:dependent+ option to +:restrict+, then the deletion of the object is restricted if a dependent associated object exist and a +DeleteRestrictionError+ exception is raised.
+h6(#has_many-source_type). +:source_type+
-NOTE: The default behavior for +:dependent => :restrict+ is to raise a +DeleteRestrictionError+ when associated objects exist. Since Rails 4.0 this behavior is being deprecated in favor of adding an error to the base model. To silence the warning in Rails 4.0, you should fix your code to not expect this Exception and add +config.active_record.dependent_restrict_raises = false+ to your application config.
+The +:source_type+ option specifies the source association type for a +has_many :through+ association that proceeds through a polymorphic association.
-NOTE: This option is ignored when you use the +:through+ option on the association.
+h6(#has_many-through). +:through+
-h6(#has_many-extend). +:extend+
+The +:through+ option specifies a join model through which to perform the query. +has_many :through+ associations provide a way to implement many-to-many relationships, as discussed <a href="#the-has_many-through-association">earlier in this guide</a>.
-The +:extend+ option specifies a named module to extend the association proxy. Association extensions are discussed in detail <a href="#association-extensions">later in this guide</a>.
+h6(#has_many-validate). +:validate+
-h6(#has_many-finder_sql). +:finder_sql+
+If you set the +:validate+ option to +false+, then associated objects will not be validated whenever you save this object. By default, this is +true+: associated objects will be validated when this object is saved.
-Normally Rails automatically generates the proper SQL to fetch the association members. With the +:finder_sql+ option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary.
+h5(#has_many-scopes_for_has_many). Scopes for +has_many+
-h6(#has_many-foreign_key). +:foreign_key+
+There may be times when you wish to customize the query used by +has_many+. Such customizations can be achieved via a scope block. For example:
-By convention, Rails assumes that the column used to hold the foreign key on the other model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
+<ruby>
+class Customer < ActiveRecord::Base
+ has_many :orders, -> { where :processed => true }
+end
+</ruby>
+
+You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
+
+* +where+
+* +extending+
+* +group+
+* +includes+
+* +limit+
+* +offset+
+* +order+
+* +readonly+
+* +select+
+* +uniq+
+
+h6(#has_many-where). +where+
+
+The +where+ method lets you specify the conditions that the associated object must meet.
<ruby>
class Customer < ActiveRecord::Base
- has_many :orders, :foreign_key => "cust_id"
+ has_many :confirmed_orders, -> { where "confirmed = 1" },
+ :class_name => "Order"
end
</ruby>
-TIP: In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.
+You can also set conditions via a hash:
+
+<ruby>
+class Customer < ActiveRecord::Base
+ has_many :confirmed_orders, -> { where :confirmed => true },
+ :class_name => "Order"
+end
+</ruby>
+
+If you use a hash-style +where+ option, then record creation via this association will be automatically scoped using the hash. In this case, using +@customer.confirmed_orders.create+ or +@customer.confirmed_orders.build+ will create orders where the confirmed column has the value +true+.
+
+h6(#has_many-extending). +extending+
-h6(#has_many-group). +:group+
+The +extending+ method specifies a named module to extend the association proxy. Association extensions are discussed in detail <a href="#association-extensions">later in this guide</a>.
-The +:group+ option supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL.
+h6(#has_many-group). +group+
+
+The +group+ method supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL.
<ruby>
class Customer < ActiveRecord::Base
- has_many :line_items, :through => :orders, :group => "orders.id"
+ has_many :line_items, -> { group 'orders.id' },
+ :through => :orders
end
</ruby>
-h6(#has_many-include). +:include+
+h6(#has_many-includes). +includes+
-You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
+You can use the +includes+ method to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:
<ruby>
class Customer < ActiveRecord::Base
@@ -1394,7 +1451,7 @@ If you frequently retrieve line items directly from customers (+@customer.orders
<ruby>
class Customer < ActiveRecord::Base
- has_many :orders, :include => :line_items
+ has_many :orders, -> { includes :line_items }
end
class Order < ActiveRecord::Base
@@ -1407,74 +1464,45 @@ class LineItem < ActiveRecord::Base
end
</ruby>
-h6(#has_many-inverse_of). +:inverse_of+
-
-The +:inverse_of+ option specifies the name of the +belongs_to+ association that is the inverse of this association. Does not work in combination with the +:through+ or +:as+ options.
-
-<ruby>
-class Customer < ActiveRecord::Base
- has_many :orders, :inverse_of => :customer
-end
-
-class Order < ActiveRecord::Base
- belongs_to :customer, :inverse_of => :orders
-end
-</ruby>
-
-h6(#has_many-limit). +:limit+
+h6(#has_many-limit). +limit+
-The +:limit+ option lets you restrict the total number of objects that will be fetched through an association.
+The +limit+ method lets you restrict the total number of objects that will be fetched through an association.
<ruby>
class Customer < ActiveRecord::Base
- has_many :recent_orders, :class_name => "Order",
- :order => "order_date DESC", :limit => 100
+ has_many :recent_orders,
+ -> { order('order_date desc').limit(100) },
+ :class_name => "Order",
end
</ruby>
-h6(#has_many-offset). +:offset+
+h6(#has_many-offset). +offset+
-The +:offset+ option lets you specify the starting offset for fetching objects via an association. For example, if you set +:offset => 11+, it will skip the first 11 records.
+The +offset+ method lets you specify the starting offset for fetching objects via an association. For example, +-> { offset(11) }+ will skip the first 11 records.
-h6(#has_many-order). +:order+
+h6(#has_many-order). +order+
-The +:order+ option dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause).
+The +order+ method dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause).
<ruby>
class Customer < ActiveRecord::Base
- has_many :orders, :order => "date_confirmed DESC"
+ has_many :orders, -> { order "date_confirmed DESC" }
end
</ruby>
-h6(#has_many-primary_key). +:primary_key+
-
-By convention, Rails assumes that the column used to hold the primary key of the association is +id+. You can override this and explicitly specify the primary key with the +:primary_key+ option.
-
-h6(#has_many-readonly). +:readonly+
-
-If you set the +:readonly+ option to +true+, then the associated objects will be read-only when retrieved via the association.
-
-h6(#has_many-select). +:select+
-
-The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns.
+h6(#has_many-readonly). +readonly+
-WARNING: If you specify your own +:select+, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error.
+If you use the +readonly+ method, then the associated objects will be read-only when retrieved via the association.
-h6(#has_many-source). +:source+
-
-The +:source+ option specifies the source association name for a +has_many :through+ association. You only need to use this option if the name of the source association cannot be automatically inferred from the association name.
-
-h6(#has_many-source_type). +:source_type+
+h6(#has_many-select). +select+
-The +:source_type+ option specifies the source association type for a +has_many :through+ association that proceeds through a polymorphic association.
+The +select+ method lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns.
-h6(#has_many-through). +:through+
+WARNING: If you specify your own +select+, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error.
-The +:through+ option specifies a join model through which to perform the query. +has_many :through+ associations provide a way to implement many-to-many relationships, as discussed <a href="#the-has_many-through-association">earlier in this guide</a>.
+h6(#has_many-uniq). +uniq+
-h6(#has_many-uniq). +:uniq+
-
-Set the +:uniq+ option to true to keep the collection free of duplicates. This is mostly useful together with the +:through+ option.
+Use the +uniq+ method to keep the collection free of duplicates. This is mostly useful together with the +:through+ option.
<ruby>
class Person < ActiveRecord::Base
@@ -1492,12 +1520,12 @@ Reading.all.inspect # => [#<Reading id: 12, person_id: 5, post_id: 5>, #<Readin
In the above case there are two readings and +person.posts+ brings out both of them even though these records are pointing to the same post.
-Now let's set +:uniq+ to true:
+Now let's set +uniq+:
<ruby>
class Person
has_many :readings
- has_many :posts, :through => :readings, :uniq => true
+ has_many :posts, -> { uniq }, :through => :readings
end
person = Person.create(:name => 'honda')
@@ -1510,10 +1538,6 @@ Reading.all.inspect # => [#<Reading id: 16, person_id: 7, post_id: 7>, #<Readin
In the above case there are still two readings. However +person.posts+ shows only one post because the collection loads only unique records.
-h6(#has_many-validate). +:validate+
-
-If you set the +:validate+ option to +false+, then associated objects will not be validated whenever you save this object. By default, this is +true+: associated objects will be validated when this object is saved.
-
h5(#has_many-when_are_objects_saved). When are Objects Saved?
When you assign an object to a +has_many+ association, that object is automatically saved (in order to update its foreign key). If you assign multiple objects in one statement, then they are all saved.
@@ -1699,22 +1723,8 @@ The +has_and_belongs_to_many+ association supports these options:
* +:association_foreign_key+
* +:autosave+
* +:class_name+
-* +:conditions+
-* +:counter_sql+
-* +:delete_sql+
-* +:extend+
-* +:finder_sql+
* +:foreign_key+
-* +:group+
-* +:include+
-* +:insert_sql+
* +:join_table+
-* +:limit+
-* +:offset+
-* +:order+
-* +:readonly+
-* +:select+
-* +:uniq+
* +:validate+
h6(#has_and_belongs_to_many-association_foreign_key). +:association_foreign_key+
@@ -1745,120 +1755,126 @@ class Parts < ActiveRecord::Base
end
</ruby>
-h6(#has_and_belongs_to_many-conditions). +:conditions+
-
-The +:conditions+ option lets you specify the conditions that the associated object must meet (in the syntax used by an SQL +WHERE+ clause).
-
-<ruby>
-class Parts < ActiveRecord::Base
- has_and_belongs_to_many :assemblies,
- :conditions => "factory = 'Seattle'"
-end
-</ruby>
+h6(#has_and_belongs_to_many-foreign_key). +:foreign_key+
-You can also set conditions via a hash:
+By convention, Rails assumes that the column in the join table used to hold the foreign key pointing to this model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
<ruby>
-class Parts < ActiveRecord::Base
- has_and_belongs_to_many :assemblies,
- :conditions => { :factory => 'Seattle' }
+class User < ActiveRecord::Base
+ has_and_belongs_to_many :friends, :class_name => "User",
+ :foreign_key => "this_user_id",
+ :association_foreign_key => "other_user_id"
end
</ruby>
-If you use a hash-style +:conditions+ option, then record creation via this association will be automatically scoped using the hash. In this case, using +@parts.assemblies.create+ or +@parts.assemblies.build+ will create orders where the +factory+ column has the value "Seattle".
-
-h6(#has_and_belongs_to_many-counter_sql). +:counter_sql+
+h6(#has_and_belongs_to_many-join_table). +:join_table+
-Normally Rails automatically generates the proper SQL to count the association members. With the +:counter_sql+ option, you can specify a complete SQL statement to count them yourself.
+If the default name of the join table, based on lexical ordering, is not what you want, you can use the +:join_table+ option to override the default.
-NOTE: If you specify +:finder_sql+ but not +:counter_sql+, then the counter SQL will be generated by substituting the +SELECT ... FROM+ clause of your +:finder_sql+ statement by +SELECT COUNT(*) FROM+.
+h6(#has_and_belongs_to_many-validate). +:validate+
-h6(#has_and_belongs_to_many-delete_sql). +:delete_sql+
+If you set the +:validate+ option to +false+, then associated objects will not be validated whenever you save this object. By default, this is +true+: associated objects will be validated when this object is saved.
-Normally Rails automatically generates the proper SQL to remove links between the associated classes. With the +:delete_sql+ option, you can specify a complete SQL statement to delete them yourself.
+h5(#has_and_belongs_to_many-scopes_for_has_and_belongs_to_many). Scopes for +has_and_belongs_to_many+
-h6(#has_and_belongs_to_many-extend). +:extend+
+There may be times when you wish to customize the query used by +has_and_belongs_to_many+. Such customizations can be achieved via a scope block. For example:
-The +:extend+ option specifies a named module to extend the association proxy. Association extensions are discussed in detail <a href="#association-extensions">later in this guide</a>.
+<ruby>
+class Parts < ActiveRecord::Base
+ has_and_belongs_to_many :assemblies, -> { where :active => true }
+end
+</ruby>
-h6(#has_and_belongs_to_many-finder_sql). +:finder_sql+
+You can use any of the standard "querying methods":active_record_querying.html inside the scope block. The following ones are discussed below:
-Normally Rails automatically generates the proper SQL to fetch the association members. With the +:finder_sql+ option, you can specify a complete SQL statement to fetch them yourself. If fetching objects requires complex multi-table SQL, this may be necessary.
+* +where+
+* +extending+
+* +group+
+* +includes+
+* +limit+
+* +offset+
+* +order+
+* +readonly+
+* +select+
+* +uniq+
-h6(#has_and_belongs_to_many-foreign_key). +:foreign_key+
+h6(#has_and_belongs_to_many-where). +where+
-By convention, Rails assumes that the column in the join table used to hold the foreign key pointing to this model is the name of this model with the suffix +_id+ added. The +:foreign_key+ option lets you set the name of the foreign key directly:
+The +where+ method lets you specify the conditions that the associated object must meet.
<ruby>
-class User < ActiveRecord::Base
- has_and_belongs_to_many :friends, :class_name => "User",
- :foreign_key => "this_user_id",
- :association_foreign_key => "other_user_id"
+class Parts < ActiveRecord::Base
+ has_and_belongs_to_many :assemblies,
+ -> { where "factory = 'Seattle'" }
end
</ruby>
-h6(#has_and_belongs_to_many-group). +:group+
-
-The +:group+ option supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL.
+You can also set conditions via a hash:
<ruby>
class Parts < ActiveRecord::Base
- has_and_belongs_to_many :assemblies, :group => "factory"
+ has_and_belongs_to_many :assemblies,
+ -> { where :factory => 'Seattle' }
end
</ruby>
-h6(#has_and_belongs_to_many-include). +:include+
+If you use a hash-style +where+, then record creation via this association will be automatically scoped using the hash. In this case, using +@parts.assemblies.create+ or +@parts.assemblies.build+ will create orders where the +factory+ column has the value "Seattle".
-You can use the +:include+ option to specify second-order associations that should be eager-loaded when this association is used.
+h6(#has_and_belongs_to_many-extending). +extending+
-h6(#has_and_belongs_to_many-insert_sql). +:insert_sql+
+The +extending+ method specifies a named module to extend the association proxy. Association extensions are discussed in detail <a href="#association-extensions">later in this guide</a>.
-Normally Rails automatically generates the proper SQL to create links between the associated classes. With the +:insert_sql+ option, you can specify a complete SQL statement to insert them yourself.
+h6(#has_and_belongs_to_many-group). +group+
-h6(#has_and_belongs_to_many-join_table). +:join_table+
+The +group+ method supplies an attribute name to group the result set by, using a +GROUP BY+ clause in the finder SQL.
-If the default name of the join table, based on lexical ordering, is not what you want, you can use the +:join_table+ option to override the default.
+<ruby>
+class Parts < ActiveRecord::Base
+ has_and_belongs_to_many :assemblies, -> { group "factory" }
+end
+</ruby>
-h6(#has_and_belongs_to_many-limit). +:limit+
+h6(#has_and_belongs_to_many-includes). +includes+
-The +:limit+ option lets you restrict the total number of objects that will be fetched through an association.
+You can use the +includes+ method to specify second-order associations that should be eager-loaded when this association is used.
+
+h6(#has_and_belongs_to_many-limit). +limit+
+
+The +limit+ method lets you restrict the total number of objects that will be fetched through an association.
<ruby>
class Parts < ActiveRecord::Base
- has_and_belongs_to_many :assemblies, :order => "created_at DESC",
- :limit => 50
+ has_and_belongs_to_many :assemblies,
+ -> { order("created_at DESC").limit(50) }
end
</ruby>
-h6(#has_and_belongs_to_many-offset). +:offset+
+h6(#has_and_belongs_to_many-offset). +offset+
-The +:offset+ option lets you specify the starting offset for fetching objects via an association. For example, if you set +:offset => 11+, it will skip the first 11 records.
+The +offset+ method lets you specify the starting offset for fetching objects via an association. For example, if you set +offset(11)+, it will skip the first 11 records.
-h6(#has_and_belongs_to_many-order). +:order+
+h6(#has_and_belongs_to_many-order). +order+
-The +:order+ option dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause).
+The +order+ method dictates the order in which associated objects will be received (in the syntax used by an SQL +ORDER BY+ clause).
<ruby>
class Parts < ActiveRecord::Base
- has_and_belongs_to_many :assemblies, :order => "assembly_name ASC"
+ has_and_belongs_to_many :assemblies,
+ -> { order "assembly_name ASC" }
end
</ruby>
-h6(#has_and_belongs_to_many-readonly). +:readonly+
-
-If you set the +:readonly+ option to +true+, then the associated objects will be read-only when retrieved via the association.
+h6(#has_and_belongs_to_many-readonly). +readonly+
-h6(#has_and_belongs_to_many-select). +:select+
+If you use the +readonly+ method, then the associated objects will be read-only when retrieved via the association.
-The +:select+ option lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns.
+h6(#has_and_belongs_to_many-select). +select+
-h6(#has_and_belongs_to_many-uniq). +:uniq+
+The +select+ method lets you override the SQL +SELECT+ clause that is used to retrieve data about the associated objects. By default, Rails retrieves all columns.
-Specify the +:uniq => true+ option to remove duplicates from the collection.
+h6(#has_and_belongs_to_many-uniq). +uniq+
-h6(#has_and_belongs_to_many-validate). +:validate+
-
-If you set the +:validate+ option to +false+, then associated objects will not be validated whenever you save this object. By default, this is +true+: associated objects will be validated when this object is saved.
+Use the +uniq+ method to remove duplicates from the collection.
h5(#has_and_belongs_to_many-when_are_objects_saved). When are Objects Saved?
@@ -1938,20 +1954,11 @@ module FindRecentExtension
end
class Customer < ActiveRecord::Base
- has_many :orders, :extend => FindRecentExtension
+ has_many :orders, -> { extending FindRecentExtension }
end
class Supplier < ActiveRecord::Base
- has_many :deliveries, :extend => FindRecentExtension
-end
-</ruby>
-
-To include more than one extension module in a single association, specify an array of modules:
-
-<ruby>
-class Customer < ActiveRecord::Base
- has_many :orders,
- :extend => [FindRecentExtension, FindActiveExtension]
+ has_many :deliveries, -> { extending FindRecentExtension }
end
</ruby>