class ActiveRecord::Associations::HasOneAssociation
:nodoc:
= Active Record Has One Association
def _create_record(attributes, raise_error = false, &block)
def _create_record(attributes, raise_error = false, &block) unless owner.persisted? raise ActiveRecord::RecordNotSaved.new("You cannot call create unless the parent is saved", owner) end super end
def delete(method = options[:dependent])
def delete(method = options[:dependent]) if load_target case method when :delete target.delete when :destroy target.destroyed_by_association = reflection target.destroy throw(:abort) unless target.destroyed? when :destroy_async primary_key_column = target.class.primary_key.to_sym id = target.public_send(primary_key_column) enqueue_destroy_association( owner_model_name: owner.class.to_s, owner_id: owner.id, association_class: reflection.klass.to_s, association_ids: [id], association_primary_key_column: primary_key_column, ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil) ) when :nullify target.update_columns(nullified_owner_attributes) if target.persisted? end end end
def handle_dependency
def handle_dependency case options[:dependent] when :restrict_with_exception raise ActiveRecord::DeleteRestrictionError.new(reflection.name) if load_target when :restrict_with_error if load_target record = owner.class.human_attribute_name(reflection.name).downcase owner.errors.add(:base, :'restrict_dependent_destroy.has_one', record: record) throw(:abort) end else delete end end
def nullify_owner_attributes(record)
def nullify_owner_attributes(record) record[reflection.foreign_key] = nil end
def remove_target!(method)
def remove_target!(method) case method when :delete target.delete when :destroy target.destroyed_by_association = reflection if target.persisted? target.destroy end else nullify_owner_attributes(target) remove_inverse_instance(target) if target.persisted? && owner.persisted? && !target.save set_owner_attributes(target) raise RecordNotSaved.new( "Failed to remove the existing associated #{reflection.name}. " \ "The record failed to save after its foreign key was set to nil.", target ) end end end
def replace(record, save = true)
def replace(record, save = true) raise_on_type_mismatch!(record) if record return target unless load_target || record assigning_another_record = target != record if assigning_another_record || record.has_changes_to_save? save &&= owner.persisted? transaction_if(save) do remove_target!(options[:dependent]) if target && !target.destroyed? && assigning_another_record if record set_owner_attributes(record) set_inverse_instance(record) if save && !record.save nullify_owner_attributes(record) set_owner_attributes(target) if target raise RecordNotSaved.new("Failed to save the new associated #{reflection.name}.", record) end end end end self.target = record end
def set_new_record(record)
the record is instantiated, and so they are set straight away and do not need to be
is because the setting of the foreign keys is actually handled by the scoping when
The reason that the save param for replace is false, if for create (not just build),
def set_new_record(record) replace(record, false) end
def transaction_if(value, &block)
def transaction_if(value, &block) if value reflection.klass.transaction(&block) else yield end end