I've got some STI in my data model. There are two types of Task
records: PrimaryTask
and SecondaryTask
. So my ActiveRecord models look like this:
class Task < ActiveRecord::Base
end
class PrimaryTask < Task
has_many :secondary_tasks
end
class SecondaryTask < Task
belongs_to :primary_task
end
I want to provide a way to "promote" a SecondaryTask
to a PrimaryTask
permanently (as in, persisted in the database). From perusing the docs, looks like the #becomes!
method is what I want, but I can't get it to save the changes in the database.
id = 1
secondary_task = SecondaryTask.find(id)
primary_task = secondary_task.becomes!(PrimaryTask)
primary_task.id # => 1
primary_task.class # => PrimaryTask
primary_task.type # => "PrimaryTask"
primary_task.new_record? # => false
primary_task.changes # => { "type"=>[nil,"PrimaryTask"] }
primary_task.save! # => true
primary_task.reload # => raises ActiveRecord::RecordNotFound: Couldn't find PrimaryTask with id=1 [WHERE "tasks"."type" IN ('PrimaryTask')]
# Note: secondary_task.reload works fine, because the task's type did not change in the DB
Any idea what's up? I tried the following things, to no avail. Am I misunderstanding becomes!
?
- Force the record to be 'dirty' in case the
save!
call was a no-op because none of the attributes were marked dirty (primary_task.update_attributes(updated_at: Time.current)
-- didn't help) - Destroy
secondary_task
in case the fact that they both have the sameid
was a problem. Didn't help. TheSecondaryTask
record was deleted but noPrimaryTask
was created (despite the call tosave!
returningtrue
)
UPDATE 1
The logs show the probable issue:
UPDATE "tasks" SET "type" = $1 WHERE "tasks"."type" IN ('PrimaryTask') AND "tasks"."id" = 2 [["type", "PrimaryTask"]]
So the update is failing because the WHERE
clause causes the record not to be found.
#becomes
instead of#becomes!
? – Aguardientico