diff options
Diffstat (limited to 'activerecord/lib')
8 files changed, 32 insertions, 26 deletions
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index d2934c830a..44596f4424 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -275,6 +275,7 @@ module ActiveRecord def build_record(attributes) reflection.build_association(attributes) do |record| initialize_attributes(record, attributes) + yield(record) if block_given? end end diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index d61d105544..7f1df9a21d 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -105,9 +105,7 @@ module ActiveRecord if attributes.is_a?(Array) attributes.collect { |attr| build(attr, &block) } else - add_to_target(build_record(attributes)) do |record| - yield(record) if block_given? - end + add_to_target(build_record(attributes, &block)) end end @@ -361,8 +359,7 @@ module ActiveRecord attributes.collect { |attr| _create_record(attr, raise, &block) } else transaction do - add_to_target(build_record(attributes)) do |record| - yield(record) if block_given? + add_to_target(build_record(attributes, &block)) do |record| insert_record(record, true, raise) { @_was_loaded = loaded? @association_ids = nil diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index 59929b8c4e..617956c768 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -90,7 +90,7 @@ module ActiveRecord def build_record(attributes) ensure_not_nested - record = super(attributes) + record = super inverse = source_reflection.inverse_of if inverse diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb index d211884135..390bfd8b08 100644 --- a/activerecord/lib/active_record/associations/has_one_association.rb +++ b/activerecord/lib/active_record/associations/has_one_association.rb @@ -106,7 +106,7 @@ module ActiveRecord end end - def _create_record(attributes, raise_error = false) + def _create_record(attributes, raise_error = false, &block) unless owner.persisted? raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved" end diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb index ead89bfe6c..cfab16a745 100644 --- a/activerecord/lib/active_record/associations/singular_association.rb +++ b/activerecord/lib/active_record/associations/singular_association.rb @@ -17,9 +17,8 @@ module ActiveRecord replace(record) end - def build(attributes = {}) - record = build_record(attributes) - yield(record) if block_given? + def build(attributes = {}, &block) + record = build_record(attributes, &block) set_new_record(record) record end @@ -62,9 +61,8 @@ module ActiveRecord replace(record) end - def _create_record(attributes, raise_error = false) - record = build_record(attributes) - yield(record) if block_given? + def _create_record(attributes, raise_error = false, &block) + record = build_record(attributes, &block) saved = record.save set_new_record(record) raise RecordInvalid.new(record) if !saved && raise_error diff --git a/activerecord/lib/active_record/associations/through_association.rb b/activerecord/lib/active_record/associations/through_association.rb index 5afb0bc068..15e6565e69 100644 --- a/activerecord/lib/active_record/associations/through_association.rb +++ b/activerecord/lib/active_record/associations/through_association.rb @@ -114,7 +114,7 @@ module ActiveRecord attributes[inverse.foreign_key] = target.id end - super(attributes) + super end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 5f090d16cd..582ac516c7 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -356,8 +356,12 @@ module ActiveRecord type = type.to_sym if type options = options.dup - if @columns_hash[name] && @columns_hash[name].primary_key? - raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table." + if @columns_hash[name] + if @columns_hash[name].primary_key? + raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table." + else + raise ArgumentError, "you can't define an already defined column '#{name}'." + end end index_options = options.delete(:index) diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 82adb19f5b..c5d5fca672 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -328,10 +328,12 @@ module ActiveRecord # but call it after the commit of a destroyed object. def committed!(should_run_callbacks: true) #:nodoc: if should_run_callbacks && (destroyed? || persisted?) + @_committed_already_called = true _run_commit_without_transaction_enrollment_callbacks _run_commit_callbacks end ensure + @_committed_already_called = false force_clear_transaction_record_state end @@ -380,6 +382,7 @@ module ActiveRecord end private + attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback # Save the new record state and id of a record so it can be restored later if a transaction fails. def remember_transaction_record_state @@ -390,6 +393,15 @@ module ActiveRecord frozen?: frozen?, ) @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1 + remember_new_record_before_last_commit + end + + def remember_new_record_before_last_commit + if _committed_already_called + @_new_record_before_last_commit = false + else + @_new_record_before_last_commit = @_start_transaction_state[:new_record] + end end # Clear the new record state and id of a record. @@ -421,22 +433,16 @@ module ActiveRecord end end - # Determine if a record was created or destroyed in a transaction. State should be one of :new_record or :destroyed. - def transaction_record_state(state) - @_start_transaction_state[state] - end - # Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks. def transaction_include_any_action?(actions) actions.any? do |action| case action when :create - transaction_record_state(:new_record) - when :destroy - defined?(@_trigger_destroy_callback) && @_trigger_destroy_callback + persisted? && @_new_record_before_last_commit when :update - !(transaction_record_state(:new_record) || destroyed?) && - (defined?(@_trigger_update_callback) && @_trigger_update_callback) + !(@_new_record_before_last_commit || destroyed?) && _trigger_update_callback + when :destroy + _trigger_destroy_callback end end end |