Class: ActiveRecord::Associations::AssociationCollection

Inherits:
AssociationProxy show all
Defined in:
lib/active_record/associations/association_collection.rb

Overview

:nodoc:

Instance Attribute Summary

Attributes inherited from AssociationProxy

#reflection

Instance Method Summary collapse

Methods inherited from AssociationProxy

#===, #aliased_table_name, #conditions, #initialize, #loaded, #loaded?, #proxy_owner, #proxy_reflection, #proxy_respond_to?, #proxy_target, #reload, #respond_to?, #target, #target=

Constructor Details

This class inherits a constructor from ActiveRecord::Associations::AssociationProxy

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class ActiveRecord::Associations::AssociationProxy

Instance Method Details

#<<(*records) ⇒ Object Also known as: push, concat

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.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/active_record/associations/association_collection.rb', line 18

def <<(*records)
  result = true
  load_target

  @owner.transaction do
    flatten_deeper(records).each do |record|
      raise_on_type_mismatch(record)
      callback(:before_add, record)
      result &&= insert_record(record) unless @owner.new_record?
      @target << record
      callback(:after_add, record)
    end
  end

  result && self
end

#clearObject

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



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/active_record/associations/association_collection.rb', line 68

def clear
  return self if length.zero? # forces load_target if hasn't happened already

  if @reflection.options[:dependent] && @reflection.options[:dependent] == :delete_all
    destroy_all
  else          
    delete_all
  end

  self
end

#create(attributes = {}) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/active_record/associations/association_collection.rb', line 88

def create(attributes = {})
  # Can't use Base.create since the foreign key may be a protected attribute.
  if attributes.is_a?(Array)
    attributes.collect { |attr| create(attr) }
  else
    record = build(attributes)
    if @owner.new_record?
      ActiveSupport::Deprecation.warn("Calling .create on a has_many association without saving its owner will not work in rails 2.0, you probably want .build instead")
    else
      record.save
    end
    record
  end
end

#delete(*records) ⇒ Object

Remove records from this association. Does not destroy records.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/active_record/associations/association_collection.rb', line 51

def delete(*records)
  records = flatten_deeper(records)
  records.each { |record| raise_on_type_mismatch(record) }
  records.reject! { |record| @target.delete(record) if record.new_record? }
  return if records.empty?
  
  @owner.transaction do
    records.each { |record| callback(:before_remove, record) }
    delete_records(records)
    records.each do |record|
      @target.delete(record)
      callback(:after_remove, record)
    end
  end
end

#delete_allObject

Remove all records from this association



39
40
41
42
43
# File 'lib/active_record/associations/association_collection.rb', line 39

def delete_all
  load_target
  delete(@target)
  reset_target!
end

#destroy_allObject



80
81
82
83
84
85
86
# File 'lib/active_record/associations/association_collection.rb', line 80

def destroy_all
  @owner.transaction do
    each { |record| record.destroy }
  end

  reset_target!
end

#empty?Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/active_record/associations/association_collection.rb', line 123

def empty?
  size.zero?
end

#lengthObject

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?



119
120
121
# File 'lib/active_record/associations/association_collection.rb', line 119

def length
  load_target.size
end

#replace(other_array) ⇒ Object

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



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/active_record/associations/association_collection.rb', line 140

def replace(other_array)
  other_array.each { |val| raise_on_type_mismatch(val) }

  load_target
  other   = other_array.size < 100 ? other_array : other_array.to_set
  current = @target.size < 100 ? @target : @target.to_set

  @owner.transaction do
    delete(@target.select { |v| !other.include?(v) })
    concat(other_array.select { |v| !current.include?(v) })
  end
end

#resetObject



11
12
13
14
# File 'lib/active_record/associations/association_collection.rb', line 11

def reset
  reset_target!
  @loaded = false
end

#sizeObject

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.



106
107
108
109
110
111
112
113
114
115
# File 'lib/active_record/associations/association_collection.rb', line 106

def size
  if loaded? && !@reflection.options[:uniq]
    @target.size
  elsif !loaded? && !@reflection.options[:uniq] && @target.is_a?(Array)
    unsaved_records = Array(@target.detect { |r| r.new_record? })
    unsaved_records.size + count_records
  else
    count_records
  end
end

#sum(*args, &block) ⇒ Object

Calculate sum using SQL, not Enumerable



46
47
48
# File 'lib/active_record/associations/association_collection.rb', line 46

def sum(*args, &block)
  calculate(:sum, *args, &block)
end

#to_aryObject



6
7
8
9
# File 'lib/active_record/associations/association_collection.rb', line 6

def to_ary
  load_target
  @target.to_ary
end

#uniq(collection = self) ⇒ Object



127
128
129
130
131
132
133
134
135
136
# File 'lib/active_record/associations/association_collection.rb', line 127

def uniq(collection = self)
  seen = Set.new
  collection.inject([]) do |kept, record|
    unless seen.include?(record.id)
      kept << record
      seen << record.id
    end
    kept
  end
end