AmV
AmV

Reputation: 61

Can I use the _destroy attribute in a non-nested form?

Say I have something like this in my controller:

FacultyMembership.update(params[:faculty_memberships].keys,
                         params[:faculty_memberships].values)

and whenever the _destroy key in params[:faculty_memberships].values is true, the record is destroyed.

Is there something like this in rails? I realize there are other ways of doing this, I was just curious if something like this existed.

Upvotes: 2

Views: 1419

Answers (2)

Vladimir Eltchinov
Vladimir Eltchinov

Reputation: 31

This code worked for me:

class FacultyMembership < ApplicationRecord
  attr_accessor :_destroy

  def _destroy= value
    self.destroy if value.present?
  end  
end

Possibly this can break nested forms with destroy - didn't check.

Upvotes: 0

Yan Foto
Yan Foto

Reputation: 11378

Short answer

no!

Long answer

Still no! It is true that it works on nested attributes:

If you want to destroy the associated model through the attributes hash, you have to enable it first using the :allow_destroy option. Now, when you add the _destroy key to the attributes hash, with a value that evaluates to true, you will destroy the associated model.

But why not trying it out in the console:

?> bundle exec rails c
?> m = MyModel.create attr_1: "some_value", attr_2: "some_value"
?> m.update(_destroy: '1') # or _destroy: true
?> ActiveRecord::UnknownAttributeError: unknown attribute '_destroy' for MyModel

This is because the update implementation is the following:

# File activerecord/lib/active_record/persistence.rb, line 245
def update(attributes)
  # The following transaction covers any possible database side-effects of the
  # attributes assignment. For example, setting the IDs of a child collection.
  with_transaction_returning_status do
    assign_attributes(attributes)
    save
  end
end

and the source for assign_attributes is:

# File activerecord/lib/active_record/attribute_assignment.rb, line 23
def assign_attributes(new_attributes)
  if !new_attributes.respond_to?(:stringify_keys)
    raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
  end
  return if new_attributes.blank?

  attributes                  = new_attributes.stringify_keys
  multi_parameter_attributes  = []
  nested_parameter_attributes = []

  attributes = sanitize_for_mass_assignment(attributes)

  attributes.each do |k, v|
    if k.include?("(")
      multi_parameter_attributes << [ k, v ]
    elsif v.is_a?(Hash)
      nested_parameter_attributes << [ k, v ]
    else
      _assign_attribute(k, v)
    end
  end

  assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
  assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
end

Upvotes: 3

Related Questions