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?
CodePudding user response:
You possibly have two options here:
- To use a combination of
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.
- To not build the Document object in one shot using nested attributes. Instead "open" up your parametes in the
create
action. The build theFrame
and it's relevant children based on_delete
for theFrameVariable
. and the "attach" the finalFrame
to the Document as usual usingbuild
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