I just updated my Rails 6 app to Rails 7 and have problems updating my :patch
and :delete
links to Turbo.
For example, in one of my views I have this link...
link_to("Mark as sent", status_url(quote), :data => {:'turbo_method' => :patch})
... which is handled by this controller:
class StatusController < ApplicationController
def update
@quote = Quote.find(params[:id])
@quote.send_it! # Should trigger AASM
flash[:notice] = "Quote marked as sent."
redirect_to edit_quote_path(@quote)
end
end
In the model I am using AASM as a state machine:
class Quote < ApplicationRecord
include AASM
aasm :column => "status" do
state :draft, :initial => true
state :inquired
state :sent
state :downloaded
state :accepted
state :rejected
event :send_it do
transitions :from => [:draft, :inquired], :to => :sent
end
...
event :reset_it do
transitions :from => [:inquired, :sent, :downloaded, :accepted, :rejected], :to => :draft
end
end
end
The problem is that the state machine does not get triggered when I hit the link. The flash message and the redirect work but the state is not changed in the database. When I replace @quote.send_it!
with @quote.update_column(:status, "sent")
it works, however.
Can anybody tell me what I'm missing here?
I don't quite see how turbo is related. Except that I think your redirect isn't actually working:
Redirected to http://127.0.0.1:3000/quotes/1/edit
Completed 302 Found in 18ms (ActiveRecord: 4.3ms | Allocations: 7265)
Started PATCH "/quotes/1/edit" for 127.0.0.1 at 2022-08-12
ActionController::RoutingError (No route matches [PATCH] "/quotes/1/edit"):
# NOTE: ^ not quite a redirect
# v but it doesn't show on a page, it just refreshes the current one.
Started GET "/quotes" for 127.0.0.1 at 2022-08-12 17:51:28 -0400
# and if the current page were /quotes/1/edit then it would look like
# redirect worked, but I was submitting from /quotes.
Update your controller to actually show any errors:
def update
@quote = Quote.find(params[:id])
# NOTE: if transition fails, `send_it!` returns `false`
# (or raises an error for invalid transitions)
# when you run `@quote.update_column(:status, "sent")`
# validations and state machine are not triggered and it works.
if @quote.send_it!
flash.notice = "Quote marked as sent."
else
flash.notice = @quote.errors.full_messages.join(", ")
end
respond_to do |format|
# in case you want add a stream response later
# format.turbo_stream { # TODO }
format.html { redirect_to edit_quote_path(@quote), status: :see_other }
# NOTE: Redirect as a GET request instead of PATCH ^
end
end
Or just add whiny_persistence
flag and check the logs, this will raise validation errors:
aasm column: :status, whiny_persistence: true do