Skip to content

Commit

Permalink
Merge branch 'javajax-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
alto committed Mar 19, 2016
2 parents ef37c72 + 6b8cca3 commit d7847bd
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .travis.yml
Expand Up @@ -14,7 +14,9 @@ rvm:
- jruby-9.0.4.0
- rbx-2.5.8

services: mongodb
services:
- mongodb
- redis-server

gemfile:
- gemfiles/rails_3.2_stable.gemfile
Expand Down
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -663,6 +663,21 @@ class Job
end
```

### Redis

AASM also supports persistence in Redis.
Make sure to include Redis::Objects before you include AASM.

```ruby
class User
include Redis::Objects
include AASM

aasm do
end
end
```

### Automatic Scopes

AASM will automatically create scope methods for each state in the model.
Expand Down
1 change: 1 addition & 0 deletions gemfiles/rails_4.0.gemfile
Expand Up @@ -10,5 +10,6 @@ gem 'mongoid', '~>4.0' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.
gem 'sequel'
gem 'dynamoid', '~> 1', :platforms => :ruby
gem 'aws-sdk', '~>2', :platforms => :ruby
gem "redis-objects"

gemspec :path => "../"
1 change: 1 addition & 0 deletions gemfiles/rails_4.1.gemfile
Expand Up @@ -10,5 +10,6 @@ gem 'mongoid', '~>4.0' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.
gem 'sequel'
gem 'dynamoid', '~> 1', :platforms => :ruby
gem 'aws-sdk', '~>2', :platforms => :ruby
gem "redis-objects"

gemspec :path => "../"
1 change: 1 addition & 0 deletions gemfiles/rails_4.2_mongo_mapper.gemfile
Expand Up @@ -12,5 +12,6 @@ gem 'mongo_mapper'
gem 'bson_ext', :platforms => :ruby
gem 'dynamoid', '~> 1', :platforms => :ruby
gem 'aws-sdk', '~>2', :platforms => :ruby
gem "redis-objects"

gemspec :path => "../"
2 changes: 2 additions & 0 deletions lib/aasm/persistence.rb
Expand Up @@ -18,6 +18,8 @@ def load_persistence(base)
include_persistence base, :dynamoid
elsif hierarchy.include?("CDQManagedObject")
include_persistence base, :core_data_query
elsif hierarchy.include?("Redis::Objects")
include_persistence base, :redis
else
include_persistence base, :plain
end
Expand Down
109 changes: 109 additions & 0 deletions lib/aasm/persistence/redis_persistence.rb
@@ -0,0 +1,109 @@
require_relative "base"

module AASM
module Persistence
module RedisPersistence

def self.included(base)
base.send(:include, AASM::Persistence::Base)
base.send(:include, AASM::Persistence::RedisPersistence::InstanceMethods)
end

module InstanceMethods
# Add the inital value to intiializer
#
# redis-objects removed the key from redis when set to nil
def initialize(*args)
super
state = send(self.class.aasm.attribute_name)
state.value = aasm.determine_state_name(self.class.aasm.initial_state)
end
# Returns the value of the aasm.attribute_name - 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
# include Redis::Objects
# 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.attribute_name)

if state.value.nil?
nil
else
state.value.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.attribute_name).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.attribute_name
self.send("#{aasm_column}=", state)
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.attribute_name}=", state)
end
end
end
end
end
77 changes: 77 additions & 0 deletions spec/unit/persistence/redis_persistence_spec.rb
@@ -0,0 +1,77 @@

describe 'redis' do
begin
require 'redis-objects'
require 'logger'
require 'spec_helper'

before(:all) do
Redis.current = Redis.new(host: '127.0.0.1', port: 6379)

@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

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 allow a nil state" do
model.status = nil
expect(model.aasm.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.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.attribute_name).to eq(:status)
expect(Class.new(@model).aasm.attribute_name).to eq(:status)
end
end

rescue LoadError
puts "Not running Sequel specs because sequel gem is not installed!!!"
end
end

0 comments on commit d7847bd

Please sign in to comment.