Home > Back-end >  Why is my AASM state machine not triggered with Rails 7 Turbo patch links?
Why is my AASM state machine not triggered with Rails 7 Turbo patch links?

Time:08-13

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?

CodePudding user response:

Not sure where you got the mark_as_ from, change that to @quote.aasm.fire! status.

Edit

Sorry, not status, needs to be the event, just use the right event.

CodePudding user response:

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
  • Related