mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
commit
3b58a64e13
4 changed files with 231 additions and 0 deletions
17
README.md
17
README.md
|
@ -278,6 +278,23 @@ class Job < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sequel
|
||||||
|
|
||||||
|
AASM also supports Sequel besides ActiveRecord.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class Job < Sequel::Model
|
||||||
|
include AASM
|
||||||
|
|
||||||
|
aasm do # default column: aasm_state
|
||||||
|
...
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
However it's not yet feature completed as ActiveRecord. For example,
|
||||||
|
no scope would be defined as in ActiveRecord. See _Automatic Scopes_.
|
||||||
|
|
||||||
### Mongoid
|
### Mongoid
|
||||||
|
|
||||||
AASM also supports persistence to Mongodb if you're using Mongoid. Make sure
|
AASM also supports persistence to Mongodb if you're using Mongoid. Make sure
|
||||||
|
|
|
@ -12,6 +12,9 @@ module AASM
|
||||||
elsif hierarchy.include?("Mongoid::Document")
|
elsif hierarchy.include?("Mongoid::Document")
|
||||||
require_files_for(:mongoid)
|
require_files_for(:mongoid)
|
||||||
base.send(:include, AASM::Persistence::MongoidPersistence)
|
base.send(:include, AASM::Persistence::MongoidPersistence)
|
||||||
|
elsif hierarchy.include?("Sequel::Model")
|
||||||
|
require_files_for(:sequel)
|
||||||
|
base.send(:include, AASM::Persistence::SequelPersistence)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
108
lib/aasm/persistence/sequel_persistence.rb
Normal file
108
lib/aasm/persistence/sequel_persistence.rb
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
module AASM
|
||||||
|
module Persistence
|
||||||
|
module SequelPersistence
|
||||||
|
def self.included(base)
|
||||||
|
base.send(:include, AASM::Persistence::Base)
|
||||||
|
base.send(:include, AASM::Persistence::SequelPersistence::InstanceMethods)
|
||||||
|
end
|
||||||
|
|
||||||
|
module InstanceMethods
|
||||||
|
def before_validation
|
||||||
|
aasm_ensure_initial_state
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def before_create
|
||||||
|
aasm_ensure_initial_state
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the value of the aasm_column - called from <tt>aasm.current_state</tt>
|
||||||
|
#
|
||||||
|
# If it's a new record, and the aasm state column is blank it returns the initial state
|
||||||
|
#
|
||||||
|
# class Foo < Sequel::Model
|
||||||
|
# include AASM
|
||||||
|
# aasm :column => :status do
|
||||||
|
# state :opened
|
||||||
|
# state :closed
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# foo = Foo.new
|
||||||
|
# foo.current_state # => :opened
|
||||||
|
# foo.close
|
||||||
|
# foo.current_state # => :closed
|
||||||
|
#
|
||||||
|
# foo = Foo[1]
|
||||||
|
# foo.current_state # => :opened
|
||||||
|
# foo.aasm_state = nil
|
||||||
|
# foo.current_state # => nil
|
||||||
|
#
|
||||||
|
# NOTE: intended to be called from an event
|
||||||
|
#
|
||||||
|
# This allows for nil aasm states - be sure to add validation to your model
|
||||||
|
def aasm_read_state
|
||||||
|
state = send(self.class.aasm_column)
|
||||||
|
if new? && state.to_s.strip.empty?
|
||||||
|
aasm.determine_state_name(self.class.aasm.initial_state)
|
||||||
|
elsif state.nil?
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
state.to_sym
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensures that if the aasm_state column is nil and the record is new
|
||||||
|
# that the initial state gets populated before validation on create
|
||||||
|
#
|
||||||
|
# foo = Foo.new
|
||||||
|
# foo.aasm_state # => nil
|
||||||
|
# foo.valid?
|
||||||
|
# foo.aasm_state # => "open" (where :open is the initial state)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# foo = Foo.find(:first)
|
||||||
|
# foo.aasm_state # => 1
|
||||||
|
# foo.aasm_state = nil
|
||||||
|
# foo.valid?
|
||||||
|
# foo.aasm_state # => nil
|
||||||
|
#
|
||||||
|
def aasm_ensure_initial_state
|
||||||
|
aasm.enter_initial_state if
|
||||||
|
send(self.class.aasm_column).to_s.strip.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Writes <tt>state</tt> to the state column and persists it to the database
|
||||||
|
#
|
||||||
|
# foo = Foo[1]
|
||||||
|
# foo.aasm.current_state # => :opened
|
||||||
|
# foo.close!
|
||||||
|
# foo.aasm.current_state # => :closed
|
||||||
|
# Foo[1].aasm.current_state # => :closed
|
||||||
|
#
|
||||||
|
# NOTE: intended to be called from an event
|
||||||
|
def aasm_write_state state
|
||||||
|
aasm_column = self.class.aasm_column
|
||||||
|
update_ony({aasm_column => state.to_s}, aasm_column)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
||||||
|
#
|
||||||
|
# foo = Foo[1]
|
||||||
|
# foo.aasm.current_state # => :opened
|
||||||
|
# foo.close
|
||||||
|
# foo.aasm.current_state # => :closed
|
||||||
|
# Foo[1].aasm.current_state # => :opened
|
||||||
|
# foo.save
|
||||||
|
# foo.aasm.current_state # => :closed
|
||||||
|
# Foo[1].aasm.current_state # => :closed
|
||||||
|
#
|
||||||
|
# NOTE: intended to be called from an event
|
||||||
|
def aasm_write_state_without_persistence state
|
||||||
|
send("#{self.class.aasm_column}=", state.to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
103
spec/unit/persistence/sequel_persistence_spec.rb
Normal file
103
spec/unit/persistence/sequel_persistence_spec.rb
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
|
||||||
|
describe 'sequel' do
|
||||||
|
begin
|
||||||
|
require 'sequel'
|
||||||
|
require 'logger'
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
before(:all) do
|
||||||
|
db = Sequel.sqlite
|
||||||
|
# if you want to see the statements while running the spec enable the following line
|
||||||
|
# db.loggers << Logger.new($stderr)
|
||||||
|
db.create_table(:models) do
|
||||||
|
primary_key :id
|
||||||
|
String :status
|
||||||
|
end
|
||||||
|
|
||||||
|
@model = Class.new(Sequel::Model(db)) do
|
||||||
|
set_dataset(:models)
|
||||||
|
attr_accessor :default
|
||||||
|
include AASM
|
||||||
|
aasm :column => :status
|
||||||
|
aasm do
|
||||||
|
state :alpha, :initial => true
|
||||||
|
state :beta
|
||||||
|
state :gamma
|
||||||
|
event :release do
|
||||||
|
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "instance methods" do
|
||||||
|
let(:model) {@model.new}
|
||||||
|
|
||||||
|
it "should respond to aasm persistence methods" do
|
||||||
|
expect(model).to respond_to(:aasm_read_state)
|
||||||
|
expect(model).to respond_to(:aasm_write_state)
|
||||||
|
expect(model).to respond_to(:aasm_write_state_without_persistence)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return the initial state when new and the aasm field is nil" do
|
||||||
|
expect(model.aasm.current_state).to eq(:alpha)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return the aasm column when new and the aasm field is not nil" do
|
||||||
|
model.status = "beta"
|
||||||
|
expect(model.aasm.current_state).to eq(:beta)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return the aasm column when not new and the aasm_column is not nil" do
|
||||||
|
allow(model).to receive(:new?).and_return(false)
|
||||||
|
model.status = "gamma"
|
||||||
|
expect(model.aasm.current_state).to eq(:gamma)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should allow a nil state" do
|
||||||
|
allow(model).to receive(:new?).and_return(false)
|
||||||
|
model.status = nil
|
||||||
|
expect(model.aasm.current_state).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should call aasm_ensure_initial_state on validation before create" do
|
||||||
|
expect(model).to receive(:aasm_ensure_initial_state).and_return(true)
|
||||||
|
model.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should call aasm_ensure_initial_state before create, even if skipping validations" do
|
||||||
|
expect(model).to receive(:aasm_ensure_initial_state).and_return(true)
|
||||||
|
model.save(:validate => false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'subclasses' do
|
||||||
|
it "should have the same states as its parent class" do
|
||||||
|
expect(Class.new(@model).aasm.states).to eq(@model.aasm.states)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have the same events as its parent class" do
|
||||||
|
expect(Class.new(@model).aasm.events).to eq(@model.aasm.events)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have the same column as its parent even for the new dsl" do
|
||||||
|
expect(@model.aasm_column).to eq(:status)
|
||||||
|
expect(Class.new(@model).aasm_column).to eq(:status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'initial states' do
|
||||||
|
it 'should support conditions' do
|
||||||
|
@model.aasm do
|
||||||
|
initial_state lambda{ |m| m.default }
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(@model.new(:default => :beta).aasm.current_state).to eq(:beta)
|
||||||
|
expect(@model.new(:default => :gamma).aasm.current_state).to eq(:gamma)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue LoadError
|
||||||
|
puts "Not running Sequel specs because sequel gem if not installed!!!"
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue