Reputation: 6981
I'm trying to discard an associated record before its parent is saved in a Rails callback if a condition is met. Doing a throw :abort
doesn't stop the record from saving. Am I doing something wrong?
class Document < ApplicationRecord
has_many :frames, as: :parent, dependent: :destroy
has_many :frame_variables, through: :frames, dependent: :destroy
accepts_nested_attributes_for :frames, allow_destroy: true
end
class Frame < ApplicationRecord
belongs_to :parent, polymorphic: true
has_many :frame_variables
end
class FrameVariable < ApplicationRecord
belongs_to :frame
attr_accessor :_delete
before_save :discard_if_cleared
def discard_if_cleared
throw :abort if _delete == true
end
end
def create
@document = current_user.documents.new(document_params)
if @document.save
redirect_to documents_path
else
redirect_to new_document_path(template: @document.template), flash: { error: "The document you tried to create was invalid: #{@document.errors.full_messages}" }
end
end
What am I missing?
Upvotes: 1
Views: 144
Reputation: 18028
You possibly have two options here:
accepts_nested_attributes_for
and :reject_if
block to not save the association conditionally by checking the _delete
in the :reject_if
block.Catch there is in your current setup your accepts_nested_attributes_for
is on Document and not on Frame. If that can be changed this might work out.
create
action. The build the Frame
and it's relevant children based on _delete
for the FrameVariable
. and the "attach" the final Frame
to the Document as usual using build
Sorry for a vague answer, but not understanding the full context of your models and what you can modify, these are the general approaches I can think of.
Finally doing it in before_save
is def a bad idea because when you are building out the full model using accepts_nested_attributes_for
rails will use a commit block and revert everything if something in the chain rejects it.
This blog goes in some details about using :reject_if
https://www.pluralsight.com/guides/ruby-on-rails-nested-attributes
Here's another example of using the reject block:
Rails: use REJECT_IF only on CREATE action for nested attributes
Upvotes: 1