Class: ActiveRecord::InsertAll
Do not use. This class is for internal use only.
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | activerecord/lib/active_record/insert_all.rb |
Class Method Summary
Instance Attribute Summary
- #connection readonly
- #inserts readonly
- #keys readonly
- #model readonly
- #on_duplicate readonly
- #record_timestamps? ⇒ Boolean readonly
- #returning readonly
- #skip_duplicates? ⇒ Boolean readonly
- #unique_by readonly
- #update_duplicates? ⇒ Boolean readonly
- #update_only readonly
- #update_sql readonly
- #custom_update_sql_provided? ⇒ Boolean readonly private
Instance Method Summary
- #execute
-
#keys_including_timestamps
TODO: Consider renaming this method, as it only conditionally extends keys, not always.
- #map_key_with_value
- #primary_keys
- #updatable_columns
- #configure_on_duplicate_update_logic private
- #disallow_raw_sql!(value) private
- #ensure_valid_options_for_connection! private
- #find_unique_index_for(unique_by) private
- #has_attribute_aliases?(attributes) ⇒ Boolean private
- #readonly_columns private
- #resolve_attribute_alias(attribute) private
- #resolve_attribute_aliases private
- #resolve_sti private
- #timestamps_for_create private
- #to_sql private
- #unique_by_columns private
- #unique_indexes private
- #verify_attributes(attributes) private
Constructor Details
.new(relation, connection, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) ⇒ InsertAll
# File 'activerecord/lib/active_record/insert_all.rb', line 18
def initialize(relation, connection, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) @relation = relation @model, @connection, @inserts = relation.model, connection, inserts.map(&:stringify_keys) @on_duplicate, @update_only, @returning, @unique_by = on_duplicate, update_only, returning, unique_by @record_timestamps = .nil? ? model. : disallow_raw_sql!(on_duplicate) disallow_raw_sql!(returning) if @inserts.empty? @keys = [] else resolve_sti resolve_attribute_aliases @keys = @inserts.first.keys end @scope_attributes = relation.scope_for_create.except(@model.inheritance_column) @keys |= @scope_attributes.keys @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) configure_on_duplicate_update_logic end
Class Method Details
.execute(relation)
[ GitHub ]Instance Attribute Details
#connection (readonly)
[ GitHub ]
#custom_update_sql_provided? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'activerecord/lib/active_record/insert_all.rb', line 145
def custom_update_sql_provided? @custom_update_sql_provided ||= Arel.arel_node?(on_duplicate) end
#inserts (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 7
attr_reader :model, :connection, :inserts, :keys
#keys (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 7
attr_reader :model, :connection, :inserts, :keys
#model (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 7
attr_reader :model, :connection, :inserts, :keys
#on_duplicate (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 8
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
#record_timestamps? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/insert_all.rb', line 87
def @record_timestamps end
#returning (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 8
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
#skip_duplicates? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/insert_all.rb', line 65
def skip_duplicates? on_duplicate == :skip end
#unique_by (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 8
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
#update_duplicates? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'activerecord/lib/active_record/insert_all.rb', line 69
def update_duplicates? on_duplicate == :update end
#update_only (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 8
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
#update_sql (readonly)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 8
attr_reader :on_duplicate, :update_only, :returning, :unique_by, :update_sql
Instance Method Details
#configure_on_duplicate_update_logic (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 129
def configure_on_duplicate_update_logic if custom_update_sql_provided? && update_only.present? raise ArgumentError, "You can't set :update_only and provide custom update SQL via :on_duplicate at the same time" end if update_only.present? @updatable_columns = Array(update_only) @on_duplicate = :update elsif custom_update_sql_provided? @update_sql = on_duplicate @on_duplicate = :update elsif @on_duplicate == :update && updatable_columns.empty? @on_duplicate = :skip end end
#disallow_raw_sql!(value) (private)
# File 'activerecord/lib/active_record/insert_all.rb', line 212
def disallow_raw_sql!(value) return if !value.is_a?(String) || Arel.arel_node?(value) raise ArgumentError, "Dangerous query method (method whose arguments are used as raw " \ "SQL) called: #{value}. " \ "Known-safe values can be passed " \ "by wrapping them in Arel.sql()." end
#ensure_valid_options_for_connection! (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 173
def if returning && !connection.supports_insert_returning? raise ArgumentError, "#{connection.class} does not support :returning" end if skip_duplicates? && !connection.supports_insert_on_duplicate_skip? raise ArgumentError, "#{connection.class} does not support skipping duplicates" end if update_duplicates? && !connection.supports_insert_on_duplicate_update? raise ArgumentError, "#{connection.class} does not support upsert" end if unique_by && !connection.supports_insert_conflict_target? raise ArgumentError, "#{connection.class} does not support :unique_by" end end
#execute
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 48
def execute return ActiveRecord::Result.empty if inserts.empty? = +"#{model} " << "Bulk " if inserts.many? << (on_duplicate == :update ? "Upsert" : "Insert") connection.exec_insert_all to_sql, end
#find_unique_index_for(unique_by) (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 149
def find_unique_index_for(unique_by) if !connection.supports_insert_conflict_target? return if unique_by.nil? raise ArgumentError, "#{connection.class} does not support :unique_by" end name_or_columns = unique_by || model.primary_key match = Array(name_or_columns).map(&:to_s) sorted_match = match.sort if index = unique_indexes.find { |i| match.include?(i.name) || Array(i.columns).sort == sorted_match } index elsif match == primary_keys unique_by.nil? ? nil : ActiveRecord::ConnectionAdapters::IndexDefinition.new(model.table_name, "#{model.table_name}_primary_key", true, match) else raise ArgumentError, "No unique index found for #{name_or_columns}" end end
#has_attribute_aliases?(attributes) ⇒ Boolean
(private)
#keys_including_timestamps
TODO: Consider renaming this method, as it only conditionally extends keys, not always
#map_key_with_value
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 73
def map_key_with_value inserts.map do |attributes| attributes = attributes.stringify_keys attributes.merge!(@scope_attributes) attributes.reverse_merge!( ) if verify_attributes(attributes) .map do |key| yield key, attributes[key] end end end
#readonly_columns (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 197
def readonly_columns primary_keys + model.readonly_attributes end
#resolve_attribute_alias(attribute) (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 125
def resolve_attribute_alias(attribute) model.attribute_alias(attribute) || attribute end
#resolve_attribute_aliases (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 114
def resolve_attribute_aliases return unless has_attribute_aliases?(@inserts.first) @inserts = @inserts.map do |insert| insert.transform_keys { |attribute| resolve_attribute_alias(attribute) } end @update_only = Array(@update_only).map { |attribute| resolve_attribute_alias(attribute) } if @update_only @unique_by = Array(@unique_by).map { |attribute| resolve_attribute_alias(attribute) } if @unique_by end
#resolve_sti (private)
[ GitHub ]#timestamps_for_create (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 221
def model. .index_with(connection. ) end
#to_sql (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 192
def to_sql connection.build_insert_sql(ActiveRecord::InsertAll::Builder.new(self)) end
#unique_by_columns (private)
[ GitHub ]#unique_indexes (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 169
def unique_indexes @model.schema_cache.indexes(model.table_name).select(&:unique) end
#updatable_columns
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 57
def updatable_columns @updatable_columns ||= keys - readonly_columns - unique_by_columns end
#verify_attributes(attributes) (private)
[ GitHub ]# File 'activerecord/lib/active_record/insert_all.rb', line 206
def verify_attributes(attributes) if != attributes.keys.to_set raise ArgumentError, "All objects being inserted must have the same keys" end end