Class: ActiveRecord::InsertAll

Inherits:
Object
  • Object
show all
Defined in:
activerecord/lib/active_record/insert_all.rb

Overview

:nodoc:

Defined Under Namespace

Classes: Builder

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) ⇒ InsertAll

Returns a new instance of InsertAll.

Raises:

  • (ArgumentError)

10
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
37
38
# File 'activerecord/lib/active_record/insert_all.rb', line 10

def initialize(model, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
  raise ArgumentError, "Empty list of attributes passed" if inserts.blank?

  @model, @connection, @inserts = model, model.connection, inserts
  @on_duplicate, @update_only, @returning, @unique_by = on_duplicate, update_only, returning, unique_by
  @record_timestamps = record_timestamps.nil? ? model.record_timestamps : record_timestamps

  disallow_raw_sql!(on_duplicate)
  disallow_raw_sql!(returning)

  resolve_attribute_aliases
  configure_on_duplicate_update_logic

  @keys = @inserts.first.keys.map(&:to_s)

  if model.scope_attributes?
    @scope_attributes = model.scope_attributes
    @keys |= @scope_attributes.keys
  end
  @keys = @keys.to_set

  @returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
  @returning = false if @returning == []

  @unique_by = find_unique_index_for(@unique_by)
  @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?

  ensure_valid_options_for_connection!
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.


7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def connection
  @connection
end

#insertsObject (readonly)

Returns the value of attribute inserts.


7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def inserts
  @inserts
end

#keysObject (readonly)

Returns the value of attribute keys.


7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def keys
  @keys
end

#modelObject (readonly)

Returns the value of attribute model.


7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def model
  @model
end

#on_duplicateObject (readonly)

Returns the value of attribute on_duplicate.


8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def on_duplicate
  @on_duplicate
end

#returningObject (readonly)

Returns the value of attribute returning.


8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def returning
  @returning
end

#unique_byObject (readonly)

Returns the value of attribute unique_by.


8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def unique_by
  @unique_by
end

#update_onlyObject (readonly)

Returns the value of attribute update_only.


8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def update_only
  @update_only
end

#update_sqlObject (readonly)

Returns the value of attribute update_sql.


8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def update_sql
  @update_sql
end

Instance Method Details

#executeObject


40
41
42
43
44
45
# File 'activerecord/lib/active_record/insert_all.rb', line 40

def execute
  message = +"#{model} "
  message << "Bulk " if inserts.many?
  message << (on_duplicate == :update ? "Upsert" : "Insert")
  connection.exec_insert_all to_sql, message
end

#keys_including_timestampsObject

TODO: Consider renaming this method, as it only conditionally extends keys, not always


83
84
85
86
87
88
89
# File 'activerecord/lib/active_record/insert_all.rb', line 83

def keys_including_timestamps
  @keys_including_timestamps ||= if record_timestamps?
    keys + model.all_timestamp_attributes_in_model
  else
    keys
  end
end

#map_key_with_valueObject


64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'activerecord/lib/active_record/insert_all.rb', line 64

def map_key_with_value
  inserts.map do |attributes|
    attributes = attributes.stringify_keys
    attributes.merge!(scope_attributes) if scope_attributes
    attributes.reverse_merge!(timestamps_for_create) if record_timestamps?

    verify_attributes(attributes)

    keys_including_timestamps.map do |key|
      yield key, attributes[key]
    end
  end
end

#primary_keysObject


51
52
53
# File 'activerecord/lib/active_record/insert_all.rb', line 51

def primary_keys
  Array(connection.schema_cache.primary_keys(model.table_name))
end

#record_timestamps?Boolean

Returns:

  • (Boolean)

78
79
80
# File 'activerecord/lib/active_record/insert_all.rb', line 78

def record_timestamps?
  @record_timestamps
end

#skip_duplicates?Boolean

Returns:

  • (Boolean)

56
57
58
# File 'activerecord/lib/active_record/insert_all.rb', line 56

def skip_duplicates?
  on_duplicate == :skip
end

#updatable_columnsObject


47
48
49
# File 'activerecord/lib/active_record/insert_all.rb', line 47

def updatable_columns
  @updatable_columns ||= keys - readonly_columns - unique_by_columns
end

#update_duplicates?Boolean

Returns:

  • (Boolean)

60
61
62
# File 'activerecord/lib/active_record/insert_all.rb', line 60

def update_duplicates?
  on_duplicate == :update
end