Running with Ruby

Tag: state machine

State Machine gem and Rails (ActiveModel) 4.1 – NoMethodError – protected method ‘around_validation’ called for StateMachine

State machine is a great gem, unfortunately it’s not working with Rails 4.1. If you upgrade your app and try to use it, you’ll end up with following error:

NoMethodError - protected method `around_validation' called for #<StateMachine::Machine:0x007fd4ea002c80>:
  activesupport (4.1.4) lib/active_support/callbacks.rb:447:in `public_send'
  activesupport (4.1.4) lib/active_support/callbacks.rb:447:in `block in make_lambda'
  activesupport (4.1.4) lib/active_support/callbacks.rb:298:in `call'
  activesupport (4.1.4) lib/active_support/callbacks.rb:298:in `block in halting'
  activesupport (4.1.4) lib/active_support/callbacks.rb:86:in `call'
  activesupport (4.1.4) lib/active_support/callbacks.rb:86:in `run_callbacks'
  activemodel (4.1.4) lib/active_model/validations/callbacks.rb:111:in `run_validations!'
  activemodel (4.1.4) lib/active_model/validations.rb:317:in `valid?'
  activerecord (4.1.4) lib/active_record/validations.rb:70:in `valid?'
  activerecord (4.1.4) lib/active_record/validations.rb:77:in `perform_validations'
  activerecord (4.1.4) lib/active_record/validations.rb:57:in `save!'
  activerecord (4.1.4) lib/active_record/attribute_methods/dirty.rb:29:in `save!'
  activerecord (4.1.4) lib/active_record/transactions.rb:273:in `block in save!'
  activerecord (4.1.4) lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:199:in `transaction'
  activerecord (4.1.4) lib/active_record/transactions.rb:208:in `transaction'
  activerecord (4.1.4) lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
  activerecord (4.1.4) lib/active_record/transactions.rb:273:in `save!'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:487:in `block in save!'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:502:in `block (2 levels) in around_save'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:150:in `block in run_actions'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:170:in `catch_exceptions'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:148:in `run_actions'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:133:in `run_callbacks'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:212:in `run_callbacks'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block (2 levels) in perform'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `catch'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block in perform'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:186:in `within_transaction'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:62:in `perform'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:502:in `block in around_save'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:530:in `block in transaction'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
  activerecord (4.1.4) lib/active_record/transactions.rb:208:in `transaction'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:529:in `transaction'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:501:in `around_save'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:487:in `save!'
  activerecord (4.1.4) lib/active_record/validations.rb:41:in `create!'
  app/models/concerns/channel/tracked.rb:139:in `find_or_create_channel'
  app/models/concerns/channel/tracked.rb:128:in `track'
  app/controllers/reporting/tracked_channels_controller.rb:20:in `create'
  actionpack (4.1.4) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (4.1.4) lib/abstract_controller/base.rb:189:in `process_action'
  actionpack (4.1.4) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (4.1.4) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
  activesupport (4.1.4) lib/active_support/callbacks.rb:113:in `call'
  activesupport (4.1.4) lib/active_support/callbacks.rb:113:in `call'

Here’s a fix. Just put it into your initializers:

# Stathe machine
module StateMachine
  # Extensions for integrations of state machine
  module Integrations
    # ActiveModel extension that fixes the non-public around_validation error
    module ActiveModel
      send :public, :around_validation
    end
  end
end

Note: It works also for any non-Rails, ActiveModel based apps.

State machine gem: undefined method underscore for ActiveModel::Name

If  you encounter this issue:

Failure/Error: ::Mobile::App::Talk.make!
NoMethodError:
  undefined method `underscore' for #<ActiveModel::Name:0x0000000ebae880>

When using state machine, machinist and machinist_mongo, please add this to your app/config/initializers/state_machine.rb:

# It seems that there is no underscore method on ActiveModel name
# It is added here, so it will be accessible and state machine
# can work. It should be removed after this is fixed
class ActiveModel::Name
  def underscore
    to_s.underscore
  end
end

This should be enough to make it work :)

Copyright © 2018 Running with Ruby

Theme by Anders NorenUp ↑