mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
parent
5b764e796e
commit
8e8c6baeaf
11 changed files with 205 additions and 38 deletions
|
@ -24,6 +24,7 @@ appraise 'rails_4.2' do
|
||||||
gem 'sequel'
|
gem 'sequel'
|
||||||
gem 'dynamoid', '~> 1', :platforms => :ruby
|
gem 'dynamoid', '~> 1', :platforms => :ruby
|
||||||
gem 'aws-sdk', '~>2', :platforms => :ruby
|
gem 'aws-sdk', '~>2', :platforms => :ruby
|
||||||
|
gem 'redis-objects'
|
||||||
end
|
end
|
||||||
|
|
||||||
appraise 'rails_4.2_mongoid_5' do
|
appraise 'rails_4.2_mongoid_5' do
|
||||||
|
@ -41,4 +42,5 @@ appraise 'rails_5.0' do
|
||||||
# gem 'dynamoid', '~> 1', :platforms => :ruby
|
# gem 'dynamoid', '~> 1', :platforms => :ruby
|
||||||
|
|
||||||
gem 'aws-sdk', '~>2', :platforms => :ruby
|
gem 'aws-sdk', '~>2', :platforms => :ruby
|
||||||
|
gem 'redis-objects'
|
||||||
end
|
end
|
||||||
|
|
|
@ -720,8 +720,10 @@ end
|
||||||
|
|
||||||
### Redis
|
### Redis
|
||||||
|
|
||||||
AASM also supports persistence in Redis.
|
AASM also supports persistence in Redis via
|
||||||
Make sure to include Redis::Objects before you include AASM.
|
[Redis::Objects](https://github.com/nateware/redis-objects).
|
||||||
|
Make sure to include Redis::Objects before you include AASM. Note that non-bang
|
||||||
|
events will work as bang events, persisting the changes on every call.
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
class User
|
class User
|
||||||
|
|
|
@ -11,5 +11,6 @@ gem "mongoid", "~>4.0"
|
||||||
gem "sequel"
|
gem "sequel"
|
||||||
gem "dynamoid", "~> 1", :platforms => :ruby
|
gem "dynamoid", "~> 1", :platforms => :ruby
|
||||||
gem "aws-sdk", "~>2", :platforms => :ruby
|
gem "aws-sdk", "~>2", :platforms => :ruby
|
||||||
|
gem "redis-objects"
|
||||||
|
|
||||||
gemspec :path => "../"
|
gemspec :path => "../"
|
||||||
|
|
|
@ -8,5 +8,6 @@ gem "rails", "5.0.0"
|
||||||
gem "mongoid", "~>6.0"
|
gem "mongoid", "~>6.0"
|
||||||
gem "sequel"
|
gem "sequel"
|
||||||
gem "aws-sdk", "~>2", :platforms => :ruby
|
gem "aws-sdk", "~>2", :platforms => :ruby
|
||||||
|
gem "redis-objects"
|
||||||
|
|
||||||
gemspec :path => "../"
|
gemspec :path => "../"
|
||||||
|
|
|
@ -8,13 +8,12 @@ module AASM
|
||||||
end
|
end
|
||||||
|
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
# Add the inital value to intiializer
|
# Initialize with default values
|
||||||
#
|
#
|
||||||
# redis-objects removed the key from redis when set to nil
|
# Redis::Objects removes the key from Redis when set to `nil`
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
super
|
super
|
||||||
state = send(self.class.aasm.attribute_name)
|
aasm_ensure_initial_state
|
||||||
state.value = aasm.determine_state_name(self.class.aasm.initial_state)
|
|
||||||
end
|
end
|
||||||
# Returns the value of the aasm.attribute_name - called from <tt>aasm.current_state</tt>
|
# Returns the value of the aasm.attribute_name - called from <tt>aasm.current_state</tt>
|
||||||
#
|
#
|
||||||
|
@ -68,8 +67,10 @@ module AASM
|
||||||
# foo.aasm_state # => nil
|
# foo.aasm_state # => nil
|
||||||
#
|
#
|
||||||
def aasm_ensure_initial_state
|
def aasm_ensure_initial_state
|
||||||
aasm.enter_initial_state if
|
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
|
||||||
send(self.class.aasm.attribute_name).to_s.strip.empty?
|
aasm_column = self.class.aasm(name).attribute_name
|
||||||
|
aasm(name).enter_initial_state if send(aasm_column).value.blank?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Writes <tt>state</tt> to the state column and persists it to the database
|
# Writes <tt>state</tt> to the state column and persists it to the database
|
||||||
|
@ -81,12 +82,16 @@ module AASM
|
||||||
# Foo[1].aasm.current_state # => :closed
|
# Foo[1].aasm.current_state # => :closed
|
||||||
#
|
#
|
||||||
# NOTE: intended to be called from an event
|
# NOTE: intended to be called from an event
|
||||||
def aasm_write_state(state)
|
def aasm_write_state(state, name=:default)
|
||||||
aasm_column = self.class.aasm.attribute_name
|
aasm_column = self.class.aasm(name).attribute_name
|
||||||
self.send("#{aasm_column}=", state)
|
send("#{aasm_column}").value = state
|
||||||
end
|
end
|
||||||
|
|
||||||
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
||||||
|
# (but actually it still does)
|
||||||
|
#
|
||||||
|
# With Redis::Objects it's not possible to skip persisting - it's not an ORM,
|
||||||
|
# it does not operate like an AR model and does not know how to postpone changes.
|
||||||
#
|
#
|
||||||
# foo = Foo[1]
|
# foo = Foo[1]
|
||||||
# foo.aasm.current_state # => :opened
|
# foo.aasm.current_state # => :opened
|
||||||
|
@ -98,8 +103,8 @@ module AASM
|
||||||
# Foo[1].aasm.current_state # => :closed
|
# Foo[1].aasm.current_state # => :closed
|
||||||
#
|
#
|
||||||
# NOTE: intended to be called from an event
|
# NOTE: intended to be called from an event
|
||||||
def aasm_write_state_without_persistence(state)
|
def aasm_write_state_without_persistence(state, name=:default)
|
||||||
send("#{self.class.aasm.attribute_name}=", state)
|
aasm_write_state(state, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
40
spec/models/redis/complex_redis_example.rb
Normal file
40
spec/models/redis/complex_redis_example.rb
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
class RedisComplexExample
|
||||||
|
include Redis::Objects
|
||||||
|
include AASM
|
||||||
|
|
||||||
|
value :left
|
||||||
|
value :right
|
||||||
|
|
||||||
|
def id
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
aasm :left, :column => 'left' do
|
||||||
|
state :one, :initial => true
|
||||||
|
state :two
|
||||||
|
state :three
|
||||||
|
|
||||||
|
event :increment do
|
||||||
|
transitions :from => :one, :to => :two
|
||||||
|
transitions :from => :two, :to => :three
|
||||||
|
end
|
||||||
|
event :reset do
|
||||||
|
transitions :from => :three, :to => :one
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
aasm :right, :column => 'right' do
|
||||||
|
state :alpha, :initial => true
|
||||||
|
state :beta
|
||||||
|
state :gamma
|
||||||
|
|
||||||
|
event :level_up do
|
||||||
|
transitions :from => :alpha, :to => :beta
|
||||||
|
transitions :from => :beta, :to => :gamma
|
||||||
|
end
|
||||||
|
event :level_down do
|
||||||
|
transitions :from => :gamma, :to => :beta
|
||||||
|
transitions :from => :beta, :to => :alpha
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
20
spec/models/redis/redis_multiple.rb
Normal file
20
spec/models/redis/redis_multiple.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class RedisMultiple
|
||||||
|
include Redis::Objects
|
||||||
|
include AASM
|
||||||
|
|
||||||
|
value :status
|
||||||
|
|
||||||
|
def id
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
aasm :left, :column => :status
|
||||||
|
aasm :left do
|
||||||
|
state :alpha, :initial => true
|
||||||
|
state :beta
|
||||||
|
state :gamma
|
||||||
|
event :release do
|
||||||
|
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
20
spec/models/redis/redis_simple.rb
Normal file
20
spec/models/redis/redis_simple.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
class RedisSimple
|
||||||
|
include Redis::Objects
|
||||||
|
include AASM
|
||||||
|
|
||||||
|
value :status
|
||||||
|
|
||||||
|
def id
|
||||||
|
1
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
|
@ -2,6 +2,14 @@
|
||||||
begin
|
begin
|
||||||
require 'redis-objects'
|
require 'redis-objects'
|
||||||
puts "redis-objects gem found, running Redis specs \e[32m#{'✔'}\e[0m"
|
puts "redis-objects gem found, running Redis specs \e[32m#{'✔'}\e[0m"
|
||||||
|
|
||||||
|
Redis.current = Redis.new(host: '127.0.0.1', port: 6379)
|
||||||
|
|
||||||
|
RSpec.configure do |c|
|
||||||
|
c.before(:each) do
|
||||||
|
Redis.current.keys('redis_*').each { |k| Redis.current.del k }
|
||||||
|
end
|
||||||
|
end
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
puts "redis-objects gem not found, not running Redis specs \e[31m#{'✖'}\e[0m"
|
puts "redis-objects gem not found, not running Redis specs \e[31m#{'✖'}\e[0m"
|
||||||
end
|
end
|
||||||
|
|
88
spec/unit/persistence/redis_persistence_multiple_spec.rb
Normal file
88
spec/unit/persistence/redis_persistence_multiple_spec.rb
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
if defined?(Redis)
|
||||||
|
describe 'redis' do
|
||||||
|
|
||||||
|
Dir[File.dirname(__FILE__) + "/../../models/redis/*.rb"].sort.each do |f|
|
||||||
|
require File.expand_path(f)
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:all) do
|
||||||
|
@model = RedisMultiple
|
||||||
|
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(:left).current_state).to eq(:alpha)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should save the initial state" do
|
||||||
|
expect(model.status).to eq("alpha")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return the aasm column the aasm field is not nil" do
|
||||||
|
model.status = "beta"
|
||||||
|
expect(model.aasm(:left).current_state).to eq(:beta)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should allow a nil state" do
|
||||||
|
model.status = nil
|
||||||
|
expect(model.aasm(:left).current_state).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'subclasses' do
|
||||||
|
it "should have the same states as its parent class" do
|
||||||
|
expect(Class.new(@model).aasm(:left).states).to eq(@model.aasm(:left).states)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have the same events as its parent class" do
|
||||||
|
expect(Class.new(@model).aasm(:left).events).to eq(@model.aasm(:left).events)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have the same column as its parent even for the new dsl" do
|
||||||
|
expect(@model.aasm(:left).attribute_name).to eq(:status)
|
||||||
|
expect(Class.new(@model).aasm(:left).attribute_name).to eq(:status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "complex example" do
|
||||||
|
it "works" do
|
||||||
|
record = RedisComplexExample.new
|
||||||
|
|
||||||
|
expect(record.aasm(:left).current_state).to eql :one
|
||||||
|
expect(record.aasm(:right).current_state).to eql :alpha
|
||||||
|
|
||||||
|
expect_aasm_states record, :one, :alpha
|
||||||
|
|
||||||
|
record.increment!
|
||||||
|
expect_aasm_states record, :two, :alpha
|
||||||
|
|
||||||
|
record.level_up!
|
||||||
|
expect_aasm_states record, :two, :beta
|
||||||
|
|
||||||
|
record.increment!
|
||||||
|
expect { record.increment! }.to raise_error(AASM::InvalidTransition)
|
||||||
|
expect_aasm_states record, :three, :beta
|
||||||
|
|
||||||
|
record.level_up!
|
||||||
|
expect_aasm_states record, :three, :gamma
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_aasm_states(record, left_state, right_state)
|
||||||
|
expect(record.aasm(:left).current_state).to eql left_state.to_sym
|
||||||
|
expect(record.left.value.to_s).to eql left_state.to_s
|
||||||
|
expect(record.aasm(:right).current_state).to eql right_state.to_sym
|
||||||
|
expect(record.right.value.to_s).to eql right_state.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,31 +3,12 @@ require 'spec_helper'
|
||||||
if defined?(Redis::Objects)
|
if defined?(Redis::Objects)
|
||||||
describe 'redis' do
|
describe 'redis' do
|
||||||
|
|
||||||
|
Dir[File.dirname(__FILE__) + "/../../models/redis/*.rb"].sort.each do |f|
|
||||||
|
require File.expand_path(f)
|
||||||
|
end
|
||||||
|
|
||||||
before(:all) do
|
before(:all) do
|
||||||
Redis.current = Redis.new(host: '127.0.0.1', port: 6379)
|
@model = RedisSimple
|
||||||
|
|
||||||
@model = Class.new do
|
|
||||||
attr_accessor :default
|
|
||||||
|
|
||||||
include Redis::Objects
|
|
||||||
include AASM
|
|
||||||
|
|
||||||
value :status
|
|
||||||
|
|
||||||
def id
|
|
||||||
1
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
end
|
||||||
|
|
||||||
describe "instance methods" do
|
describe "instance methods" do
|
||||||
|
@ -68,6 +49,5 @@ if defined?(Redis::Objects)
|
||||||
expect(Class.new(@model).aasm.attribute_name).to eq(:status)
|
expect(Class.new(@model).aasm.attribute_name).to eq(:status)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue