pluginaweek / state_machine

Adds support for creating state machines for attributes on any Ruby class
http://www.pluginaweek.org
MIT License
3.74k stars 507 forks source link

After callbacks stopped working after upgrading to 1.2.0 #289

Open markmilman opened 10 years ago

markmilman commented 10 years ago

Hi,

My after callbacks are no longer executed after upgrading from 1.1.2 to 1.2.0. I confirmed that by rolling back to 1.1.2:

Following is the state machine with the after callback any => :active

  state_machine :status, :initial => :draft do
    state :draft, value: STATUS_DRAFT
    state :active, value: STATUS_ACTIVE do
      validate ->(agr) { agr.check_rules }
    end
    state :pending_org_approval, value: STATUS_PENDING_ORG_APPROVAL do

      validates_presence_of :posting_rules
    end
    state :pending_cparty_approval, value: STATUS_PENDING_CPARTY_APPROVAL do

      validates_presence_of :posting_rules
    end
    state :rejected_by_org, value: STATUS_REJECTED_BY_ORG do

      validates_presence_of :posting_rules
    end
    state :rejected_by_cparty, value: STATUS_REJECTED_BY_CPARTY do

      validates_presence_of :posting_rules
    end
    state :canceled, value: STATUS_CANCELED
    state :replaced, value: STATUS_REPLACED

    # create the accounts after activating the agreement
    after_transition any => :active do |agreement, transition|
      unless Account.where("organization_id = ? and accountable_id = ? and accountable_type = 'Organization'", agreement.organization_id, agreement.counterparty_id).present?
        Account.create!(organization: agreement.organization, accountable: agreement.counterparty) if agreement.organization.subcontrax_member?
      end
      unless Account.where("organization_id = ? and accountable_id = ? and accountable_type = 'Organization'", agreement.counterparty_id, agreement.organization_id).present?
        Account.create!(organization: agreement.counterparty, accountable: agreement.organization) if agreement.counterparty.subcontrax_member?
      end
    end

    event :submit_for_approval do
      transition :draft => :pending_cparty_approval, if: ->(agreement) { agreement.creator.organization == agreement.organization && agreement.counterparty.subcontrax_member? }
      transition :draft => :pending_org_approval, if: ->(agreement) { agreement.creator.organization == agreement.counterparty && agreement.organization.subcontrax_member? }
    end

    event :activate do
      transition :draft => :active, if: ->(agreement) { !agreement.organization.subcontrax_member? }
      transition :draft => :active, if: ->(agreement) { !agreement.counterparty.subcontrax_member? }
    end

    event :submit_change do
      transition [:pending_org_approval, :rejected_by_cparty] => :pending_cparty_approval
      transition [:pending_cparty_approval, :rejected_by_org] => :pending_org_approval
    end

    event :accept do
      transition [:pending_org_approval, :pending_cparty_approval] => :active
    end

    event :reject do
      transition :pending_org_approval => :rejected_by_org
      transition :pending_cparty_approval => :rejected_by_cparty
    end

    event :cancel do
      transition :active => :canceled
    end

  end
markmilman commented 10 years ago

did some further analysis and it turns out that the issue occurs only when invoking the event using a web request and update_attributes. The other thing worth mentioning is that the state is changing successfully, but none of the after callbacks is being invoked

jmuheim commented 10 years ago

Did you find any solution for this? We are having a similar problem here with the following transition:

    state_machine :state, initial: :draft do
      event :process do
        transition [:draft, :crashed] => :processing
      end

      after_transition any => :processing do |activity, transition|
        # This is never called
      end
    end

I have re-created the very same state machine in an empty class, and there it works. So it has to be some side-effect by something else in the class, but it's a quite complex one and I couldn't find the answer yet.

jmuheim commented 10 years ago

In our case, the rollback to statemachine v1.2.0 didn't solve the problem though, it seems to be the upgrade from Rails3.2 to Rails4.

jmuheim commented 10 years ago

Maybe this is related? https://github.com/pluginaweek/state_machine/pull/280