Class: ActiveRecord::Associations::HasManyAssociation

Inherits:
AssociationCollection show all
Defined in:
lib/active_record/associations/has_many_association.rb

Overview

:nodoc:

Instance Attribute Summary

Attributes inherited from AssociationProxy

#reflection

Instance Method Summary collapse

Methods inherited from AssociationCollection

#<<, #clear, #create, #delete, #delete_all, #destroy_all, #empty?, #length, #replace, #reset, #size, #sum, #to_ary, #uniq

Methods inherited from AssociationProxy

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

Constructor Details

#initialize(owner, reflection) ⇒ HasManyAssociation

Returns a new instance of HasManyAssociation.



4
5
6
7
# File 'lib/active_record/associations/has_many_association.rb', line 4

def initialize(owner, reflection)
  super
  construct_sql
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (protected)



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/active_record/associations/has_many_association.rb', line 96

def method_missing(method, *args, &block)
  if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method))
    super
  else
    create_scoping = {}
    set_belongs_to_association_for(create_scoping)

    @reflection.klass.with_scope(
      :create => create_scoping,
      :find => {
        :conditions => @finder_sql, 
        :joins      => @join_sql, 
        :readonly   => false
      }
    ) do
      @reflection.klass.send(method, *args, &block)
    end
  end
end

Instance Method Details

#build(attributes = {}) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/active_record/associations/has_many_association.rb', line 9

def build(attributes = {})
  if attributes.is_a?(Array)
    attributes.collect { |attr| build(attr) }
  else
    record = @reflection.klass.new(attributes)
    set_belongs_to_association_for(record)
    
    @target ||= [] unless loaded?
    @target << record
    
    record
  end
end

#count(*args) ⇒ Object

Count the number of associated records. All arguments are optional.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/active_record/associations/has_many_association.rb', line 43

def count(*args)
  if @reflection.options[:counter_sql]
    @reflection.klass.count_by_sql(@counter_sql)
  elsif @reflection.options[:finder_sql]
    @reflection.klass.count_by_sql(@finder_sql)
  else
    column_name, options = @reflection.klass.send(:construct_count_options_from_legacy_args, *args)          
    options[:conditions] = options[:conditions].nil? ?
      @finder_sql :
      @finder_sql + " AND (#{sanitize_sql(options[:conditions])})"
    options[:include] ||= @reflection.options[:include]

    @reflection.klass.count(column_name, options)
  end
end

#find(*args) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/active_record/associations/has_many_association.rb', line 59

def find(*args)
  options = Base.send(:extract_options_from_args!, args)

  # If using a custom finder_sql, scan the entire collection.
  if @reflection.options[:finder_sql]
    expects_array = args.first.kind_of?(Array)
    ids = args.flatten.compact.uniq

    if ids.size == 1
      id = ids.first
      record = load_target.detect { |record| id == record.id }
      expects_array ? [ record ] : record
    else
      load_target.select { |record| ids.include?(record.id) }
    end
  else
    conditions = "#{@finder_sql}"
    if sanitized_conditions = sanitize_sql(options[:conditions])
      conditions << " AND (#{sanitized_conditions})"
    end
    options[:conditions] = conditions

    if options[:order] && @reflection.options[:order]
      options[:order] = "#{options[:order]}, #{@reflection.options[:order]}"
    elsif @reflection.options[:order]
      options[:order] = @reflection.options[:order]
    end

    merge_options_from_reflection!(options)

    # Pass through args exactly as we received them.
    args << options
    @reflection.klass.find(*args)
  end
end

#find_all(runtime_conditions = nil, orderings = nil, limit = nil, joins = nil) ⇒ Object

DEPRECATED.



24
25
26
27
28
29
30
31
32
33
# File 'lib/active_record/associations/has_many_association.rb', line 24

def find_all(runtime_conditions = nil, orderings = nil, limit = nil, joins = nil)
  if @reflection.options[:finder_sql]
    @reflection.klass.find_by_sql(@finder_sql)
  else
    conditions = @finder_sql
    conditions += " AND (#{sanitize_sql(runtime_conditions)})" if runtime_conditions
    orderings ||= @reflection.options[:order]
    @reflection.klass.find_all(conditions, orderings, limit, joins)
  end
end

#find_first(conditions = nil, orderings = nil) ⇒ Object

DEPRECATED. Find the first associated record. All arguments are optional.



37
38
39
# File 'lib/active_record/associations/has_many_association.rb', line 37

def find_first(conditions = nil, orderings = nil)
  find_all(conditions, orderings, 1).first
end