Class: ActiveRecord::Associations::HasManyThroughAssociation
- Inherits:
-
AssociationProxy
- Object
- AssociationProxy
- ActiveRecord::Associations::HasManyThroughAssociation
- Defined in:
- lib/active_record/associations/has_many_through_association.rb
Overview
:nodoc:
Instance Attribute Summary
Attributes inherited from AssociationProxy
Instance Method Summary collapse
-
#<<(*records) ⇒ Object
Adds records to the association.
- #build(attrs = nil) ⇒ Object (also: #new)
- #count(*args) ⇒ Object
- #create!(attrs = nil) ⇒ Object
-
#delete(*records) ⇒ Object
Removes
records
from this association. - #find(*args) ⇒ Object
-
#initialize(owner, reflection) ⇒ HasManyThroughAssociation
constructor
A new instance of HasManyThroughAssociation.
- #reset ⇒ Object
-
#size ⇒ Object
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.
-
#sum(*args, &block) ⇒ Object
Calculate sum using SQL, not Enumerable.
Methods inherited from AssociationProxy
#===, #aliased_table_name, #inspect, #loaded, #loaded?, #proxy_owner, #proxy_reflection, #proxy_respond_to?, #proxy_target, #reload, #respond_to?, #target, #target=
Constructor Details
#initialize(owner, reflection) ⇒ HasManyThroughAssociation
Returns a new instance of HasManyThroughAssociation.
4 5 6 7 8 9 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 4 def initialize(owner, reflection) super reflection.check_validity! @finder_sql = construct_conditions construct_sql end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object (protected)
131 132 133 134 135 136 137 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 131 def method_missing(method, *args, &block) if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) super else @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.send(method, *args, &block) } end end |
Instance Method Details
#<<(*records) ⇒ Object
Adds records to the association. The source record and its associates must have ids in order to create records associating them, so this will raise ActiveRecord::HasManyThroughCantAssociateNewRecords if either is a new record. Calls create! so you can rescue errors.
The :before_add and :after_add callbacks are not yet supported.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 49 def <<(*records) return if records.empty? through = @reflection.through_reflection raise ActiveRecord::HasManyThroughCantAssociateNewRecords.new(@owner, through) if @owner.new_record? klass = through.klass klass.transaction do flatten_deeper(records).each do |associate| raise_on_type_mismatch(associate) raise ActiveRecord::HasManyThroughCantAssociateNewRecords.new(@owner, through) unless associate.respond_to?(:new_record?) && !associate.new_record? @owner.send(@reflection.through_reflection.name).proxy_target << klass.send(:with_scope, :create => construct_join_attributes(associate)) { klass.create! } @target << associate if loaded? end end self end |
#build(attrs = nil) ⇒ Object Also known as: new
94 95 96 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 94 def build(attrs = nil) raise ActiveRecord::HasManyThroughCantAssociateNewRecords.new(@owner, @reflection.through_reflection) end |
#count(*args) ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 120 def count(*args) column_name, = @reflection.klass.send(:construct_count_options_from_args, *args) if @reflection.[:uniq] # This is needed because 'SELECT count(DISTINCT *)..' is not valid sql statement. column_name = "#{@reflection.klass.table_name}.#{@reflection.klass.primary_key}" if column_name == :all .merge!(:distinct => true) end @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, ) } end |
#create!(attrs = nil) ⇒ Object
99 100 101 102 103 104 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 99 def create!(attrs = nil) @reflection.klass.transaction do self << (object = @reflection.klass.send(:with_scope, :create => attrs) { @reflection.klass.create! }) object end end |
#delete(*records) ⇒ Object
Removes records
from this association. Does not destroy records
.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 71 def delete(*records) records = flatten_deeper(records) records.each { |associate| raise_on_type_mismatch(associate) } through = @reflection.through_reflection raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) if @owner.new_record? load_target klass = through.klass klass.transaction do flatten_deeper(records).each do |associate| raise_on_type_mismatch(associate) raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) unless associate.respond_to?(:new_record?) && !associate.new_record? @owner.send(through.name).proxy_target.delete(klass.delete_all(construct_join_attributes(associate))) @target.delete(associate) end end self end |
#find(*args) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 11 def find(*args) = args. conditions = "#{@finder_sql}" if sanitized_conditions = sanitize_sql([:conditions]) conditions << " AND (#{sanitized_conditions})" end [:conditions] = conditions if [:order] && @reflection.[:order] [:order] = "#{[:order]}, #{@reflection.[:order]}" elsif @reflection.[:order] [:order] = @reflection.[:order] end [:select] = construct_select([:select]) [:from] ||= construct_from [:joins] = construct_joins([:joins]) [:include] = @reflection.source_reflection.[:include] if [:include].nil? () # Pass through args exactly as we received them. args << @reflection.klass.find(*args) end |
#reset ⇒ Object
38 39 40 41 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 38 def reset @target = [] @loaded = false end |
#size ⇒ Object
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.
109 110 111 112 113 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 109 def size return @owner.send(:read_attribute, cached_counter_attribute_name) if has_cached_counter? return @target.size if loaded? return count end |
#sum(*args, &block) ⇒ Object
Calculate sum using SQL, not Enumerable
116 117 118 |
# File 'lib/active_record/associations/has_many_through_association.rb', line 116 def sum(*args, &block) calculate(:sum, *args, &block) end |