Class: ActiveRecord::Associations::AssociationCollection

Public Instance Methods


<< (*records)

Add records to this association. Returns self so method calls may be chained. Since << flattens its argument list and inserts each record, push and concat behave identically.

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 18
18:       def <<(*records)
19:         result = true
20:         load_target if @owner.new_record?
21: 
22:         @owner.transaction do
23:           flatten_deeper(records).each do |record|
24:             raise_on_type_mismatch(record)
25:             callback(:before_add, record)
26:             result &&= insert_record(record) unless @owner.new_record?
27:             @target << record
28:             callback(:after_add, record)
29:           end
30:         end
31: 
32:         result && self
33:       end

any? () {|*block_args| ...}

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 128
128:       def any?
129:         if block_given?
130:           method_missing(:any?) { |*block_args| yield(*block_args) }
131:         else
132:           !empty?
133:         end
134:       end

clear ()

Removes all records from this association. Returns self so method calls may be chained.

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 72
72:       def clear
73:         return self if length.zero? # forces load_target if it hasn't happened already
74: 
75:         if @reflection.options[:dependent] && @reflection.options[:dependent] == :destroy
76:           destroy_all
77:         else          
78:           delete_all
79:         end
80: 
81:         self
82:       end

concat (*records)

Alias for #<<


create (attrs = {})

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 92
92:       def create(attrs = {})
93:         if attrs.is_a?(Array)
94:           attrs.collect { |attr| create(attr) }
95:         else
96:           create_record(attrs) { |record| record.save }
97:         end
98:       end

create! (attrs = {})

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 100
100:       def create!(attrs = {})
101:         create_record(attrs) { |record| record.save! }
102:       end

delete (*records)

Remove records from this association. Does not destroy records.

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 55
55:       def delete(*records)
56:         records = flatten_deeper(records)
57:         records.each { |record| raise_on_type_mismatch(record) }
58:         records.reject! { |record| @target.delete(record) if record.new_record? }
59:         return if records.empty?
60:         
61:         @owner.transaction do
62:           records.each { |record| callback(:before_remove, record) }
63:           delete_records(records)
64:           records.each do |record|
65:             @target.delete(record)
66:             callback(:after_remove, record)
67:           end
68:         end
69:       end

delete_all ()

Remove all records from this association

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 39
39:       def delete_all
40:         load_target
41:         delete(@target)
42:         reset_target!
43:       end

destroy_all ()

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 84
84:       def destroy_all
85:         @owner.transaction do
86:           each { |record| record.destroy }
87:         end
88: 
89:         reset_target!
90:       end

empty? ()

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 124
124:       def empty?
125:         size.zero?
126:       end

include? (record)

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 162
162:       def include?(record)
163:         return false unless record.is_a?(@reflection.klass)
164:         return @target.include?(record) if loaded?
165:         exists?(record)
166:       end

length ()

Returns the size of the collection by loading it and calling size on the array. If you want to use this method to check whether the collection is empty, use collection.length.zero? instead of collection.empty?

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 120
120:       def length
121:         load_target.size
122:       end

push (*records)

Alias for #<<


replace (other_array)

Replace this collection with other_array This will perform a diff and delete/add only records that have changed.

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 149
149:       def replace(other_array)
150:         other_array.each { |val| raise_on_type_mismatch(val) }
151: 
152:         load_target
153:         other   = other_array.size < 100 ? other_array : other_array.to_set
154:         current = @target.size < 100 ? @target : @target.to_set
155: 
156:         @owner.transaction do
157:           delete(@target.select { |v| !other.include?(v) })
158:           concat(other_array.select { |v| !current.include?(v) })
159:         end
160:       end

reset ()

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 11
11:       def reset
12:         reset_target!
13:         @loaded = false
14:       end

size ()

Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn‘t been loaded and calling collection.size if it has. If it‘s more likely than not that the collection does have a size larger than zero and you need to fetch that collection afterwards, it‘ll take one less SELECT query if you use length.

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 107
107:       def size
108:         if @owner.new_record? || (loaded? && !@reflection.options[:uniq])
109:           @target.size
110:         elsif !loaded? && !@reflection.options[:uniq] && @target.is_a?(Array)
111:           unsaved_records = Array(@target.detect { |r| r.new_record? })
112:           unsaved_records.size + count_records
113:         else
114:           count_records
115:         end
116:       end

sum (*args) {|*block_args| ...}

Calculate sum using SQL, not Enumerable

    # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 46
46:       def sum(*args)
47:         if block_given?
48:           calculate(:sum, *args) { |*block_args| yield(*block_args) }
49:         else
50:           calculate(:sum, *args)
51:         end
52:       end

to_ary ()

   # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 6
6:       def to_ary
7:         load_target
8:         @target.to_ary
9:       end

uniq (collection = self)

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 136
136:       def uniq(collection = self)
137:         seen = Set.new
138:         collection.inject([]) do |kept, record|
139:           unless seen.include?(record.id)
140:             kept << record
141:             seen << record.id
142:           end
143:           kept
144:         end
145:       end

Protected Instance Methods


construct_scope ()

overloaded in derived Association classes to provide useful scoping depending on association type.

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 190
190:         def construct_scope
191:           {}
192:         end

find_target ()

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 198
198:         def find_target
199:           records =
200:             if @reflection.options[:finder_sql]
201:               @reflection.klass.find_by_sql(@finder_sql)
202:             else
203:               find(:all)
204:             end
205: 
206:           @reflection.options[:uniq] ? uniq(records) : records
207:         end

method_missing (method, *args) {|*block_args| ...}

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 169
169:         def method_missing(method, *args)
170:           if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
171:             if block_given?
172:               super { |*block_args| yield(*block_args) }
173:             else
174:               super
175:             end
176:           elsif @reflection.klass.scopes.include?(method)
177:             @reflection.klass.scopes[method].call(self, *args)
178:           else          
179:             with_scope(construct_scope) do
180:               if block_given?
181:                 @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) }
182:               else
183:                 @reflection.klass.send(method, *args)
184:               end
185:             end
186:           end
187:         end

reset_target! ()

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 194
194:         def reset_target!
195:           @target = Array.new
196:         end

Private Instance Methods


add_record_to_target_with_callbacks (record) {|record| ...}

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 232
232:         def add_record_to_target_with_callbacks(record)
233:           callback(:before_add, record)
234:           yield(record) if block_given?
235:           @target ||= [] unless loaded?
236:           @target << record
237:           callback(:after_add, record)
238:           record
239:         end

build_record (attrs) {|*block_args| ...}

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 222
222:         def build_record(attrs)
223:           attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
224:           record = @reflection.klass.new(attrs)
225:           if block_given?
226:             add_record_to_target_with_callbacks(record) { |*block_args| yield(*block_args) }
227:           else
228:             add_record_to_target_with_callbacks(record)
229:           end
230:         end

callback (method, record)

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 241
241:         def callback(method, record)
242:           callbacks_for(method).each do |callback|
243:             case callback
244:               when Symbol
245:                 @owner.send(callback, record)
246:               when Proc, Method
247:                 callback.call(@owner, record)
248:               else
249:                 if callback.respond_to?(method)
250:                   callback.send(method, @owner, record)
251:                 else
252:                   raise ActiveRecordError, "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method."
253:                 end
254:             end
255:           end
256:         end

callbacks_for (callback_name)

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 258
258:         def callbacks_for(callback_name)
259:           full_callback_name = "#{callback_name}_for_#{@reflection.name}"
260:           @owner.class.read_inheritable_attribute(full_callback_name.to_sym) || []
261:         end

create_record (attrs) {|*block_args| ...}

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 211
211:         def create_record(attrs)
212:           attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
213:           ensure_owner_is_not_new
214:           record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) { @reflection.klass.new(attrs) }
215:           if block_given?
216:             add_record_to_target_with_callbacks(record) { |*block_args| yield(*block_args) }
217:           else
218:             add_record_to_target_with_callbacks(record)
219:           end
220:         end

ensure_owner_is_not_new ()

     # File vendor/rails/activerecord/lib/active_record/associations/association_collection.rb, line 263
263:         def ensure_owner_is_not_new
264:           if @owner.new_record?
265:             raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
266:           end
267:         end