How to define a state_machine in a Concern?

activesupport-concern, ruby-on-rails-4, state-machine

Solution

Okay. I am feeling really stupid. One should not `extend` a class with a module, but `include` that module. Obviously.

# Tested with:
class DeployableDouble
  include Deployable
end

One of these things that you oversee once written. Also, extending the `ActiveRecord::Base` is not needed, since state_machine is just plain old Ruby and works on a generic Ruby Object.

Problem

I am trying to factor out some duplicated logic into a concern. Part of the duplicated logic is a state_machine. Simplified, the `Database`, `Site`, `SftpUser` and more contain, amongst others, this: ``` class Database < ActiveRecord::Base # ... state_machine :deploy_state, initial: :halted do state :pending end end ``` I'm attempting to refactor this into a concern: ``` module Deployable extend ActiveSupport::Concern included do state_machine :deploy_state, initial: :halted do state :pending end end end # Tested with: class DeployableDouble < ActiveRecord::Base extend Deployable end describe DeployableDouble do let(:subject) { DeployableDouble.new } it "should have default state halted" do subject.deploy_state.must_equal "halted" end end ``` However, this is not the correct way to implement a `state_machnine` in a `concern`, because this results in: `NoMethodError: undefined method 'deploy_state' for <DeployableDouble:0xb9831f8>`. Which indicates that the Double did not get a statemachine assigned at all. Is the `included do` actually the right callback to implement this? Is it maybe an issue with `state_machine`, it needing a subclass of ActiveRecord::Base or so? Something I'm not getting? I am pretty new to the concept of Concerns.

Original source