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.

Tracking Sidekiq workers exceptions with Errbit/Airbrake

If you’ve set up Errbit/Airbrake and you use Sidekiq, by default you would expect, that Errbit tracks things that happen in Sidekiq workers as well. Unfortunately it doesn’t.

In order to make Sidekiq retry failed jobs in needs to catch and handle exceptions on its own. And that’s the reason why you need a bit of “magic” to make it work with Errbit. You need to add an custom error handler that will notify Errbit app about errors that occured in Sidekiq workers.

To do so, just create an initializer like this:

# Errbit error catching for Sidekiq workers
Sidekiq.configure_server do |config|
  config.error_handlers << Proc.new { |ex,ctx_hash| Airbrake.notify_or_ignore(ex, ctx_hash) }
end

And that’s all!

22
Jul 2014
POSTED BY
DISCUSSION 2 Comments