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
recordsfrom 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] = "#{options[:order]}, #{@reflection.options[: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 |