Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,26 @@ also know, if you need any interface beyond `load_workflow_state` and
`persist_workflow_state` methods to implement an adapter for your
favorite database.


Custom Versions of Existing Adapters
------------------------------------

Other adapters (such as a custom ActiveRecord plugin) can be selected by adding a `workflow_adapter` class method, eg.

```ruby
class Example < ActiveRecord::Base
def self.workflow_adapter
MyCustomAdapter
end
include Workflow

# ...
end
```

(The above will include `MyCustomAdapter` *instead* of `Workflow::Adapter::ActiveRecord`.)


Accessing your workflow specification
-------------------------------------

Expand Down
16 changes: 8 additions & 8 deletions lib/workflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,15 @@ def self.included(klass)

klass.extend ClassMethods

if Object.const_defined?(:ActiveRecord)
if klass < ActiveRecord::Base
klass.send :include, Adapter::ActiveRecord::InstanceMethods
klass.send :extend, Adapter::ActiveRecord::Scopes
klass.before_validation :write_initial_state
# Look for a hook; otherwise detect based on ancestor class.
if klass.respond_to?(:workflow_adapter)
klass.send :include, klass.workflow_adapter
else
if Object.const_defined?(:ActiveRecord) && klass < ActiveRecord::Base
klass.send :include, Adapter::ActiveRecord
end
elsif Object.const_defined?(:Remodel)
if klass < Adapter::Remodel::Entity
klass.send :include, Remodel::InstanceMethods
if Object.const_defined?(:Remodel) && klass < Adapter::Remodel::Entity
klass.send :include, Adapter::Remodel::InstanceMethods
end
end
end
Expand Down
6 changes: 6 additions & 0 deletions lib/workflow/adapters/active_record.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
module Workflow
module Adapter
module ActiveRecord
def self.included(klass)
klass.send :include, Adapter::ActiveRecord::InstanceMethods
klass.send :extend, Adapter::ActiveRecord::Scopes
klass.before_validation :write_initial_state
end

module InstanceMethods
def load_workflow_state
read_attribute(self.class.workflow_column)
Expand Down
52 changes: 52 additions & 0 deletions test/adapter_hook_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require File.join(File.dirname(__FILE__), 'test_helper')
require 'workflow'
class AdapterHookTest < ActiveRecordTestCase
test 'hook to choose adapter' do

ActiveRecord::Schema.define do
create_table(:examples) { |t| t.string :workflow_state }
end

class DefaultAdapter < ActiveRecord::Base
self.table_name = :examples
include Workflow
workflow do
state(:initial) { event :progress, :transitions_to => :last }
state(:last)
end
end

class ChosenByHookAdapter < ActiveRecord::Base
self.table_name = :examples
attr_reader :foo
def self.workflow_adapter
Module.new do
def load_workflow_state
@foo if defined?(@foo)
end
def persist_workflow_state(new_value)
@foo = new_value
end
end
end

include Workflow
workflow do
state(:initial) { event :progress, :transitions_to => :last }
state(:last)
end
end

default = DefaultAdapter.create
assert default.initial?
default.progress!
assert default.last?
assert DefaultAdapter.find(default.id).last?, 'should have persisted via ActiveRecord'

hook = ChosenByHookAdapter.create
assert hook.initial?
hook.progress!
assert_equal hook.foo, 'last', 'should have "persisted" with custom adapter'
assert ChosenByHookAdapter.find(hook.id).initial?, 'should not have persisted via ActiveRecord'
end
end