|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
1 |
require 'active_record/associations/association_proxy' |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
2 |
require 'active_record/associations/association_collection' |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
3 |
require 'active_record/associations/belongs_to_association' |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
4 |
require 'active_record/associations/belongs_to_polymorphic_association' |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
5 |
require 'active_record/associations/has_one_association' |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
6 |
require 'active_record/associations/has_many_association' |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
7 |
require 'active_record/associations/has_many_through_association' |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
8 |
require 'active_record/associations/has_and_belongs_to_many_association' |
| |
9 |
|
| |
10 |
module ActiveRecord |
|
fed7d334
»
|
dhh |
2006-03-27 |
Fixed documentation |
11 |
class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc: |
|
291adbd3
»
|
technoweenie |
2006-07-19 |
fix association exception m... |
12 |
def initialize(owner_class_name, reflection) |
| |
13 |
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}") |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
14 |
end |
| |
15 |
end |
| |
16 |
|
|
fed7d334
»
|
dhh |
2006-03-27 |
Fixed documentation |
17 |
class HasManyThroughAssociationPolymorphicError < ActiveRecordError #:nodoc: |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
18 |
def initialize(owner_class_name, reflection, source_reflection) |
|
291adbd3
»
|
technoweenie |
2006-07-19 |
fix association exception m... |
19 |
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}'.") |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
20 |
end |
| |
21 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
22 |
|
|
e3dab67c
»
|
technoweenie |
2007-03-12 |
Allow a polymorphic :source... |
23 |
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc: |
| |
24 |
def initialize(owner_class_name, reflection, source_reflection) |
| |
25 |
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.") |
| |
26 |
end |
| |
27 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
28 |
|
|
fed7d334
»
|
dhh |
2006-03-27 |
Fixed documentation |
29 |
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc: |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
30 |
def initialize(reflection) |
|
291adbd3
»
|
technoweenie |
2006-07-19 |
fix association exception m... |
31 |
through_reflection = reflection.through_reflection |
| |
32 |
source_reflection_names = reflection.source_reflection_names |
| |
33 |
source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect } |
| |
34 |
super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence :connector => 'or'} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence :connector => 'or'}?") |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
35 |
end |
| |
36 |
end |
| |
37 |
|
|
0aa0c84c
»
|
dhh |
2007-01-26 |
Nodoc the irrelevant (from ... |
38 |
class HasManyThroughSourceAssociationMacroError < ActiveRecordError #:nodoc: |
|
4d232025
»
|
technoweenie |
2006-04-05 |
Added descriptive error mes... |
39 |
def initialize(reflection) |
|
291adbd3
»
|
technoweenie |
2006-07-19 |
fix association exception m... |
40 |
through_reflection = reflection.through_reflection |
| |
41 |
source_reflection = reflection.source_reflection |
| |
42 |
super("Invalid source reflection macro :#{source_reflection.macro}#{" :through" if source_reflection.options[:through]} for has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}. Use :source to specify the source reflection.") |
|
4d232025
»
|
technoweenie |
2006-04-05 |
Added descriptive error mes... |
43 |
end |
| |
44 |
end |
| |
45 |
|
|
0da426be
»
|
jeremy |
2006-08-18 |
Add records to has_many :th... |
46 |
class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc: |
| |
47 |
def initialize(owner, reflection) |
| |
48 |
super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.") |
| |
49 |
end |
| |
50 |
end |
| |
51 |
|
|
4b639904
»
|
jeremy |
2007-10-27 |
Fix has_many :through delet... |
52 |
class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc: |
| |
53 |
def initialize(owner, reflection) |
| |
54 |
super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.") |
| |
55 |
end |
| |
56 |
end |
| |
57 |
|
|
fed7d334
»
|
dhh |
2006-03-27 |
Fixed documentation |
58 |
class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
59 |
def initialize(reflection) |
|
291adbd3
»
|
technoweenie |
2006-07-19 |
fix association exception m... |
60 |
super("Can not eagerly load the polymorphic association #{reflection.name.inspect}") |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
61 |
end |
| |
62 |
end |
| |
63 |
|
|
c61b10b6
»
|
technoweenie |
2006-04-24 |
Raise error when trying to ... |
64 |
class ReadOnlyAssociation < ActiveRecordError #:nodoc: |
| |
65 |
def initialize(reflection) |
|
291adbd3
»
|
technoweenie |
2006-07-19 |
fix association exception m... |
66 |
super("Can not add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.") |
|
c61b10b6
»
|
technoweenie |
2006-04-24 |
Raise error when trying to ... |
67 |
end |
| |
68 |
end |
| |
69 |
|
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
70 |
module Associations # :nodoc: |
|
61864909
»
|
Marcel Molina |
2006-04-29 |
Replace Ruby's deprecated a... |
71 |
def self.included(base) |
|
7c8d2f28
»
|
dhh |
2005-04-02 |
Removed broken attempt to D... |
72 |
base.extend(ClassMethods) |
| |
73 |
end |
| |
74 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
75 |
# Clears out the association cache |
|
4b229d10
»
|
dhh |
2004-12-22 |
Added Base#clear_associatio... |
76 |
def clear_association_cache #:nodoc: |
| |
77 |
self.class.reflect_on_all_associations.to_a.each do |assoc| |
| |
78 |
instance_variable_set "@#{assoc.name}", nil |
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
79 |
end unless self.new_record? |
|
4b229d10
»
|
dhh |
2004-12-22 |
Added Base#clear_associatio... |
80 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
81 |
|
| |
82 |
# Associations are a set of macro-like class methods for tying objects together through foreign keys. They express relationships like |
| |
83 |
# "Project has one Project Manager" or "Project belongs to a Portfolio". Each macro adds a number of methods to the class which are |
| |
84 |
# specialized according to the collection or association symbol and the options hash. It works much the same way as Ruby's own <tt>attr*</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
85 |
# methods. Example: |
| |
86 |
# |
| |
87 |
# class Project < ActiveRecord::Base |
| |
88 |
# belongs_to :portfolio |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
89 |
# has_one :project_manager |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
90 |
# has_many :milestones |
| |
91 |
# has_and_belongs_to_many :categories |
| |
92 |
# end |
| |
93 |
# |
| |
94 |
# The project class now has the following methods (and more) to ease the traversal and manipulation of its relationships: |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
95 |
# * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
96 |
# * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt> |
| |
97 |
# * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt> |
|
7aa9eed8
»
|
jeremy |
2006-09-01 |
Deprecation: update docs. C... |
98 |
# <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.find(:all, options),</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
99 |
# <tt>Project#milestones.build, Project#milestones.create</tt> |
| |
100 |
# * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt> |
| |
101 |
# <tt>Project#categories.delete(category1)</tt> |
| |
102 |
# |
|
7288fd3e
»
|
jeremy |
2007-05-18 |
Docs: warn that association... |
103 |
# === A word of warning |
| |
104 |
# |
| |
105 |
# Don't create associations that have the same name as instance methods of ActiveRecord::Base. Since the association |
| |
106 |
# adds a method with that name to its model, it will override the inherited method and break things. |
| |
107 |
# For instance, #attributes and #connection would be bad choices for association names. |
| |
108 |
# |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
109 |
# == Auto-generated methods |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
110 |
# |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
111 |
# ===Singular associations (one-to-one) |
| |
112 |
# | | belongs_to | |
| |
113 |
# generated methods | belongs_to | :polymorphic | has_one |
| |
114 |
# ----------------------------------+------------+--------------+--------- |
| |
115 |
# #other | X | X | X |
| |
116 |
# #other=(other) | X | X | X |
| |
117 |
# #build_other(attributes={}) | X | | X |
| |
118 |
# #create_other(attributes={}) | X | | X |
| |
119 |
# #other.create!(attributes={}) | | | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
120 |
# #other.nil? | X | X | |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
121 |
# |
| |
122 |
# ===Collection associations (one-to-many / many-to-many) |
| |
123 |
# | | | has_many |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
124 |
# generated methods | habtm | has_many | :through |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
125 |
# ----------------------------------+-------+----------+---------- |
| |
126 |
# #others | X | X | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
127 |
# #others=(other,other,...) | X | X | |
|
a291ea2b
»
|
Marcel Molina |
2007-11-06 |
Update association/method m... |
128 |
# #other_ids | X | X | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
129 |
# #other_ids=(id,id,...) | X | X | |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
130 |
# #others<< | X | X | X |
| |
131 |
# #others.push | X | X | X |
| |
132 |
# #others.concat | X | X | X |
| |
133 |
# #others.build(attributes={}) | X | X | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
134 |
# #others.create(attributes={}) | X | X | |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
135 |
# #others.create!(attributes={}) | X | X | X |
|
a291ea2b
»
|
Marcel Molina |
2007-11-06 |
Update association/method m... |
136 |
# #others.size | X | X | X |
| |
137 |
# #others.length | X | X | X |
| |
138 |
# #others.count | | X | X |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
139 |
# #others.sum(args*,&block) | X | X | X |
|
a291ea2b
»
|
Marcel Molina |
2007-11-06 |
Update association/method m... |
140 |
# #others.empty? | X | X | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
141 |
# #others.clear | X | X | |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
142 |
# #others.delete(other,other,...) | X | X | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
143 |
# #others.delete_all | X | X | |
|
a291ea2b
»
|
Marcel Molina |
2007-11-06 |
Update association/method m... |
144 |
# #others.destroy_all | X | X | X |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
145 |
# #others.find(*args) | X | X | X |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
146 |
# #others.find_first | X | | |
| |
147 |
# #others.uniq | X | X | |
|
ff6d2aae
»
|
jeremy |
2007-05-30 |
Quickref for association me... |
148 |
# #others.reset | X | X | X |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
149 |
# |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
150 |
# == Cardinality and associations |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
151 |
# |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
152 |
# ActiveRecord associations can be used to describe relations with one-to-one, one-to-many |
| |
153 |
# and many-to-many cardinality. Each model uses an association to describe its role in |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
154 |
# the relation. In each case, the +belongs_to+ association is used in the model that has |
|
8296c680
»
|
technoweenie |
2007-01-22 |
Remove useless code in #att... |
155 |
# the foreign key. |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
156 |
# |
| |
157 |
# === One-to-one |
| |
158 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
159 |
# Use +has_one+ in the base, and +belongs_to+ in the associated model. |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
160 |
# |
| |
161 |
# class Employee < ActiveRecord::Base |
| |
162 |
# has_one :office |
| |
163 |
# end |
| |
164 |
# class Office < ActiveRecord::Base |
| |
165 |
# belongs_to :employee # foreign key - employee_id |
| |
166 |
# end |
| |
167 |
# |
| |
168 |
# === One-to-many |
| |
169 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
170 |
# Use +has_many+ in the base, and +belongs_to+ in the associated model. |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
171 |
# |
| |
172 |
# class Manager < ActiveRecord::Base |
| |
173 |
# has_many :employees |
| |
174 |
# end |
| |
175 |
# class Employee < ActiveRecord::Base |
|
8296c680
»
|
technoweenie |
2007-01-22 |
Remove useless code in #att... |
176 |
# belongs_to :manager # foreign key - manager_id |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
177 |
# end |
| |
178 |
# |
| |
179 |
# === Many-to-many |
| |
180 |
# |
| |
181 |
# There are two ways to build a many-to-many relationship. |
| |
182 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
183 |
# The first way uses a +has_many+ association with the <tt>:through</tt> option and a join model, so |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
184 |
# there are two stages of associations. |
| |
185 |
# |
| |
186 |
# class Assignment < ActiveRecord::Base |
| |
187 |
# belongs_to :programmer # foreign key - programmer_id |
| |
188 |
# belongs_to :project # foreign key - project_id |
| |
189 |
# end |
| |
190 |
# class Programmer < ActiveRecord::Base |
| |
191 |
# has_many :assignments |
| |
192 |
# has_many :projects, :through => :assignments |
| |
193 |
# end |
| |
194 |
# class Project < ActiveRecord::Base |
| |
195 |
# has_many :assignments |
| |
196 |
# has_many :programmers, :through => :assignments |
| |
197 |
# end |
| |
198 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
199 |
# For the second way, use +has_and_belongs_to_many+ in both models. This requires a join table |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
200 |
# that has no corresponding model or primary key. |
| |
201 |
# |
| |
202 |
# class Programmer < ActiveRecord::Base |
| |
203 |
# has_and_belongs_to_many :projects # foreign keys in the join table |
| |
204 |
# end |
| |
205 |
# class Project < ActiveRecord::Base |
| |
206 |
# has_and_belongs_to_many :programmers # foreign keys in the join table |
| |
207 |
# end |
| |
208 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
209 |
# Choosing which way to build a many-to-many relationship is not always simple. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
210 |
# If you need to work with the relationship model as its own entity, |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
211 |
# use <tt>has_many :through</tt>. Use +has_and_belongs_to_many+ when working with legacy schemas or when |
|
51d840e2
»
|
NZKoz |
2007-01-14 |
Improve association documen... |
212 |
# you never work directly with the relationship itself. |
| |
213 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
214 |
# == Is it a +belongs_to+ or +has_one+ association? |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
215 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
216 |
# Both express a 1-1 relationship. The difference is mostly where to place the foreign key, which goes on the table for the class |
| |
217 |
# declaring the +belongs_to+ relationship. Example: |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
218 |
# |
|
69d8ca4c
»
|
jeremy |
2006-07-07 |
Clearer has_one/belongs_to ... |
219 |
# class User < ActiveRecord::Base |
| |
220 |
# # I reference an account. |
| |
221 |
# belongs_to :account |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
222 |
# end |
| |
223 |
# |
|
69d8ca4c
»
|
jeremy |
2006-07-07 |
Clearer has_one/belongs_to ... |
224 |
# class Account < ActiveRecord::Base |
| |
225 |
# # One user references me. |
| |
226 |
# has_one :user |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
227 |
# end |
| |
228 |
# |
| |
229 |
# The tables for these classes could look something like: |
| |
230 |
# |
|
69d8ca4c
»
|
jeremy |
2006-07-07 |
Clearer has_one/belongs_to ... |
231 |
# CREATE TABLE users ( |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
232 |
# id int(11) NOT NULL auto_increment, |
|
69d8ca4c
»
|
jeremy |
2006-07-07 |
Clearer has_one/belongs_to ... |
233 |
# account_id int(11) default NULL, |
| |
234 |
# name varchar default NULL, |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
235 |
# PRIMARY KEY (id) |
| |
236 |
# ) |
| |
237 |
# |
|
69d8ca4c
»
|
jeremy |
2006-07-07 |
Clearer has_one/belongs_to ... |
238 |
# CREATE TABLE accounts ( |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
239 |
# id int(11) NOT NULL auto_increment, |
| |
240 |
# name varchar default NULL, |
| |
241 |
# PRIMARY KEY (id) |
| |
242 |
# ) |
| |
243 |
# |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
244 |
# == Unsaved objects and associations |
| |
245 |
# |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
246 |
# You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
247 |
# aware of, mostly involving the saving of associated objects. |
| |
248 |
# |
| |
249 |
# === One-to-one associations |
| |
250 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
251 |
# * Assigning an object to a +has_one+ association automatically saves that object and the object being replaced (if there is one), in |
| |
252 |
# order to update their primary keys - except if the parent object is unsaved (<tt>new_record? == true</tt>). |
| |
253 |
# * If either of these saves fail (due to one of the objects being invalid) the assignment statement returns +false+ and the assignment |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
254 |
# is cancelled. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
255 |
# * If you wish to assign an object to a +has_one+ association without saving it, use the <tt>#association.build</tt> method (documented below). |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
256 |
# * Assigning an object to a +belongs_to+ association does not save the object, since the foreign key field belongs on the parent. It |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
257 |
# does not save the parent either. |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
258 |
# |
| |
259 |
# === Collections |
| |
260 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
261 |
# * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically saves that object, except if the parent object |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
262 |
# (the owner of the collection) is not yet stored in the database. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
263 |
# * If saving any of the objects being added to a collection (via <tt>#push</tt> or similar) fails, then <tt>#push</tt> returns +false+. |
| |
264 |
# * You can add an object to a collection without automatically saving it by using the <tt>#collection.build</tt> method (documented below). |
| |
265 |
# * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically saved when the parent is saved. |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
266 |
# |
|
17f7f8a0
»
|
dhh |
2005-07-06 |
Made documentation ready fo... |
267 |
# === Association callbacks |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
268 |
# |
|
2af36bbb
»
|
dhh |
2007-12-05 |
Fix typos (closes #10378) |
269 |
# Similar to the normal callbacks that hook into the lifecycle of an Active Record object, you can also define callbacks that get |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
270 |
# triggered when you add an object to or remove an object from an association collection. Example: |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
271 |
# |
| |
272 |
# class Project |
| |
273 |
# has_and_belongs_to_many :developers, :after_add => :evaluate_velocity |
| |
274 |
# |
| |
275 |
# def evaluate_velocity(developer) |
| |
276 |
# ... |
| |
277 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
278 |
# end |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
279 |
# |
| |
280 |
# It's possible to stack callbacks by passing them as an array. Example: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
281 |
# |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
282 |
# class Project |
|
17f7f8a0
»
|
dhh |
2005-07-06 |
Made documentation ready fo... |
283 |
# has_and_belongs_to_many :developers, :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}] |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
284 |
# end |
| |
285 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
286 |
# Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+. |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
287 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
288 |
# Should any of the +before_add+ callbacks throw an exception, the object does not get added to the collection. Same with |
| |
289 |
# the +before_remove+ callbacks; if an exception is thrown the object doesn't get removed. |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
290 |
# |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
291 |
# === Association extensions |
| |
292 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
293 |
# The proxy objects that control the access to associations can be extended through anonymous modules. This is especially |
|
3c01e01d
»
|
Marcel Molina |
2005-12-19 |
Fix typo in association doc... |
294 |
# beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association. |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
295 |
# Example: |
| |
296 |
# |
| |
297 |
# class Account < ActiveRecord::Base |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
298 |
# has_many :people do |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
299 |
# def find_or_create_by_name(name) |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
300 |
# first_name, last_name = name.split(" ", 2) |
|
da7752e5
»
|
dhh |
2005-11-06 |
Sharper example |
301 |
# find_or_create_by_first_name_and_last_name(first_name, last_name) |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
302 |
# end |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
303 |
# end |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
304 |
# end |
| |
305 |
# |
| |
306 |
# person = Account.find(:first).people.find_or_create_by_name("David Heinemeier Hansson") |
| |
307 |
# person.first_name # => "David" |
| |
308 |
# person.last_name # => "Heinemeier Hansson" |
| |
309 |
# |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
310 |
# If you need to share the same extensions between many associations, you can use a named extension module. Example: |
| |
311 |
# |
| |
312 |
# module FindOrCreateByNameExtension |
| |
313 |
# def find_or_create_by_name(name) |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
314 |
# first_name, last_name = name.split(" ", 2) |
|
da7752e5
»
|
dhh |
2005-11-06 |
Sharper example |
315 |
# find_or_create_by_first_name_and_last_name(first_name, last_name) |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
316 |
# end |
| |
317 |
# end |
| |
318 |
# |
| |
319 |
# class Account < ActiveRecord::Base |
| |
320 |
# has_many :people, :extend => FindOrCreateByNameExtension |
| |
321 |
# end |
| |
322 |
# |
| |
323 |
# class Company < ActiveRecord::Base |
| |
324 |
# has_many :people, :extend => FindOrCreateByNameExtension |
| |
325 |
# end |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
326 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
327 |
# If you need to use multiple named extension modules, you can specify an array of modules with the <tt>:extend</tt> option. |
|
7e76740d
»
|
technoweenie |
2006-04-10 |
Allow multiple association... |
328 |
# In the case of name conflicts between methods in the modules, methods in modules later in the array supercede |
| |
329 |
# those earlier in the array. Example: |
| |
330 |
# |
| |
331 |
# class Account < ActiveRecord::Base |
| |
332 |
# has_many :people, :extend => [FindOrCreateByNameExtension, FindRecentExtension] |
| |
333 |
# end |
| |
334 |
# |
|
ea51d72e
»
|
technoweenie |
2006-05-28 |
Provide Association Extensi... |
335 |
# Some extensions can only be made to work with knowledge of the association proxy's internals. |
| |
336 |
# Extensions can access relevant state using accessors on the association proxy: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
337 |
# |
|
ea51d72e
»
|
technoweenie |
2006-05-28 |
Provide Association Extensi... |
338 |
# * +proxy_owner+ - Returns the object the association is part of. |
| |
339 |
# * +proxy_reflection+ - Returns the reflection object that describes the association. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
340 |
# * +proxy_target+ - Returns the associated object for +belongs_to+ and +has_one+, or the collection of associated objects for +has_many+ and +has_and_belongs_to_many+. |
|
ea51d72e
»
|
technoweenie |
2006-05-28 |
Provide Association Extensi... |
341 |
# |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
342 |
# === Association Join Models |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
343 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
344 |
# Has Many associations can be configured with the <tt>:through</tt> option to use an explicit join model to retrieve the data. This |
| |
345 |
# operates similarly to a +has_and_belongs_to_many+ association. The advantage is that you're able to add validations, |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
346 |
# callbacks, and extra attributes on the join model. Consider the following schema: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
347 |
# |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
348 |
# class Author < ActiveRecord::Base |
| |
349 |
# has_many :authorships |
| |
350 |
# has_many :books, :through => :authorships |
| |
351 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
352 |
# |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
353 |
# class Authorship < ActiveRecord::Base |
| |
354 |
# belongs_to :author |
| |
355 |
# belongs_to :book |
| |
356 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
357 |
# |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
358 |
# @author = Author.find :first |
| |
359 |
# @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to. |
| |
360 |
# @author.books # selects all books by using the Authorship join model |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
361 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
362 |
# You can also go through a +has_many+ association on the join model: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
363 |
# |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
364 |
# class Firm < ActiveRecord::Base |
| |
365 |
# has_many :clients |
| |
366 |
# has_many :invoices, :through => :clients |
| |
367 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
368 |
# |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
369 |
# class Client < ActiveRecord::Base |
| |
370 |
# belongs_to :firm |
| |
371 |
# has_many :invoices |
| |
372 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
373 |
# |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
374 |
# class Invoice < ActiveRecord::Base |
| |
375 |
# belongs_to :client |
| |
376 |
# end |
| |
377 |
# |
| |
378 |
# @firm = Firm.find :first |
| |
379 |
# @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm |
| |
380 |
# @firm.invoices # selects all invoices by going through the Client join model. |
| |
381 |
# |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
382 |
# === Polymorphic Associations |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
383 |
# |
| |
384 |
# Polymorphic associations on models are not restricted on what types of models they can be associated with. Rather, they |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
385 |
# specify an interface that a +has_many+ association must adhere to. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
386 |
# |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
387 |
# class Asset < ActiveRecord::Base |
| |
388 |
# belongs_to :attachable, :polymorphic => true |
| |
389 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
390 |
# |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
391 |
# class Post < ActiveRecord::Base |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
392 |
# has_many :assets, :as => :attachable # The :as option specifies the polymorphic interface to use. |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
393 |
# end |
| |
394 |
# |
| |
395 |
# @asset.attachable = @post |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
396 |
# |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
397 |
# This works by using a type column in addition to a foreign key to specify the associated record. In the Asset example, you'd need |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
398 |
# an +attachable_id+ integer column and an +attachable_type+ string column. |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
399 |
# |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
400 |
# Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
401 |
# for the associations to work as expected, ensure that you store the base model for the STI models in the |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
402 |
# type column of the polymorphic association. To continue with the asset example above, suppose there are guest posts |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
403 |
# and member posts that use the posts table for STI. In this case, there must be a +type+ column in the posts table. |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
404 |
# |
| |
405 |
# class Asset < ActiveRecord::Base |
| |
406 |
# belongs_to :attachable, :polymorphic => true |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
407 |
# |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
408 |
# def attachable_type=(sType) |
| |
409 |
# super(sType.to_s.classify.constantize.base_class.to_s) |
| |
410 |
# end |
| |
411 |
# end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
412 |
# |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
413 |
# class Post < ActiveRecord::Base |
| |
414 |
# # because we store "Post" in attachable_type now :dependent => :destroy will work |
| |
415 |
# has_many :assets, :as => :attachable, :dependent => :destroy |
| |
416 |
# end |
| |
417 |
# |
|
aa9ed408
»
|
Marcel Molina |
2007-12-05 |
Fix typo in documentation f... |
418 |
# class GuestPost < Post |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
419 |
# end |
| |
420 |
# |
|
aa9ed408
»
|
Marcel Molina |
2007-12-05 |
Fix typo in documentation f... |
421 |
# class MemberPost < Post |
|
fc7fd4c5
»
|
dhh |
2006-10-08 |
Docfix (closes #6040) |
422 |
# end |
| |
423 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
424 |
# == Caching |
| |
425 |
# |
| |
426 |
# All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
427 |
# instructed not to. The cache is even shared across methods to make it even cheaper to use the macro-added methods without |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
428 |
# worrying too much about performance at the first go. Example: |
| |
429 |
# |
| |
430 |
# project.milestones # fetches milestones from the database |
| |
431 |
# project.milestones.size # uses the milestone cache |
| |
432 |
# project.milestones.empty? # uses the milestone cache |
| |
433 |
# project.milestones(true).size # fetches milestones from the database |
| |
434 |
# project.milestones # uses the milestone cache |
| |
435 |
# |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
436 |
# == Eager loading of associations |
| |
437 |
# |
| |
438 |
# Eager loading is a way to find objects of a certain class and a number of named associations along with it in a single SQL call. This is |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
439 |
# one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100 posts that each need to display their author |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
440 |
# triggers 101 database queries. Through the use of eager loading, the 101 queries can be reduced to 1. Example: |
| |
441 |
# |
| |
442 |
# class Post < ActiveRecord::Base |
| |
443 |
# belongs_to :author |
| |
444 |
# has_many :comments |
| |
445 |
# end |
| |
446 |
# |
| |
447 |
# Consider the following loop using the class above: |
| |
448 |
# |
|
4e2f7bec
»
|
dhh |
2005-04-19 |
Added documentation about :... |
449 |
# for post in Post.find(:all) |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
450 |
# puts "Post: " + post.title |
| |
451 |
# puts "Written by: " + post.author.name |
| |
452 |
# puts "Last comment on: " + post.comments.first.created_on |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
453 |
# end |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
454 |
# |
| |
455 |
# To iterate over these one hundred posts, we'll generate 201 database queries. Let's first just optimize it for retrieving the author: |
| |
456 |
# |
|
4e2f7bec
»
|
dhh |
2005-04-19 |
Added documentation about :... |
457 |
# for post in Post.find(:all, :include => :author) |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
458 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
459 |
# This references the name of the +belongs_to+ association that also used the <tt>:author</tt> symbol, so the find will now weave in a join something |
| |
460 |
# like this: <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Doing so will cut down the number of queries from 201 to 101. |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
461 |
# |
| |
462 |
# We can improve upon the situation further by referencing both associations in the finder with: |
| |
463 |
# |
|
4e2f7bec
»
|
dhh |
2005-04-19 |
Added documentation about :... |
464 |
# for post in Post.find(:all, :include => [ :author, :comments ]) |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
465 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
466 |
# That'll add another join along the lines of: <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt>. And we'll be down to 1 query. |
|
5b414190
»
|
jeremy |
2007-05-19 |
Document deep eager include... |
467 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
468 |
# To include a deep hierarchy of associations, use a hash: |
|
5b414190
»
|
jeremy |
2007-05-19 |
Document deep eager include... |
469 |
# |
| |
470 |
# for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ]) |
| |
471 |
# |
| |
472 |
# That'll grab not only all the comments but all their authors and gravatar pictures. You can mix and match |
| |
473 |
# symbols, arrays and hashes in any combination to describe the associations you want to load. |
| |
474 |
# |
| |
475 |
# All of this power shouldn't fool you into thinking that you can pull out huge amounts of data with no performance penalty just because you've reduced |
|
a8eea0b0
»
|
dhh |
2005-10-26 |
Fix docs (closes #2491) |
476 |
# the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no |
| |
477 |
# catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
478 |
# |
|
8e3bf70b
»
|
technoweenie |
2006-10-08 |
Removes the ability for eag... |
479 |
# Since the eager loading pulls from multiple tables, you'll have to disambiguate any column references in both conditions and orders. So |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
480 |
# <tt>:order => "posts.id DESC"</tt> will work while <tt>:order => "id DESC"</tt> will not. Because eager loading generates the +SELECT+ statement too, the |
| |
481 |
# <tt>:select</tt> option is ignored. |
|
515886a5
»
|
dhh |
2005-04-18 |
Added documentation for new... |
482 |
# |
|
8e3bf70b
»
|
technoweenie |
2006-10-08 |
Removes the ability for eag... |
483 |
# You can use eager loading on multiple associations from the same table, but you cannot use those associations in orders and conditions |
| |
484 |
# as there is currently not any way to disambiguate them. Eager loading will not pull additional attributes on join tables, so "rich |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
485 |
# associations" with +has_and_belongs_to_many+ are not a good fit for eager loading. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
486 |
# |
|
78704946
»
|
technoweenie |
2006-10-11 |
Restore eager condition int... |
487 |
# When eager loaded, conditions are interpolated in the context of the model class, not the model instance. Conditions are lazily interpolated |
| |
488 |
# before the actual model exists. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
489 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
490 |
# == Table Aliasing |
| |
491 |
# |
| |
492 |
# ActiveRecord uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once, |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
493 |
# the standard table name is used. The second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>. Indexes are appended |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
494 |
# for any more successive uses of the table name. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
495 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
496 |
# Post.find :all, :include => :comments |
| |
497 |
# # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... |
| |
498 |
# Post.find :all, :include => :special_comments # STI |
| |
499 |
# # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... AND comments.type = 'SpecialComment' |
| |
500 |
# Post.find :all, :include => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name |
| |
501 |
# # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... LEFT OUTER JOIN comments special_comments_posts |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
502 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
503 |
# Acts as tree example: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
504 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
505 |
# TreeMixin.find :all, :include => :children |
| |
506 |
# # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... |
| |
507 |
# TreeMixin.find :all, :include => {:children => :parent} # using cascading eager includes |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
508 |
# # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... |
| |
509 |
# LEFT OUTER JOIN parents_mixins ... |
| |
510 |
# TreeMixin.find :all, :include => {:children => {:parent => :children}} |
| |
511 |
# # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
512 |
# LEFT OUTER JOIN parents_mixins ... |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
513 |
# LEFT OUTER JOIN mixins childrens_mixins_2 |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
514 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
515 |
# Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
516 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
517 |
# Post.find :all, :include => :categories |
| |
518 |
# # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... |
| |
519 |
# Post.find :all, :include => {:categories => :posts} |
| |
520 |
# # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... |
| |
521 |
# LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories |
| |
522 |
# Post.find :all, :include => {:categories => {:posts => :categories}} |
| |
523 |
# # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... |
| |
524 |
# LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories |
| |
525 |
# LEFT OUTER JOIN categories_posts categories_posts_join LEFT OUTER JOIN categories categories_posts |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
526 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
527 |
# If you wish to specify your own custom joins using a <tt>:joins</tt> option, those table names will take precedence over the eager associations: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
528 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
529 |
# Post.find :all, :include => :comments, :joins => "inner join comments ..." |
| |
530 |
# # => SELECT ... FROM posts LEFT OUTER JOIN comments_posts ON ... INNER JOIN comments ... |
| |
531 |
# Post.find :all, :include => [:comments, :special_comments], :joins => "inner join comments ..." |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
532 |
# # => SELECT ... FROM posts LEFT OUTER JOIN comments comments_posts ON ... |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
533 |
# LEFT OUTER JOIN comments special_comments_posts ... |
| |
534 |
# INNER JOIN comments ... |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
535 |
# |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
536 |
# Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
537 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
538 |
# == Modules |
| |
539 |
# |
| |
540 |
# By default, associations will look for objects within the current module scope. Consider: |
| |
541 |
# |
| |
542 |
# module MyApplication |
| |
543 |
# module Business |
| |
544 |
# class Firm < ActiveRecord::Base |
| |
545 |
# has_many :clients |
| |
546 |
# end |
| |
547 |
# |
| |
548 |
# class Company < ActiveRecord::Base; end |
| |
549 |
# end |
| |
550 |
# end |
| |
551 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
552 |
# When <tt>Firm#clients</tt> is called, it will in turn call <tt>MyApplication::Business::Company.find(firm.id)</tt>. If you want to associate |
| |
553 |
# with a class in another module scope, this can be done by specifying the complete class name. Example: |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
554 |
# |
| |
555 |
# module MyApplication |
| |
556 |
# module Business |
| |
557 |
# class Firm < ActiveRecord::Base; end |
| |
558 |
# end |
| |
559 |
# |
| |
560 |
# module Billing |
| |
561 |
# class Account < ActiveRecord::Base |
| |
562 |
# belongs_to :firm, :class_name => "MyApplication::Business::Firm" |
| |
563 |
# end |
| |
564 |
# end |
| |
565 |
# end |
| |
566 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
567 |
# == Type safety with <tt>ActiveRecord::AssociationTypeMismatch</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
568 |
# |
| |
569 |
# If you attempt to assign an object to an association that doesn't match the inferred or specified <tt>:class_name</tt>, you'll |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
570 |
# get an <tt>ActiveRecord::AssociationTypeMismatch</tt>. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
571 |
# |
| |
572 |
# == Options |
| |
573 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
574 |
# All of the association macros can be specialized through options. This makes cases more complex than the simple and guessable ones |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
575 |
# possible. |
| |
576 |
module ClassMethods |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
577 |
# Adds the following methods for retrieval and query of collections of associated objects: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
578 |
# +collection+ is replaced with the symbol passed as the first argument, so |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
579 |
# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
580 |
# * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. |
| |
581 |
# An empty array is returned if none are found. |
| |
582 |
# * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by setting their foreign keys to the collection's primary key. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
583 |
# * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by setting their foreign keys to NULL. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
584 |
# This will also destroy the objects if they're declared as +belongs_to+ and dependent on this model. |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
585 |
# * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
586 |
# * <tt>collection_singular_ids</tt> - returns an array of the associated objects' ids |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
587 |
# * <tt>collection_singular_ids=ids</tt> - replace the collection with the objects identified by the primary keys in +ids+ |
|
efaf2af0
»
|
jeremy |
2005-09-27 |
r3653@asus: jeremy | 2005... |
588 |
# * <tt>collection.clear</tt> - removes every object from the collection. This destroys the associated objects if they |
|
6ad9d1db
»
|
Marcel Molina |
2007-05-05 |
Update documentation for :d... |
589 |
# are associated with <tt>:dependent => :destroy</tt>, deletes them directly from the database if <tt>:dependent => :delete_all</tt>, |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
590 |
# otherwise sets their foreign keys to NULL. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
591 |
# * <tt>collection.empty?</tt> - returns +true+ if there are no associated objects. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
592 |
# * <tt>collection.size</tt> - returns the number of associated objects. |
|
c1611a70
»
|
dhh |
2005-04-18 |
Updated documentation here ... |
593 |
# * <tt>collection.find</tt> - finds an associated object according to the same rules as Base.find. |
|
b49fcde7
»
|
technoweenie |
2007-07-24 |
tiny doc patches [lifo] |
594 |
# * <tt>collection.build(attributes = {}, ...)</tt> - returns one or more new objects of the collection type that have been instantiated |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
595 |
# with +attributes+ and linked to this object through a foreign key, but have not yet been saved. *Note:* This only works if an |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
596 |
# associated object already exists, not if it's +nil+! |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
597 |
# * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
598 |
# with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation). |
| |
599 |
# *Note:* This only works if an associated object already exists, not if it's +nil+! |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
600 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
601 |
# Example: A +Firm+ class declares <tt>has_many :clients</tt>, which will add: |
|
c1611a70
»
|
dhh |
2005-04-18 |
Updated documentation here ... |
602 |
# * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => "firm_id = #{id}"</tt>) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
603 |
# * <tt>Firm#clients<<</tt> |
| |
604 |
# * <tt>Firm#clients.delete</tt> |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
605 |
# * <tt>Firm#clients=</tt> |
|
cb0837a2
»
|
dhh |
2006-10-08 |
Doc fixes (closes #6325) |
606 |
# * <tt>Firm#client_ids</tt> |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
607 |
# * <tt>Firm#client_ids=</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
608 |
# * <tt>Firm#clients.clear</tt> |
| |
609 |
# * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>) |
| |
610 |
# * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>) |
|
c1611a70
»
|
dhh |
2005-04-18 |
Updated documentation here ... |
611 |
# * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
612 |
# * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>) |
|
1d4d7217
»
|
dhh |
2005-06-21 |
Fixed docs #856 |
613 |
# * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
614 |
# The declaration can also include an options hash to specialize the behavior of the association. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
615 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
616 |
# Options are: |
|
098fa943
»
|
dhh |
2005-02-07 |
Fixed documentation snafus ... |
617 |
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
618 |
# from the association name. So <tt>has_many :products</tt> will by default be linked to the +Product+ class, but |
| |
619 |
# if the real class name is +SpecialProduct+, you'll have to specify it with this option. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
620 |
# * <tt>:conditions</tt> - specify the conditions that the associated objects must meet in order to be included as a +WHERE+ |
| |
621 |
# SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. |
| |
622 |
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, |
| |
623 |
# such as <tt>last_name, first_name DESC</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
624 |
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
625 |
# of this class in lower-case and +_id+ suffixed. So a +Person+ class that makes a +has_many+ association will use +person_id+ |
| |
626 |
# as the default +foreign_key+. |
| |
627 |
# * <tt>:dependent</tt> - if set to <tt>:destroy</tt> all the associated objects are destroyed |
| |
628 |
# alongside this object by calling their destroy method. If set to <tt>:delete_all</tt> all associated |
| |
629 |
# objects are deleted *without* calling their destroy method. If set to <tt>:nullify</tt> all associated |
| |
630 |
# objects' foreign keys are set to +NULL+ *without* calling their save callbacks. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
631 |
# * <tt>:finder_sql</tt> - specify a complete SQL statement to fetch the association. This is a good way to go for complex |
|
a8eea0b0
»
|
dhh |
2005-10-26 |
Fix docs (closes #2491) |
632 |
# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
633 |
# * <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
634 |
# 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>. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
635 |
# * <tt>:extend</tt> - specify a named module for extending the proxy. See "Association extensions". |
|
49c801b7
»
|
dhh |
2005-11-06 |
Added :include as an option... |
636 |
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
637 |
# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause. |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
638 |
# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. |
| |
639 |
# * <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. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
640 |
# * <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 |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
641 |
# but not include the joined columns. |
| |
642 |
# * <tt>:as</tt>: Specifies a polymorphic interface (See <tt>#belongs_to</tt>). |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
643 |
# * <tt>:through</tt>: Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt> |
|
9f51eb24
»
|
jeremy |
2007-05-22 |
Fix :through docs wrecked u... |
644 |
# are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt> |
| |
645 |
# or <tt>has_many</tt> association on the join model. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
646 |
# * <tt>:source</tt>: Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
647 |
# inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or |
| |
648 |
# <tt>:subscriber</tt> on +Subscription+, unless a <tt>:source</tt> is given. |
| |
649 |
# * <tt>:source_type</tt>: Specifies type of the source association used by <tt>has_many :through</tt> queries where the source |
| |
650 |
# association is a polymorphic +belongs_to+. |
| |
651 |
# * <tt>:uniq</tt> - if set to +true+, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
652 |
# |
| |
653 |
# Option examples: |
| |
654 |
# has_many :comments, :order => "posted_on" |
|
49c801b7
»
|
dhh |
2005-11-06 |
Added :include as an option... |
655 |
# has_many :comments, :include => :author |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
656 |
# has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name" |
|
57565b35
»
|
NZKoz |
2006-03-09 |
format fix for locking [Mic... |
657 |
# has_many :tracks, :order => "position", :dependent => :destroy |
| |
658 |
# has_many :comments, :dependent => :nullify |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
659 |
# has_many :tags, :as => :taggable |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
660 |
# has_many :subscribers, :through => :subscriptions, :source => :user |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
661 |
# has_many :subscribers, :class_name => "Person", :finder_sql => |
| |
662 |
# 'SELECT DISTINCT people.* ' + |
| |
663 |
# 'FROM people p, post_subscriptions ps ' + |
| |
664 |
# 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' + |
| |
665 |
# 'ORDER BY p.first_name' |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
666 |
def has_many(association_id, options = {}, &extension) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
667 |
reflection = create_has_many_reflection(association_id, options, &extension) |
|
04397693
»
|
dhh |
2005-09-09 |
Refactored away all the leg... |
668 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
669 |
configure_dependency_for_has_many(reflection) |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
670 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
671 |
if options[:through] |
|
b5b16a80
»
|
jeremy |
2007-06-27 |
Define collection singular ... |
672 |
collection_accessor_methods(reflection, HasManyThroughAssociation, false) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
673 |
else |
| |
674 |
add_multiple_associated_save_callbacks(reflection.name) |
| |
675 |
add_association_callbacks(reflection.name, reflection.options) |
| |
676 |
collection_accessor_methods(reflection, HasManyAssociation) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
677 |
end |
| |
678 |
end |
| |
679 |
|
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
680 |
# Adds the following methods for retrieval and query of a single associated object: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
681 |
# +association+ is replaced with the symbol passed as the first argument, so |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
682 |
# <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
683 |
# * <tt>association(force_reload = false)</tt> - returns the associated object. +nil+ is returned if none is found. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
684 |
# * <tt>association=(associate)</tt> - assigns the associate object, extracts the primary key, sets it as the foreign key, |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
685 |
# and saves the associate object. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
686 |
# * <tt>association.nil?</tt> - returns +true+ if there is no associated object. |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
687 |
# * <tt>build_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
688 |
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved. Note: This ONLY works if |
| |
689 |
# an association already exists. It will NOT work if the association is +nil+. |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
690 |
# * <tt>create_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
691 |
# with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation). |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
692 |
# |
| |
693 |
# Example: An Account class declares <tt>has_one :beneficiary</tt>, which will add: |
|
3dfa56cc
»
|
dhh |
2005-06-26 |
Updated all references to t... |
694 |
# * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}")</tt>) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
695 |
# * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>) |
| |
696 |
# * <tt>Account#beneficiary.nil?</tt> |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
697 |
# * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>) |
| |
698 |
# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>) |
| |
699 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
700 |
# The declaration can also include an options hash to specialize the behavior of the association. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
701 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
702 |
# Options are: |
|
098fa943
»
|
dhh |
2005-02-07 |
Fixed documentation snafus ... |
703 |
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
704 |
# from the association name. So <tt>has_one :manager</tt> will by default be linked to the +Manager+ class, but |
| |
705 |
# if the real class name is +Person+, you'll have to specify it with this option. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
706 |
# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a +WHERE+ |
| |
707 |
# SQL fragment, such as <tt>rank = 5</tt>. |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
708 |
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, |
| |
709 |
# such as <tt>last_name, first_name DESC</tt> |
|
aa04635d
»
|
jeremy |
2007-10-08 |
Update :dependent docs and ... |
710 |
# * <tt>:dependent</tt> - if set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
711 |
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to <tt>:nullify</tt>, the associated |
| |
712 |
# object's foreign key is set to +NULL+. Also, association is assigned. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
713 |
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
714 |
# of this class in lower-case and +_id+ suffixed. So a +Person+ class that makes a +has_one+ association will use +person_id+ |
| |
715 |
# as the default +foreign_key+. |
|
49c801b7
»
|
dhh |
2005-11-06 |
Added :include as an option... |
716 |
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
717 |
# * <tt>:as</tt>: Specifies a polymorphic interface (See <tt>#belongs_to</tt>). |
|
21399219
»
|
technoweenie |
2006-05-22 |
Add docs for the :as option... |
718 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
719 |
# Option examples: |
|
57565b35
»
|
NZKoz |
2006-03-09 |
format fix for locking [Mic... |
720 |
# has_one :credit_card, :dependent => :destroy # destroys the associated credit card |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
721 |
# has_one :credit_card, :dependent => :nullify # updates the associated records foreign key value to NULL rather than destroying it |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
722 |
# has_one :last_comment, :class_name => "Comment", :order => "posted_on" |
| |
723 |
# has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'" |
|
21399219
»
|
technoweenie |
2006-05-22 |
Add docs for the :as option... |
724 |
# has_one :attachment, :as => :attachable |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
725 |
def has_one(association_id, options = {}) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
726 |
reflection = create_has_one_reflection(association_id, options) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
727 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
728 |
ivar = "@#{reflection.name}" |
| |
729 |
|
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
730 |
module_eval do |
| |
731 |
after_save <<-EOF |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
732 |
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") |
| |
733 |
|
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
734 |
if !association.nil? && (new_record? || association.new_record? || association["#{reflection.primary_key_name}"] != id) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
735 |
association["#{reflection.primary_key_name}"] = id |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
736 |
association.save(true) |
| |
737 |
end |
| |
738 |
EOF |
| |
739 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
740 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
741 |
association_accessor_methods(reflection, HasOneAssociation) |
| |
742 |
association_constructor_method(:build, reflection, HasOneAssociation) |
| |
743 |
association_constructor_method(:create, reflection, HasOneAssociation) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
744 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
745 |
configure_dependency_for_has_one(reflection) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
746 |
end |
| |
747 |
|
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
748 |
# Adds the following methods for retrieval and query for a single associated object for which this object holds an id: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
749 |
# +association+ is replaced with the symbol passed as the first argument, so |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
750 |
# <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
751 |
# * <tt>association(force_reload = false)</tt> - returns the associated object. +nil+ is returned if none is found. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
752 |
# * <tt>association=(associate)</tt> - assigns the associate object, extracts the primary key, and sets it as the foreign key. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
753 |
# * <tt>association.nil?</tt> - returns +true+ if there is no associated object. |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
754 |
# * <tt>build_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
755 |
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved. |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
756 |
# * <tt>create_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
757 |
# with +attributes+, linked to this object through a foreign key, and that has already been saved (if it passed the validation). |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
758 |
# |
|
e58f2675
»
|
dhh |
2005-02-23 |
Documentation fixes #694 |
759 |
# Example: A Post class declares <tt>belongs_to :author</tt>, which will add: |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
760 |
# * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>) |
| |
761 |
# * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>) |
| |
762 |
# * <tt>Post#author?</tt> (similar to <tt>post.author == some_author</tt>) |
| |
763 |
# * <tt>Post#author.nil?</tt> |
|
1d4d7217
»
|
dhh |
2005-06-21 |
Fixed docs #856 |
764 |
# * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>) |
| |
765 |
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
766 |
# The declaration can also include an options hash to specialize the behavior of the association. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
767 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
768 |
# Options are: |
|
098fa943
»
|
dhh |
2005-02-07 |
Fixed documentation snafus ... |
769 |
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
770 |
# from the association name. So <tt>has_one :author</tt> will by default be linked to the +Author+ class, but |
| |
771 |
# if the real class name is +Person+, you'll have to specify it with this option. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
772 |
# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a +WHERE+ |
| |
773 |
# SQL fragment, such as <tt>authorized = 1</tt>. |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
774 |
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, |
| |
775 |
# such as <tt>last_name, first_name DESC</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
776 |
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name |
|
f6379bfe
»
|
jeremy |
2007-12-20 |
Eager belongs_to :include i... |
777 |
# of the association with an +_id+ suffix. So a class that defines a +belongs_to :person+ association will use +person_id+ as the default +foreign_key+. |
| |
778 |
# Similarly, +belongs_to :favorite_person, :class_name => "Person"+ will use a foreign key of +favorite_person_id+. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
779 |
# * <tt>:counter_cache</tt> - caches the number of belonging objects on the associate class through the use of +increment_counter+ |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
780 |
# and +decrement_counter+. The counter cache is incremented when an object of this class is created and decremented when it's |
| |
781 |
# destroyed. This requires that a column named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging +Comment+ class) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
782 |
# is used on the associate class (such as a +Post+ class). You can also specify a custom counter cache column by providing |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
783 |
# a column name instead of a +true+/+false+ value to this option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.) |
|
c1bc61cb
»
|
technoweenie |
2007-10-13 |
Add notes to documentation ... |
784 |
# Note: Specifying a counter_cache will add it to that model's list of readonly attributes using #attr_readonly. |
|
49c801b7
»
|
dhh |
2005-11-06 |
Added :include as an option... |
785 |
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
786 |
# * <tt>:polymorphic</tt> - specify this association is a polymorphic association by passing +true+. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
787 |
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute |
|
c1bc61cb
»
|
technoweenie |
2007-10-13 |
Add notes to documentation ... |
788 |
# to the attr_readonly list in the associated classes (e.g. class Post; attr_readonly :comments_count; end). |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
789 |
# |
| |
790 |
# Option examples: |
| |
791 |
# belongs_to :firm, :foreign_key => "client_of" |
| |
792 |
# belongs_to :author, :class_name => "Person", :foreign_key => "author_id" |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
793 |
# belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
794 |
# :conditions => 'discounts > #{payments_count}' |
|
2597bd69
»
|
technoweenie |
2006-03-27 |
documentation for polymorph... |
795 |
# belongs_to :attachable, :polymorphic => true |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
796 |
def belongs_to(association_id, options = {}) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
797 |
reflection = create_belongs_to_reflection(association_id, options) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
798 |
|
| |
799 |
ivar = "@#{reflection.name}" |
| |
800 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
801 |
if reflection.options[:polymorphic] |
| |
802 |
association_accessor_methods(reflection, BelongsToPolymorphicAssociation) |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
803 |
|
| |
804 |
module_eval do |
| |
805 |
before_save <<-EOF |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
806 |
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") |
| |
807 |
|
|
94a13091
»
|
technoweenie |
2006-08-08 |
Cache nil results for has_o... |
808 |
if association && association.target |
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
809 |
if association.new_record? |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
810 |
association.save(true) |
| |
811 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
812 |
|
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
813 |
if association.updated? |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
814 |
self["#{reflection.primary_key_name}"] = association.id |
|
0859779d
»
|
technoweenie |
2006-03-15 |
Allow :dependent options to... |
815 |
self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
816 |
end |
|
5213a1f7
»
|
jamis |
2005-09-20 |
Fixed saving a record with ... |
817 |
end |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
818 |
EOF |
| |
819 |
end |
| |
820 |
else |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
821 |
association_accessor_methods(reflection, BelongsToAssociation) |
| |
822 |
association_constructor_method(:build, reflection, BelongsToAssociation) |
| |
823 |
association_constructor_method(:create, reflection, BelongsToAssociation) |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
824 |
|
| |
825 |
module_eval do |
| |
826 |
before_save <<-EOF |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
827 |
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") |
| |
828 |
|
| |
829 |
if !association.nil? |
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
830 |
if association.new_record? |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
831 |
association.save(true) |
| |
832 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
833 |
|
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
834 |
if association.updated? |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
835 |
self["#{reflection.primary_key_name}"] = association.id |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
836 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
837 |
end |
|
57b7532b
»
|
dhh |
2005-12-01 |
Work-in progress for provid... |
838 |
EOF |
| |
839 |
end |
| |
840 |
end |
|
964b67dd
»
|
jamis |
2006-03-04 |
Make counter_cache work wit... |
841 |
|
|
2a305949
»
|
technoweenie |
2007-03-27 |
documentation project patch... |
842 |
# Create the callbacks to update counter cache |
|
964b67dd
»
|
jamis |
2006-03-04 |
Make counter_cache work wit... |
843 |
if options[:counter_cache] |
|
87898bad
»
|
jamis |
2006-03-09 |
Allow counter_cache to acce... |
844 |
cache_column = options[:counter_cache] == true ? |
| |
845 |
"#{self.to_s.underscore.pluralize}_count" : |
| |
846 |
options[:counter_cache] |
| |
847 |
|
|
964b67dd
»
|
jamis |
2006-03-04 |
Make counter_cache work wit... |
848 |
module_eval( |
|
87898bad
»
|
jamis |
2006-03-09 |
Allow counter_cache to acce... |
849 |
"after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + |
|
964b67dd
»
|
jamis |
2006-03-04 |
Make counter_cache work wit... |
850 |
" unless #{reflection.name}.nil?'" |
| |
851 |
) |
| |
852 |
|
| |
853 |
module_eval( |
|
87898bad
»
|
jamis |
2006-03-09 |
Allow counter_cache to acce... |
854 |
"before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + |
|
964b67dd
»
|
jamis |
2006-03-04 |
Make counter_cache work wit... |
855 |
" unless #{reflection.name}.nil?'" |
|
66d05f5e
»
|
technoweenie |
2007-09-30 |
Add attr_readonly to specif... |
856 |
) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
857 |
|
|
66d05f5e
»
|
technoweenie |
2007-09-30 |
Add attr_readonly to specif... |
858 |
module_eval( |
|
24c2457a
»
|
technoweenie |
2007-10-05 |
Don't call attr_readonly on... |
859 |
"#{reflection.class_name}.send(:attr_readonly,\"#{cache_column}\".intern) if defined?(#{reflection.class_name}) && #{reflection.class_name}.respond_to?(:attr_readonly)" |
|
66d05f5e
»
|
technoweenie |
2007-09-30 |
Add attr_readonly to specif... |
860 |
) |
|
964b67dd
»
|
jamis |
2006-03-04 |
Make counter_cache work wit... |
861 |
end |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
862 |
end |
| |
863 |
|
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
864 |
# Associates two classes via an intermediate join table. Unless the join table is explicitly specified as |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
865 |
# an option, it is guessed using the lexical order of the class names. So a join between +Developer+ and +Project+ |
| |
866 |
# will give the default join table name of +developers_projects+ because "D" outranks "P". Note that this precedence |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
867 |
# is calculated using the <tt><</tt> operator for <tt>String</tt>. This means that if the strings are of different lengths, |
|
56c55354
»
|
technoweenie |
2007-01-15 |
[DOC] clear up some ambigui... |
868 |
# and the strings are equal when compared up to the shortest length, then the longer string is considered of higher |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
869 |
# lexical precedence than the shorter one. For example, one would expect the tables <tt>paper_boxes</tt> and <tt>papers</tt> |
|
56c55354
»
|
technoweenie |
2007-01-15 |
[DOC] clear up some ambigui... |
870 |
# to generate a join table name of <tt>papers_paper_boxes</tt> because of the length of the name <tt>paper_boxes</tt>, |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
871 |
# but it in fact generates a join table name of <tt>paper_boxes_papers</tt>. Be aware of this caveat, and use the |
|
56c55354
»
|
technoweenie |
2007-01-15 |
[DOC] clear up some ambigui... |
872 |
# custom <tt>join_table</tt> option if you need to. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
873 |
# |
|
53aa8da1
»
|
dhh |
2006-04-01 |
Fixed that records returned... |
874 |
# Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
875 |
# +has_and_belongs_to_many+ associations. Records returned from join tables with additional attributes will be marked as |
|
e3b49c05
»
|
dhh |
2007-09-28 |
Fixed spelling errors (clos... |
876 |
# +ReadOnly+ (because we can't save changes to the additional attributes). It's strongly recommended that you upgrade any |
|
53aa8da1
»
|
dhh |
2006-04-01 |
Fixed that records returned... |
877 |
# associations with attributes to a real join model (see introduction). |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
878 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
879 |
# Adds the following methods for retrieval and query: |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
880 |
# +collection+ is replaced with the symbol passed as the first argument, so |
|
4eab3758
»
|
dhh |
2005-02-23 |
Finished polishing API docs |
881 |
# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
882 |
# * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
883 |
# An empty array is returned if none are found. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
884 |
# * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by creating associations in the join table |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
885 |
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method). |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
886 |
# * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by removing their associations from the join table. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
887 |
# This does not destroy the objects. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
888 |
# * <tt>collection=objects</tt> - replaces the collection's content by deleting and adding objects as appropriate. |
| |
889 |
# * <tt>collection_singular_ids</tt> - returns an array of the associated objects' ids |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
890 |
# * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+ |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
891 |
# * <tt>collection.clear</tt> - removes every object from the collection. This does not destroy the objects. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
892 |
# * <tt>collection.empty?</tt> - returns +true+ if there are no associated objects. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
893 |
# * <tt>collection.size</tt> - returns the number of associated objects. |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
894 |
# * <tt>collection.find(id)</tt> - finds an associated object responding to the +id+ and that |
| |
895 |
# meets the condition that it has to be associated with this object. |
|
06075a9e
»
|
technoweenie |
2006-05-28 |
Fix the has_and_belongs_to_... |
896 |
# * <tt>collection.build(attributes = {})</tt> - returns a new object of the collection type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
897 |
# with +attributes+ and linked to this object through the join table, but has not yet been saved. |
|
06075a9e
»
|
technoweenie |
2006-05-28 |
Fix the has_and_belongs_to_... |
898 |
# * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
899 |
# with +attributes+, linked to this object through the join table, and that has already been saved (if it passed the validation). |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
900 |
# |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
901 |
# Example: A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add: |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
902 |
# * <tt>Developer#projects</tt> |
| |
903 |
# * <tt>Developer#projects<<</tt> |
| |
904 |
# * <tt>Developer#projects.delete</tt> |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
905 |
# * <tt>Developer#projects=</tt> |
|
cb0837a2
»
|
dhh |
2006-10-08 |
Doc fixes (closes #6325) |
906 |
# * <tt>Developer#project_ids</tt> |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
907 |
# * <tt>Developer#project_ids=</tt> |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
908 |
# * <tt>Developer#projects.clear</tt> |
| |
909 |
# * <tt>Developer#projects.empty?</tt> |
| |
910 |
# * <tt>Developer#projects.size</tt> |
| |
911 |
# * <tt>Developer#projects.find(id)</tt> |
|
06075a9e
»
|
technoweenie |
2006-05-28 |
Fix the has_and_belongs_to_... |
912 |
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>) |
| |
913 |
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
914 |
# The declaration may include an options hash to specialize the behavior of the association. |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
915 |
# |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
916 |
# Options are: |
|
098fa943
»
|
dhh |
2005-02-07 |
Fixed documentation snafus ... |
917 |
# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
918 |
# from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
919 |
# +Project+ class, but if the real class name is +SuperProject+, you'll have to specify it with this option. |
| |
920 |
# * <tt>:join_table</tt> - specify the name of the join table if the default based on lexical order isn't what you want. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
921 |
# WARNING: If you're overwriting the table name of either class, the +table_name+ method MUST be declared underneath any |
| |
922 |
# +has_and_belongs_to_many+ declaration in order to work. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
923 |
# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
924 |
# of this class in lower-case and +_id+ suffixed. So a +Person+ class that makes a +has_and_belongs_to_many+ association |
| |
925 |
# will use +person_id+ as the default +foreign_key+. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
926 |
# * <tt>:association_foreign_key</tt> - specify the association foreign key used for the association. By default this is |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
927 |
# guessed to be the name of the associated class in lower-case and +_id+ suffixed. So if the associated class is +Project+, |
| |
928 |
# the +has_and_belongs_to_many+ association will use +project_id+ as the default association +foreign_key+. |
| |
929 |
# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a +WHERE+ |
| |
930 |
# SQL fragment, such as <tt>authorized = 1</tt>. |
|
7143d801
»
|
Marcel Molina |
2007-11-07 |
Smattering of grammatical f... |
931 |
# * <tt>:order</tt> - specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment, |
| |
932 |
# such as <tt>last_name, first_name DESC</tt> |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
933 |
# * <tt>:uniq</tt> - if set to +true+, duplicate associated objects will be ignored by accessors and query methods |
| |
934 |
# * <tt>:finder_sql</tt> - overwrite the default generated SQL statement used to fetch the association with a manual statement |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
935 |
# * <tt>:delete_sql</tt> - overwrite the default generated SQL statement used to remove links between the associated |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
936 |
# classes with a manual statement |
| |
937 |
# * <tt>:insert_sql</tt> - overwrite the default generated SQL statement used to add links between the associated classes |
| |
938 |
# with a manual statement |
|
8c512a1c
»
|
dhh |
2005-11-03 |
Added extension capabilitie... |
939 |
# * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions". |
|
49c801b7
»
|
dhh |
2005-11-06 |
Added :include as an option... |
940 |
# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
941 |
# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause. |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
942 |
# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. |
| |
943 |
# * <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. |
|
18a3333a
»
|
NZKoz |
2007-08-28 |
Formatting, grammar and spe... |
944 |
# * <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 |
| |
945 |
# but not include the joined columns. |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
946 |
# |
| |
947 |
# Option examples: |
| |
948 |
# has_and_belongs_to_many :projects |
|
49c801b7
»
|
dhh |
2005-11-06 |
Added :include as an option... |
949 |
# has_and_belongs_to_many :projects, :include => [ :milestones, :manager ] |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
950 |
# has_and_belongs_to_many :nations, :class_name => "Country" |
| |
951 |
# has_and_belongs_to_many :categories, :join_table => "prods_cats" |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
952 |
# has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql => |
|
190e0464
»
|
dhh |
2005-05-19 |
Fixed that :delete_sql in h... |
953 |
# 'DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}' |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
954 |
def has_and_belongs_to_many(association_id, options = {}, &extension) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
955 |
reflection = create_has_and_belongs_to_many_reflection(association_id, options, &extension) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
956 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
957 |
add_multiple_associated_save_callbacks(reflection.name) |
| |
958 |
collection_accessor_methods(reflection, HasAndBelongsToManyAssociation) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
959 |
|
|
35b4bdcf
»
|
jeremy |
2005-11-08 |
Destroy associated has_and_... |
960 |
# Don't use a before_destroy callback since users' before_destroy |
| |
961 |
# callbacks will be executed after the association is wiped out. |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
962 |
old_method = "destroy_without_habtm_shim_for_#{reflection.name}" |
|
88f951a5
»
|
jeremy |
2007-10-27 |
Allow association redefinit... |
963 |
class_eval <<-end_eval unless method_defined?(old_method) |
|
35b4bdcf
»
|
jeremy |
2005-11-08 |
Destroy associated has_and_... |
964 |
alias_method :#{old_method}, :destroy_without_callbacks |
| |
965 |
def destroy_without_callbacks |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
966 |
#{reflection.name}.clear |
|
35b4bdcf
»
|
jeremy |
2005-11-08 |
Destroy associated has_and_... |
967 |
#{old_method} |
| |
968 |
end |
| |
969 |
end_eval |
| |
970 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
971 |
add_association_callbacks(reflection.name, options) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
972 |
end |
| |
973 |
|
| |
974 |
private |
|
2a305949
»
|
technoweenie |
2007-03-27 |
documentation project patch... |
975 |
# Generate a join table name from two provided tables names. |
| |
976 |
# The order of names in join name is determined by lexical precedence. |
| |
977 |
# join_table_name("members", "clubs") |
| |
978 |
# => "clubs_members" |
| |
979 |
# join_table_name("members", "special_clubs") |
| |
980 |
# => "members_special_clubs" |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
981 |
def join_table_name(first_table_name, second_table_name) |
| |
982 |
if first_table_name < second_table_name |
| |
983 |
join_table = "#{first_table_name}_#{second_table_name}" |
| |
984 |
else |
| |
985 |
join_table = "#{second_table_name}_#{first_table_name}" |
| |
986 |
end |
| |
987 |
|
| |
988 |
table_name_prefix + join_table + table_name_suffix |
| |
989 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
990 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
991 |
def association_accessor_methods(reflection, association_proxy_class) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
992 |
ivar = "@#{reflection.name}" |
| |
993 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
994 |
define_method(reflection.name) do |*params| |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
995 |
force_reload = params.first unless params.empty? |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
996 |
|
| |
997 |
association = instance_variable_get(ivar) if instance_variable_defined?(ivar) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
998 |
|
| |
999 |
if association.nil? || force_reload |
| |
1000 |
association = association_proxy_class.new(self, reflection) |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1001 |
retval = association.reload |
|
94a13091
»
|
technoweenie |
2006-08-08 |
Cache nil results for has_o... |
1002 |
if retval.nil? and association_proxy_class == BelongsToAssociation |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1003 |
instance_variable_set(ivar, nil) |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1004 |
return nil |
| |
1005 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1006 |
instance_variable_set(ivar, association) |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1007 |
end |
|
94a13091
»
|
technoweenie |
2006-08-08 |
Cache nil results for has_o... |
1008 |
|
| |
1009 |
association.target.nil? ? nil : association |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1010 |
end |
| |
1011 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1012 |
define_method("#{reflection.name}=") do |new_value| |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1013 |
association = instance_variable_get(ivar) if instance_variable_defined?(ivar) |
| |
1014 |
|
|
4afd6c9f
»
|
jeremy |
2007-05-21 |
belongs_to assignment creat... |
1015 |
if association.nil? || association.target != new_value |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1016 |
association = association_proxy_class.new(self, reflection) |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1017 |
end |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1018 |
|
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1019 |
association.replace(new_value) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1020 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1021 |
instance_variable_set(ivar, new_value.nil? ? nil : association) |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1022 |
end |
|
f8783abf
»
|
dhh |
2005-04-03 |
Made eager loading work eve... |
1023 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1024 |
define_method("set_#{reflection.name}_target") do |target| |
|
18057d2f
»
|
jeremy |
2006-08-17 |
Cache nil results for :incl... |
1025 |
return if target.nil? and association_proxy_class == BelongsToAssociation |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1026 |
association = association_proxy_class.new(self, reflection) |
|
f8783abf
»
|
dhh |
2005-04-03 |
Made eager loading work eve... |
1027 |
association.target = target |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1028 |
instance_variable_set(ivar, association) |
|
f8783abf
»
|
dhh |
2005-04-03 |
Made eager loading work eve... |
1029 |
end |
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1030 |
end |
| |
1031 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1032 |
def collection_reader_method(reflection, association_proxy_class) |
| |
1033 |
define_method(reflection.name) do |*params| |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1034 |
ivar = "@#{reflection.name}" |
| |
1035 |
|
|
bce0e149
»
|
dhh |
2005-01-18 |
Fixed that the belongs_to a... |
1036 |
force_reload = params.first unless params.empty? |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1037 |
association = instance_variable_get(ivar) if instance_variable_defined?(ivar) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1038 |
|
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
1039 |
unless association.respond_to?(:loaded?) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1040 |
association = association_proxy_class.new(self, reflection) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1041 |
instance_variable_set(ivar, association) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
1042 |
end |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1043 |
|
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
1044 |
association.reload if force_reload |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1045 |
|
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
1046 |
association |
| |
1047 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1048 |
|
| |
1049 |
define_method("#{reflection.name.to_s.singularize}_ids") do |
| |
1050 |
send(reflection.name).map(&:id) |
| |
1051 |
end |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1052 |
end |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
1053 |
|
|
b5b16a80
»
|
jeremy |
2007-06-27 |
Define collection singular ... |
1054 |
def collection_accessor_methods(reflection, association_proxy_class, writer = true) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1055 |
collection_reader_method(reflection, association_proxy_class) |
| |
1056 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1057 |
if writer |
| |
1058 |
define_method("#{reflection.name}=") do |new_value| |
| |
1059 |
# Loads proxy class instance (defined in collection_reader_method) if not already loaded |
| |
1060 |
association = send(reflection.name) |
| |
1061 |
association.replace(new_value) |
| |
1062 |
association |
| |
1063 |
end |
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
1064 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1065 |
define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value| |
| |
1066 |
ids = (new_value || []).reject { |nid| nid.blank? } |
| |
1067 |
send("#{reflection.name}=", reflection.class_name.constantize.find(ids)) |
| |
1068 |
end |
|
0092d0ac
»
|
jeremy |
2006-10-01 |
Association collections hav... |
1069 |
end |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
1070 |
end |
| |
1071 |
|
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
1072 |
def add_multiple_associated_save_callbacks(association_name) |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1073 |
method_name = "validate_associated_records_for_#{association_name}".to_sym |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1074 |
ivar = "@#{association_name}" |
| |
1075 |
|
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1076 |
define_method(method_name) do |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1077 |
association = instance_variable_get(ivar) if instance_variable_defined?(ivar) |
| |
1078 |
|
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1079 |
if association.respond_to?(:loaded?) |
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
1080 |
if new_record? |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1081 |
association |
| |
1082 |
else |
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
1083 |
association.select { |record| record.new_record? } |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1084 |
end.each do |record| |
| |
1085 |
errors.add "#{association_name}" unless record.valid? |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
1086 |
end |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1087 |
end |
|
823554ea
»
|
dhh |
2005-01-15 |
Added support for associati... |
1088 |
end |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
1089 |
|
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1090 |
validate method_name |
|
85fbb22f
»
|
dhh |
2006-09-05 |
Backed out of new_record? t... |
1091 |
before_save("@new_record_before_save = new_record?; true") |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1092 |
|
| |
1093 |
after_callback = <<-end_eval |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1094 |
association = instance_variable_get("#{ivar}") if instance_variable_defined?("#{ivar}") |
|
989332c7
»
|
jeremy |
2007-06-21 |
Save associated records onl... |
1095 |
|
|
1c881ca5
»
|
NZKoz |
2007-10-09 |
Ensure that 'autosaving' wo... |
1096 |
records_to_save = if @new_record_before_save |
| |
1097 |
association |
| |
1098 |
elsif association.respond_to?(:loaded?) && association.loaded? |
| |
1099 |
association.select { |record| record.new_record? } |
| |
1100 |
else |
| |
1101 |
[] |
| |
1102 |
end |
| |
1103 |
|
|
cfbd790a
»
|
jeremy |
2007-10-16 |
Fix regression where the as... |
1104 |
records_to_save.each { |record| association.send(:insert_record, record) } unless records_to_save.blank? |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1105 |
|
|
cfbd790a
»
|
jeremy |
2007-10-16 |
Fix regression where the as... |
1106 |
# reconstruct the SQL queries now that we know the owner's id |
| |
1107 |
association.send(:construct_sql) if association.respond_to?(:construct_sql) |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1108 |
end_eval |
|
989332c7
»
|
jeremy |
2007-06-21 |
Save associated records onl... |
1109 |
|
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1110 |
# Doesn't use after_save as that would save associations added in after_create/after_update twice |
| |
1111 |
after_create(after_callback) |
| |
1112 |
after_update(after_callback) |
|
db045dbb
»
|
dhh |
2004-11-23 |
Initial |
1113 |
end |
|
abc895b8
»
|
dhh |
2005-04-03 |
Added new Base.find API and... |
1114 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1115 |
def association_constructor_method(constructor, reflection, association_proxy_class) |
| |
1116 |
define_method("#{constructor}_#{reflection.name}") do |*params| |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1117 |
ivar = "@#{reflection.name}" |
| |
1118 |
|
|
2bdaff4a
»
|
dhh |
2005-06-06 |
Added a second parameter to... |
1119 |
attributees = params.first unless params.empty? |
| |
1120 |
replace_existing = params[1].nil? ? true : params[1] |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1121 |
association = instance_variable_get(ivar) if instance_variable_defined?(ivar) |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
1122 |
|
| |
1123 |
if association.nil? |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1124 |
association = association_proxy_class.new(self, reflection) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1125 |
instance_variable_set(ivar, association) |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
1126 |
end |
| |
1127 |
|
|
bfe6a759
»
|
dhh |
2005-06-15 |
Added actual database-chang... |
1128 |
if association_proxy_class == HasOneAssociation |
| |
1129 |
association.send(constructor, attributees, replace_existing) |
| |
1130 |
else |
| |
1131 |
association.send(constructor, attributees) |
| |
1132 |
end |
|
3b9e90a4
»
|
dhh |
2005-04-11 |
Moved build_association and... |
1133 |
end |
| |
1134 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1135 |
|
|
abc895b8
»
|
dhh |
2005-04-03 |
Added new Base.find API and... |
1136 |
def find_with_associations(options = {}) |
|
31d8169e
»
|
technoweenie |
2006-04-05 |
Fixed that loading includin... |
1137 |
catch :invalid_query do |
|
37adea6f
»
|
dhh |
2007-11-07 |
Address shortcomings of cha... |
1138 |
join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins]) |
|
31d8169e
»
|
technoweenie |
2006-04-05 |
Fixed that loading includin... |
1139 |
rows = select_all_rows(options, join_dependency) |
| |
1140 |
return join_dependency.instantiate(rows) |
| |
1141 |
end |
| |
1142 |
[] |
|
3a7be80f
»
|
dhh |
2006-03-15 |
Change LEFT OUTER JOIN auth... |
1143 |
end |
|
6f344000
»
|
dhh |
2005-04-19 |
Fixed order of loading in e... |
1144 |
|
|
aa04635d
»
|
jeremy |
2007-10-08 |
Update :dependent docs and ... |
1145 |
# See HasManyAssociation#delete_records. Dependent associations |
| |
1146 |
# delete children, otherwise foreign key is set to NULL. |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1147 |
def configure_dependency_for_has_many(reflection) |
|
aa04635d
»
|
jeremy |
2007-10-08 |
Update :dependent docs and ... |
1148 |
if reflection.options.include?(:dependent) |
| |
1149 |
# Add polymorphic type if the :as option is present |
| |
1150 |
dependent_conditions = [] |
| |
1151 |
dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}" |
| |
1152 |
dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as] |
| |
1153 |
dependent_conditions << sanitize_sql(reflection.options[:conditions]) if reflection.options[:conditions] |
| |
1154 |
dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ") |
|
0859779d
»
|
technoweenie |
2006-03-15 |
Allow :dependent options to... |
1155 |
|
|
aa04635d
»
|
jeremy |
2007-10-08 |
Update :dependent docs and ... |
1156 |
case reflection.options[:dependent] |
| |
1157 |
when :destroy |
| |
1158 |
module_eval "before_destroy '#{reflection.name}.each { |o| o.destroy }'" |
| |
1159 |
when :delete_all |
| |
1160 |
module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" |
| |
1161 |
when :nullify |
| |
1162 |
module_eval "before_destroy { |record| #{reflection.class_name}.update_all(%(#{reflection.primary_key_name} = NULL), %(#{dependent_conditions})) }" |
| |
1163 |
else |
| |
1164 |
raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})" |
| |
1165 |
end |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1166 |
end |
| |
1167 |
end |
|
3f1acf49
»
|
jeremy |
2006-09-15 |
Deprecation tests. Remove w... |
1168 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1169 |
def configure_dependency_for_has_one(reflection) |
|
aa04635d
»
|
jeremy |
2007-10-08 |
Update :dependent docs and ... |
1170 |
if reflection.options.include?(:dependent) |
| |
1171 |
case reflection.options[:dependent] |
| |
1172 |
when :destroy |
| |
1173 |
module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" |
| |
1174 |
when :delete |
| |
1175 |
module_eval "before_destroy '#{reflection.class_name}.delete(#{reflection.name}.id) unless #{reflection.name}.nil?'" |
| |
1176 |
when :nullify |
| |
1177 |
module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil) unless #{reflection.name}.nil?'" |
| |
1178 |
else |
| |
1179 |
raise ArgumentError, "The :dependent option expects either :destroy, :delete or :nullify (#{reflection.options[:dependent].inspect})" |
| |
1180 |
end |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1181 |
end |
| |
1182 |
end |
| |
1183 |
|
| |
1184 |
def create_has_many_reflection(association_id, options, &extension) |
| |
1185 |
options.assert_valid_keys( |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
1186 |
:class_name, :table_name, :foreign_key, |
|
6246fad1
»
|
NZKoz |
2007-09-02 |
Remove deprecated functiona... |
1187 |
:dependent, |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
1188 |
:select, :conditions, :include, :order, :group, :limit, :offset, |
|
e3dab67c
»
|
technoweenie |
2007-03-12 |
Allow a polymorphic :source... |
1189 |
:as, :through, :source, :source_type, |
|
50f538b7
»
|
jeremy |
2006-05-06 |
Allow :uniq => true with ha... |
1190 |
:uniq, |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1191 |
:finder_sql, :counter_sql, |
| |
1192 |
:before_add, :after_add, :before_remove, :after_remove, |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
1193 |
:extend |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1194 |
) |
| |
1195 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1196 |
options[:extend] = create_extension_modules(association_id, extension, options[:extend]) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1197 |
|
|
8203a2af
»
|
dhh |
2006-02-26 |
Dont require association cl... |
1198 |
create_reflection(:has_many, association_id, options, self) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1199 |
end |
| |
1200 |
|
| |
1201 |
def create_has_one_reflection(association_id, options) |
| |
1202 |
options.assert_valid_keys( |
|
b3065a51
»
|
jeremy |
2006-02-09 |
Polymorphic join support fo... |
1203 |
:class_name, :foreign_key, :remote, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1204 |
) |
| |
1205 |
|
|
8203a2af
»
|
dhh |
2006-02-26 |
Dont require association cl... |
1206 |
create_reflection(:has_one, association_id, options, self) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1207 |
end |
| |
1208 |
|
| |
1209 |
def create_belongs_to_reflection(association_id, options) |
| |
1210 |
options.assert_valid_keys( |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1211 |
:class_name, :foreign_key, :foreign_type, :remote, :conditions, :order, :include, :dependent, |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1212 |
:counter_cache, :extend, :polymorphic |
| |
1213 |
) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1214 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1215 |
reflection = create_reflection(:belongs_to, association_id, options, self) |
| |
1216 |
|
| |
1217 |
if options[:polymorphic] |
| |
1218 |
reflection.options[:foreign_type] ||= reflection.class_name.underscore + "_type" |
| |
1219 |
end |
| |
1220 |
|
| |
1221 |
reflection |
| |
1222 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1223 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1224 |
def create_has_and_belongs_to_many_reflection(association_id, options, &extension) |
| |
1225 |
options.assert_valid_keys( |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1226 |
:class_name, :table_name, :join_table, :foreign_key, :association_foreign_key, |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
1227 |
:select, :conditions, :include, :order, :group, :limit, :offset, |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1228 |
:uniq, |
|
50f538b7
»
|
jeremy |
2006-05-06 |
Allow :uniq => true with ha... |
1229 |
:finder_sql, :delete_sql, :insert_sql, |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1230 |
:before_add, :after_add, :before_remove, :after_remove, |
|
e5d9ad3e
»
|
dhh |
2005-12-12 |
Added option inheritance fo... |
1231 |
:extend |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1232 |
) |
| |
1233 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1234 |
options[:extend] = create_extension_modules(association_id, extension, options[:extend]) |
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1235 |
|
| |
1236 |
reflection = create_reflection(:has_and_belongs_to_many, association_id, options, self) |
| |
1237 |
|
| |
1238 |
reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name)) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1239 |
|
|
6abda696
»
|
dhh |
2005-12-02 |
Added preliminary support f... |
1240 |
reflection |
| |
1241 |
end |
| |
1242 |
|
|
49d0f0cb
»
|
dhh |
2005-04-18 |
Speeded up eager loading a ... |
1243 |
def reflect_on_included_associations(associations) |
|
251a5d45
»
|
seckar |
2005-09-18 |
Fix eager loading error mes... |
1244 |
[ associations ].flatten.collect { |association| reflect_on_association(association.to_s.intern) } |
|
49d0f0cb
»
|
dhh |
2005-04-18 |
Speeded up eager loading a ... |
1245 |
end |
| |
1246 |
|
|
5b9b904f
»
|
dhh |
2005-07-10 |
Added support for limit and... |
1247 |
def guard_against_unlimitable_reflections(reflections, options) |
| |
1248 |
if (options[:offset] || options[:limit]) && !using_limitable_reflections?(reflections) |
| |
1249 |
raise( |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1250 |
ConfigurationError, |
|
5b9b904f
»
|
dhh |
2005-07-10 |
Added support for limit and... |
1251 |
"You can not use offset and limit together with has_many or has_and_belongs_to_many associations" |
| |
1252 |
) |
| |
1253 |
end |
| |
1254 |
end |
| |
1255 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1256 |
def select_all_rows(options, join_dependency) |
|
49d0f0cb
»
|
dhh |
2005-04-18 |
Speeded up eager loading a ... |
1257 |
connection.select_all( |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1258 |
construct_finder_sql_with_included_associations(options, join_dependency), |
|
49d0f0cb
»
|
dhh |
2005-04-18 |
Speeded up eager loading a ... |
1259 |
"#{name} Load Including Associations" |
| |
1260 |
) |
| |
1261 |
end |
|
057cf491
»
|
dhh |
2005-04-10 |
Added support for has_and_b... |
1262 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1263 |
def construct_finder_sql_with_included_associations(options, join_dependency) |
|
c9c18520
»
|
dhh |
2006-03-27 |
Making ActiveRecord faster ... |
1264 |
scope = scope(:find) |
|
a5fded3e
»
|
dhh |
2007-12-04 |
Fix that options[:from] tab... |
1265 |
sql = "SELECT #{column_aliases(join_dependency)} FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} " |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1266 |
sql << join_dependency.join_associations.collect{|join| join.association_join }.join |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1267 |
|
|
c9c18520
»
|
dhh |
2006-03-27 |
Making ActiveRecord faster ... |
1268 |
add_joins!(sql, options, scope) |
| |
1269 |
add_conditions!(sql, options[:conditions], scope) |
|
d016d9a6
»
|
dhh |
2006-06-03 |
Fixed usage of :limit and w... |
1270 |
add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit]) |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1271 |
|
|
3566be47
»
|
dhh |
2007-08-21 |
Fixed that eager loading qu... |
1272 |
add_group!(sql, options[:group], scope) |
|
9d2da046
»
|
jeremy |
2006-11-09 |
Cache inheritance_column. C... |
1273 |
add_order!(sql, options[:order], scope) |
|
c9c18520
»
|
dhh |
2006-03-27 |
Making ActiveRecord faster ... |
1274 |
add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections) |
|
8dea60b0
»
|
jeremy |
2006-12-05 |
find supports :lock with :i... |
1275 |
add_lock!(sql, options, scope) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1276 |
|
|
abc895b8
»
|
dhh |
2005-04-03 |
Added new Base.find API and... |
1277 |
return sanitize_sql(sql) |
| |
1278 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1279 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1280 |
def add_limited_ids_condition!(sql, options, join_dependency) |
| |
1281 |
unless (id_list = select_limited_ids_list(options, join_dependency)).empty? |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1282 |
sql << "#{condition_word(sql)} #{connection.quote_table_name table_name}.#{primary_key} IN (#{id_list}) " |
|
31d8169e
»
|
technoweenie |
2006-04-05 |
Fixed that loading includin... |
1283 |
else |
| |
1284 |
throw :invalid_query |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1285 |
end |
| |
1286 |
end |
|
4965b1b9
»
|
jeremy |
2007-09-22 |
Correctly quote id list for... |
1287 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1288 |
def select_limited_ids_list(options, join_dependency) |
|
4965b1b9
»
|
jeremy |
2007-09-22 |
Correctly quote id list for... |
1289 |
pk = columns_hash[primary_key] |
| |
1290 |
|
|
5ea76fab
»
|
technoweenie |
2006-04-18 |
Associations#select_limited... |
1291 |
connection.select_all( |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1292 |
construct_finder_sql_for_association_limiting(options, join_dependency), |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1293 |
"#{name} Load IDs For Limited Eager Loading" |
|
4965b1b9
»
|
jeremy |
2007-09-22 |
Correctly quote id list for... |
1294 |
).collect { |row| connection.quote(row[primary_key], pk) }.join(", ") |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1295 |
end |
|
c0bce43e
»
|
jeremy |
2006-11-10 |
Oracle: fix limited id sele... |
1296 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1297 |
def construct_finder_sql_for_association_limiting(options, join_dependency) |
|
e789b26e
»
|
technoweenie |
2006-10-13 |
fix select_limited_ids_list... |
1298 |
scope = scope(:find) |
|
b8657089
»
|
jeremy |
2007-09-15 |
Eager loading respects expl... |
1299 |
is_distinct = !options[:joins].blank? || include_eager_conditions?(options) || include_eager_order?(options) |
|
d49a5fcb
»
|
NZKoz |
2006-02-09 |
* Fix pagination problems w... |
1300 |
sql = "SELECT " |
|
e789b26e
»
|
technoweenie |
2006-10-13 |
fix select_limited_ids_list... |
1301 |
if is_distinct |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1302 |
sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", options[:order]) |
|
e789b26e
»
|
technoweenie |
2006-10-13 |
fix select_limited_ids_list... |
1303 |
else |
| |
1304 |
sql << primary_key |
| |
1305 |
end |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1306 |
sql << " FROM #{connection.quote_table_name table_name} " |
|
c0bce43e
»
|
jeremy |
2006-11-10 |
Oracle: fix limited id sele... |
1307 |
|
|
e789b26e
»
|
technoweenie |
2006-10-13 |
fix select_limited_ids_list... |
1308 |
if is_distinct |
|
c98b471c
»
|
technoweenie |
2006-10-08 |
Reverted old select_limited... |
1309 |
sql << join_dependency.join_associations.collect(&:association_join).join |
|
c9c18520
»
|
dhh |
2006-03-27 |
Making ActiveRecord faster ... |
1310 |
add_joins!(sql, options, scope) |
|
d49a5fcb
»
|
NZKoz |
2006-02-09 |
* Fix pagination problems w... |
1311 |
end |
|
c0bce43e
»
|
jeremy |
2006-11-10 |
Oracle: fix limited id sele... |
1312 |
|
|
c9c18520
»
|
dhh |
2006-03-27 |
Making ActiveRecord faster ... |
1313 |
add_conditions!(sql, options[:conditions], scope) |
|
3566be47
»
|
dhh |
2007-08-21 |
Fixed that eager loading qu... |
1314 |
add_group!(sql, options[:group], scope) |
|
0e452bb0
»
|
dhh |
2007-08-21 |
Fixed that eager loading qu... |
1315 |
|
|
c8b6b482
»
|
Marcel Molina |
2007-10-23 |
Limited eager loading no lo... |
1316 |
if options[:order] && is_distinct |
| |
1317 |
connection.add_order_by_for_association_limiting!(sql, options) |
| |
1318 |
else |
| |
1319 |
add_order!(sql, options[:order], scope) |
|
ef4ac31d
»
|
jeremy |
2007-01-11 |
PostgreSQL: use a subselect... |
1320 |
end |
|
0e452bb0
»
|
dhh |
2007-08-21 |
Fixed that eager loading qu... |
1321 |
|
|
c9c18520
»
|
dhh |
2006-03-27 |
Making ActiveRecord faster ... |
1322 |
add_limit!(sql, options, scope) |
|
0e452bb0
»
|
dhh |
2007-08-21 |
Fixed that eager loading qu... |
1323 |
|
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1324 |
return sanitize_sql(sql) |
| |
1325 |
end |
|
c98b471c
»
|
technoweenie |
2006-10-08 |
Reverted old select_limited... |
1326 |
|
|
2a2afca0
»
|
technoweenie |
2006-04-19 |
Ensure that Associations#in... |
1327 |
# Checks if the conditions reference a table other than the current model table |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1328 |
def include_eager_conditions?(options) |
|
2a2afca0
»
|
technoweenie |
2006-04-19 |
Ensure that Associations#in... |
1329 |
# look in both sets of conditions |
| |
1330 |
conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond| |
| |
1331 |
case cond |
| |
1332 |
when nil then all |
| |
1333 |
when Array then all << cond.first |
| |
1334 |
else all << cond |
| |
1335 |
end |
| |
1336 |
end |
| |
1337 |
return false unless conditions.any? |
|
d22f9c94
»
|
Marcel Molina |
2006-05-21 |
Fix Oracle boolean support ... |
1338 |
conditions.join(' ').scan(/([\.\w]+)\.\w+/).flatten.any? do |condition_table_name| |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1339 |
condition_table_name != table_name |
| |
1340 |
end |
| |
1341 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1342 |
|
|
2a2afca0
»
|
technoweenie |
2006-04-19 |
Ensure that Associations#in... |
1343 |
# Checks if the query order references a table other than the current model's table. |
|
d49a5fcb
»
|
NZKoz |
2006-02-09 |
* Fix pagination problems w... |
1344 |
def include_eager_order?(options) |
| |
1345 |
order = options[:order] |
| |
1346 |
return false unless order |
|
d22f9c94
»
|
Marcel Molina |
2006-05-21 |
Fix Oracle boolean support ... |
1347 |
order.scan(/([\.\w]+)\.\w+/).flatten.any? do |order_table_name| |
|
d49a5fcb
»
|
NZKoz |
2006-02-09 |
* Fix pagination problems w... |
1348 |
order_table_name != table_name |
| |
1349 |
end |
| |
1350 |
end |
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1351 |
|
|
5b9b904f
»
|
dhh |
2005-07-10 |
Added support for limit and... |
1352 |
def using_limitable_reflections?(reflections) |
| |
1353 |
reflections.reject { |r| [ :belongs_to, :has_one ].include?(r.macro) }.length.zero? |
| |
1354 |
end |
| |
1355 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1356 |
def column_aliases(join_dependency) |
| |
1357 |
join_dependency.joins.collect{|join| join.column_names_with_alias.collect{|column_name, aliased_name| |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1358 |
"#{connection.quote_table_name join.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}"}}.flatten.join(", ") |
|
057cf491
»
|
dhh |
2005-04-10 |
Added support for has_and_b... |
1359 |
end |
| |
1360 |
|
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
1361 |
def add_association_callbacks(association_name, options) |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1362 |
callbacks = %w(before_add after_add before_remove after_remove) |
| |
1363 |
callbacks.each do |callback_name| |
|
7cc446ac
»
|
Marcel Molina |
2006-04-15 |
DRY up association collecti... |
1364 |
full_callback_name = "#{callback_name}_for_#{association_name}" |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1365 |
defined_callbacks = options[callback_name.to_sym] |
| |
1366 |
if options.has_key?(callback_name.to_sym) |
| |
1367 |
class_inheritable_reader full_callback_name.to_sym |
|
88f951a5
»
|
jeremy |
2007-10-27 |
Allow association redefinit... |
1368 |
write_inheritable_attribute(full_callback_name.to_sym, [defined_callbacks].flatten) |
| |
1369 |
else |
| |
1370 |
write_inheritable_attribute(full_callback_name.to_sym, []) |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1371 |
end |
| |
1372 |
end |
|
4180e57b
»
|
dhh |
2005-07-04 |
Added callback hooks to ass... |
1373 |
end |
|
057cf491
»
|
dhh |
2005-04-10 |
Added support for has_and_b... |
1374 |
|
|
851dd080
»
|
dhh |
2005-10-18 |
Added support for using lim... |
1375 |
def condition_word(sql) |
| |
1376 |
sql =~ /where/i ? " AND " : "WHERE " |
| |
1377 |
end |
|
e19bd169
»
|
jeremy |
2005-10-01 |
Association validation does... |
1378 |
|
|
81d619ea
»
|
jeremy |
2007-09-17 |
Associations macros accept ... |
1379 |
def create_extension_modules(association_id, block_extension, extensions) |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1380 |
if block_extension |
| |
1381 |
extension_module_name = "#{self.to_s}#{association_id.to_s.camelize}AssociationExtension" |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
1382 |
|
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1383 |
silence_warnings do |
| |
1384 |
Object.const_set(extension_module_name, Module.new(&block_extension)) |
| |
1385 |
end |
| |
1386 |
Array(extensions).push(extension_module_name.constantize) |
| |
1387 |
else |
| |
1388 |
Array(extensions) |
|
c8dd66fd
»
|
dhh |
2005-11-06 |
Made association extensions... |
1389 |
end |
| |
1390 |
end |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1391 |
|
|
f384622a
»
|
dhh |
2006-07-04 |
Doc fixes |
1392 |
class JoinDependency # :nodoc: |
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |
1393 |
attr_reader :joins, :reflections, :table_aliases |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1394 |
|
|
37adea6f
»
|
dhh |
2007-11-07 |
Address shortcomings of cha... |
1395 |
def initialize(base, associations, joins) |
|
ea25e246
»
|
technoweenie |
2006-03-19 |
Quit ignoring default :incl... |
1396 |
@joins = [JoinBase.new(base, joins)] |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1397 |
@associations = associations |
| |
1398 |
@reflections = [] |
| |
1399 |
@base_records_hash = {} |
| |
1400 |
@base_records_in_order = [] |
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |
1401 |
@table_aliases = Hash.new { |aliases, table| aliases[table] = 0 } |
| |
1402 |
@table_aliases[base.table_name] = 1 |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1403 |
build(associations) |
| |
1404 |
end |
| |
1405 |
|
| |
1406 |
def join_associations |
| |
1407 |
@joins[1..-1].to_a |
| |
1408 |
end |
| |
1409 |
|
| |
1410 |
def join_base |
| |
1411 |
@joins[0] |
| |
1412 |
end |
| |
1413 |
|
| |
1414 |
def instantiate(rows) |
| |
1415 |
rows.each_with_index do |row, i| |
| |
1416 |
primary_id = join_base.record_id(row) |
| |
1417 |
unless @base_records_hash[primary_id] |
| |
1418 |
@base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(row)) |
| |
1419 |
end |
|
37adea6f
»
|
dhh |
2007-11-07 |
Address shortcomings of cha... |
1420 |
construct(@base_records_hash[primary_id], @associations, join_associations.dup, row) |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1421 |
end |
|
37adea6f
»
|
dhh |
2007-11-07 |
Address shortcomings of cha... |
1422 |
remove_duplicate_results!(join_base.active_record, @base_records_in_order, @associations) |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1423 |
return @base_records_in_order |
| |
1424 |
end |
| |
1425 |
|
|
204c2755
»
|
jeremy |
2007-10-28 |
Associations: speedup dupli... |
1426 |
def remove_duplicate_results!(base, records, associations) |
| |
1427 |
case associations |
| |
1428 |
when Symbol, String |
| |
1429 |
reflection = base.reflections[associations] |
| |
1430 |
if reflection && [:has_many, :has_and_belongs_to_many].include?(reflection.macro) |
| |
1431 |
records.each { |record| record.send(reflection.name).target.uniq! } |
| |
1432 |
end |
| |
1433 |
when Array |
| |
1434 |
associations.each do |association| |
| |
1435 |
remove_duplicate_results!(base, records, association) |
| |
1436 |
end |
| |
1437 |
when Hash |
| |
1438 |
associations.keys.each do |name| |
| |
1439 |
reflection = base.reflections[name] |
| |
1440 |
is_collection = [:has_many, :has_and_belongs_to_many].include?(reflection.macro) |
| |
1441 |
|
| |
1442 |
parent_records = records.map do |record| |
| |
1443 |
next unless record.send(reflection.name) |
| |
1444 |
is_collection ? record.send(reflection.name).target.uniq! : record.send(reflection.name) |
| |
1445 |
end.flatten.compact |
| |
1446 |
|
| |
1447 |
remove_duplicate_results!(reflection.class_name.constantize, parent_records, associations[name]) unless parent_records.empty? |
| |
1448 |
end |
| |
1449 |
end |
| |
1450 |
end |
| |
1451 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1452 |
protected |
| |
1453 |
def build(associations, parent = nil) |
| |
1454 |
parent ||= @joins.last |
| |
1455 |
case associations |
| |
1456 |
when Symbol, String |
| |
1457 |
reflection = parent.reflections[associations.to_s.intern] or |
| |
1458 |
raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" |
| |
1459 |
@reflections << reflection |
|
37adea6f
»
|
dhh |
2007-11-07 |
Address shortcomings of cha... |
1460 |
@joins << build_join_association(reflection, parent) |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1461 |
when Array |
| |
1462 |
associations.each do |association| |
| |
1463 |
build(association, parent) |
| |
1464 |
end |
| |
1465 |
when Hash |
| |
1466 |
associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| |
| |
1467 |
build(name, parent) |
| |
1468 |
build(associations[name]) |
| |
1469 |
end |
| |
1470 |
else |
| |
1471 |
raise ConfigurationError, associations.inspect |
| |
1472 |
end |
| |
1473 |
end |
| |
1474 |
|
|
37adea6f
»
|
dhh |
2007-11-07 |
Address shortcomings of cha... |
1475 |
# overridden in InnerJoinDependency subclass |
| |
1476 |
def build_join_association(reflection, parent) |
| |
1477 |
JoinAssociation.new(reflection, self, parent) |
| |
1478 |
end |
| |
1479 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1480 |
def construct(parent, associations, joins, row) |
| |
1481 |
case associations |
| |
1482 |
when Symbol, String |
| |
1483 |
while (join = joins.shift).reflection.name.to_s != associations.to_s |
| |
1484 |
raise ConfigurationError, "Not Enough Associations" if joins.empty? |
| |
1485 |
end |
| |
1486 |
construct_association(parent, join, row) |
| |
1487 |
when Array |
| |
1488 |
associations.each do |association| |
| |
1489 |
construct(parent, association, joins, row) |
| |
1490 |
end |
| |
1491 |
when Hash |
| |
1492 |
associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| |
| |
1493 |
association = construct_association(parent, joins.shift, row) |
| |
1494 |
construct(association, associations[name], joins, row) if association |
| |
1495 |
end |
| |
1496 |
else |
| |
1497 |
raise ConfigurationError, associations.inspect |
| |
1498 |
end |
| |
1499 |
end |
| |
1500 |
|
| |
1501 |
def construct_association(record, join, row) |
| |
1502 |
case join.reflection.macro |
| |
1503 |
when :has_many, :has_and_belongs_to_many |
| |
1504 |
collection = record.send(join.reflection.name) |
| |
1505 |
collection.loaded |
|
18057d2f
»
|
jeremy |
2006-08-17 |
Cache nil results for :incl... |
1506 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1507 |
return nil if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil? |
| |
1508 |
association = join.instantiate(row) |
|
204c2755
»
|
jeremy |
2007-10-28 |
Associations: speedup dupli... |
1509 |
collection.target.push(association) |
|
18057d2f
»
|
jeremy |
2006-08-17 |
Cache nil results for :incl... |
1510 |
when :has_one |
| |
1511 |
return if record.id.to_s != join.parent.record_id(row).to_s |
| |
1512 |
association = join.instantiate(row) unless row[join.aliased_primary_key].nil? |
| |
1513 |
record.send("set_#{join.reflection.name}_target", association) |
| |
1514 |
when :belongs_to |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1515 |
return if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil? |
| |
1516 |
association = join.instantiate(row) |
| |
1517 |
record.send("set_#{join.reflection.name}_target", association) |
| |
1518 |
else |
| |
1519 |
raise ConfigurationError, "unknown macro: #{join.reflection.macro}" |
| |
1520 |
end |
| |
1521 |
return association |
| |
1522 |
end |
| |
1523 |
|
|
f384622a
»
|
dhh |
2006-07-04 |
Doc fixes |
1524 |
class JoinBase # :nodoc: |
|
ea25e246
»
|
technoweenie |
2006-03-19 |
Quit ignoring default :incl... |
1525 |
attr_reader :active_record, :table_joins |
|
9c9069a6
»
|
technoweenie |
2006-03-18 |
Fixed has_many :through to ... |
1526 |
delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :to => :active_record |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1527 |
|
|
ea25e246
»
|
technoweenie |
2006-03-19 |
Quit ignoring default :incl... |
1528 |
def initialize(active_record, joins = nil) |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1529 |
@active_record = active_record |
| |
1530 |
@cached_record = {} |
|
ea25e246
»
|
technoweenie |
2006-03-19 |
Quit ignoring default :incl... |
1531 |
@table_joins = joins |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1532 |
end |
| |
1533 |
|
| |
1534 |
def aliased_prefix |
| |
1535 |
"t0" |
| |
1536 |
end |
| |
1537 |
|
| |
1538 |
def aliased_primary_key |
| |
1539 |
"#{ aliased_prefix }_r0" |
| |
1540 |
end |
| |
1541 |
|
| |
1542 |
def aliased_table_name |
| |
1543 |
active_record.table_name |
| |
1544 |
end |
| |
1545 |
|
| |
1546 |
def column_names_with_alias |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1547 |
unless defined?(@column_names_with_alias) |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1548 |
@column_names_with_alias = [] |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1549 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1550 |
([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| |
| |
1551 |
@column_names_with_alias << [column_name, "#{ aliased_prefix }_r#{ i }"] |
| |
1552 |
end |
| |
1553 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1554 |
|
| |
1555 |
@column_names_with_alias |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1556 |
end |
| |
1557 |
|
| |
1558 |
def extract_record(row) |
| |
1559 |
column_names_with_alias.inject({}){|record, (cn, an)| record[cn] = row[an]; record} |
| |
1560 |
end |
| |
1561 |
|
| |
1562 |
def record_id(row) |
| |
1563 |
row[aliased_primary_key] |
| |
1564 |
end |
| |
1565 |
|
| |
1566 |
def instantiate(row) |
|
3d5c9471
»
|
jeremy |
2007-03-17 |
Fix method visibility bug u... |
1567 |
@cached_record[record_id(row)] ||= active_record.send(:instantiate, extract_record(row)) |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1568 |
end |
| |
1569 |
end |
| |
1570 |
|
|
f384622a
»
|
dhh |
2006-07-04 |
Doc fixes |
1571 |
class JoinAssociation < JoinBase # :nodoc: |
|
229c0f43
»
|
technoweenie |
2006-03-17 |
Rework table aliasing to ac... |
1572 |
attr_reader :reflection, :parent, :aliased_table_name, :aliased_prefix, :aliased_join_table_name, :parent_table_name |
|
9412c053
»
|
technoweenie |
2006-03-18 |
Eager Loading support added... |
1573 |
delegate :options, :klass, :through_reflection, :source_reflection, :to => :reflection |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1574 |
|
| |
1575 |
def initialize(reflection, join_dependency, parent = nil) |
|
57af961a
»
|
technoweenie |
2006-03-18 |
Raise error when trying to ... |
1576 |
reflection.check_validity! |
| |
1577 |
if reflection.options[:polymorphic] |
| |
1578 |
raise EagerLoadPolymorphicError.new(reflection) |
| |
1579 |
end |
| |
1580 |
|
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1581 |
super(reflection.klass) |
| |
1582 |
@parent = parent |
| |
1583 |
@reflection = reflection |
| |
1584 |
@aliased_prefix = "t#{ join_dependency.joins.size }" |
|
d22f9c94
»
|
Marcel Molina |
2006-05-21 |
Fix Oracle boolean support ... |
1585 |
@aliased_table_name = table_name #.tr('.', '_') # start with the table name, sub out any .'s |
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
1586 |
@parent_table_name = parent.active_record.table_name |
|
a9fb1544
»
|
technoweenie |
2006-04-05 |
Added support for eagerly i... |
1587 |
|
|
ed10f873
»
|
technoweenie |
2006-03-22 |
STI associations are now al... |
1588 |
if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{aliased_table_name.downcase}\son} |
|
ea25e246
»
|
technoweenie |
2006-03-19 |
Quit ignoring default :incl... |
1589 |
join_dependency.table_aliases[aliased_table_name] += 1 |
| |
1590 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1591 |
|
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |
1592 |
unless join_dependency.table_aliases[aliased_table_name].zero? |
| |
1593 |
# if the table name has been used, then use an alias |
|
7aaf4867
»
|
jeremy |
2006-08-16 |
Included associations: go d... |
1594 |
@aliased_table_name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}" |
|
229c0f43
»
|
technoweenie |
2006-03-17 |
Rework table aliasing to ac... |
1595 |
table_index = join_dependency.table_aliases[aliased_table_name] |
|
7aaf4867
»
|
jeremy |
2006-08-16 |
Included associations: go d... |
1596 |
join_dependency.table_aliases[aliased_table_name] += 1 |
|
229c0f43
»
|
technoweenie |
2006-03-17 |
Rework table aliasing to ac... |
1597 |
@aliased_table_name = @aliased_table_name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 |
|
d7f780e0
»
|
jeremy |
2006-08-14 |
Fix for deep includes on th... |
1598 |
else |
| |
1599 |
join_dependency.table_aliases[aliased_table_name] += 1 |
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |
1600 |
end |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1601 |
|
|
02d34440
»
|
technoweenie |
2006-03-15 |
Alias the has_and_belongs_t... |
1602 |
if reflection.macro == :has_and_belongs_to_many || (reflection.macro == :has_many && reflection.options[:through]) |
|
38bae0a9
»
|
technoweenie |
2006-03-24 |
Change has_many :through to... |
1603 |
@aliased_join_table_name = reflection.macro == :has_and_belongs_to_many ? reflection.options[:join_table] : reflection.through_reflection.klass.table_name |
|
02d34440
»
|
technoweenie |
2006-03-15 |
Alias the has_and_belongs_t... |
1604 |
unless join_dependency.table_aliases[aliased_join_table_name].zero? |
|
229c0f43
»
|
technoweenie |
2006-03-17 |
Rework table aliasing to ac... |
1605 |
@aliased_join_table_name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}_join" |
| |
1606 |
table_index = join_dependency.table_aliases[aliased_join_table_name] |
|
7aaf4867
»
|
jeremy |
2006-08-16 |
Included associations: go d... |
1607 |
join_dependency.table_aliases[aliased_join_table_name] += 1 |
|
229c0f43
»
|
technoweenie |
2006-03-17 |
Rework table aliasing to ac... |
1608 |
@aliased_join_table_name = @aliased_join_table_name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 |
|
7aaf4867
»
|
jeremy |
2006-08-16 |
Included associations: go d... |
1609 |
else |
| |
1610 |
join_dependency.table_aliases[aliased_join_table_name] += 1 |
|
02d34440
»
|
technoweenie |
2006-03-15 |
Alias the has_and_belongs_t... |
1611 |
end |
| |
1612 |
end |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1613 |
end |
| |
1614 |
|
| |
1615 |
def association_join |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1616 |
connection = reflection.active_record.connection |
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |
1617 |
join = case reflection.macro |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1618 |
when :has_and_belongs_to_many |
|
bef071dd
»
|
jeremy |
2007-10-29 |
Introduce finder :joins wit... |
1619 |
" #{join_type} %s ON %s.%s = %s.%s " % [ |
|
229c0f43
»
|
technoweenie |
2006-03-17 |
Rework table aliasing to ac... |
1620 |
table_alias_for(options[:join_table], aliased_join_table_name), |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1621 |
connection.quote_table_name(aliased_join_table_name), |
|
bc97a871
»
|
technoweenie |
2007-01-22 |
Fix incorrect usage of #cla... |
1622 |
options[:foreign_key] || reflection.active_record.to_s.foreign_key, |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1623 |
connection.quote_table_name(parent.aliased_table_name), |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1624 |
reflection.active_record.primary_key] + |
|
bef071dd
»
|
jeremy |
2007-10-29 |
Introduce finder :joins wit... |
1625 |
" #{join_type} %s ON %s.%s = %s.%s " % [ |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1626 |
table_name_and_alias, |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1627 |
connection.quote_table_name(aliased_table_name), |
| |
1628 |
klass.primary_key, |
|
79823e0b
»
|
NZKoz |
2007-11-10 |
Ensure that column names ar... |
1629 |
connection.quote_table_name(aliased_join_table_name), |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1630 |
options[:association_foreign_key] || klass.to_s.foreign_key |
|
55854c41
»
|
dhh |
2006-03-04 |
Added cascading eager loadi... |
1631 |
] |
| |
1632 |
when :has_many, :has_one |
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |
1633 |
case |
| |
1634 |
when reflection.macro == :has_many && reflection.options[:through] |
|
9c9069a6
»
|
technoweenie |
2006-03-18 |
Fixed has_many :through to ... |
1635 |
through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : '' |
|
8b5f4e47
»
|
jeremy |
2007-12-22 |
Ruby 1.9 compat: fix warnin... |
1636 |
|
| |
1637 |
jt_foreign_key = jt_as_extra = jt_source_extra = jt_sti_extra = nil |
| |
1638 |
first_key = second_key = as_extra = nil |
| |
1639 |
|
|
4f00c705
»
|
dhh |
2006-03-05 |
Fixed eager loading problem... |