问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/20396103/how-to-define-a-state-machine-in-a-concern