1
0
Fork 0
mirror of https://github.com/aasm/aasm synced 2023-03-27 23:22:41 -04:00

Added support for Rails 4.1+ enums.

This commit is contained in:
Konstantin Burnaev 2014-05-10 19:02:11 +10:00
parent 85ed696500
commit ab6d184a21
4 changed files with 163 additions and 4 deletions

View file

@ -278,6 +278,31 @@ class Job < ActiveRecord::Base
end
```
#### ActiveRecord enums
You can use
[enumerations](http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html)
in Rails 4.1+ for your state column:
```ruby
class Job < ActiveRecord::Base
include AASM
enum state {
sleeping: 5,
running: 99
}
aasm :column => :state, :enum => :states do
state :sleeping, :initial => true
state :running
end
end
```
You need to pass the name of the method which provides access to the
enumeration mapping as a value of ```enum```.
### Mongoid
AASM also supports persistence to Mongodb if you're using Mongoid. Make sure

View file

@ -18,6 +18,8 @@ module AASM
# use requires_new for nested transactions
configure :requires_new_transaction, true
configure :enum, nil
end
def initial_state(new_initial_state=nil)

View file

@ -85,10 +85,11 @@ module AASM
# NOTE: intended to be called from an event
def aasm_write_state(state)
old_value = read_attribute(self.class.aasm_column)
write_attribute(self.class.aasm_column, state.to_s)
aasm_write_attribute state
success = if AASM::StateMachine[self.class].config.skip_validation_on_save
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm_column => state.to_s) == 1
success = if aasm_skipping_validations
value = aasm_raw_attribute_value state
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm_column => value) == 1
else
self.save
end
@ -113,10 +114,29 @@ module AASM
#
# NOTE: intended to be called from an event
def aasm_write_state_without_persistence(state)
write_attribute(self.class.aasm_column, state.to_s)
aasm_write_attribute state
end
private
def aasm_enum
AASM::StateMachine[self.class].config.enum
end
def aasm_skipping_validations
AASM::StateMachine[self.class].config.skip_validation_on_save
end
def aasm_write_attribute(state)
write_attribute self.class.aasm_column, aasm_raw_attribute_value(state)
end
def aasm_raw_attribute_value(state)
if aasm_enum
value = self.class.send(aasm_enum)[state]
else
value = state.to_s
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

View file

@ -23,6 +23,118 @@ describe "instance methods" do
expect(gate).to respond_to(:aasm_write_state_without_persistence)
end
context "when AASM is configured to use enum" do
let(:state_sym) { :running }
let(:state_code) { 2 }
let(:enum_name) { :states }
let(:enum) { Hash[state_sym, state_code] }
before :each do
gate
.stub(:aasm_enum)
.and_return(enum_name)
gate.stub(:aasm_write_attribute)
gate.stub(:write_attribute)
gate
.class
.stub(enum_name)
.and_return(enum)
end
describe "aasm_write_state" do
context "when AASM is configured to skip validations on save" do
before :each do
gate
.stub(:aasm_skipping_validations)
.and_return(true)
end
it "passes state code instead of state symbol to update_all" do
# stub_chain does not allow us to give expectations on call
# parameters in the middle of the chain, so we need to use
# intermediate object instead.
obj = double(Object, update_all: 1)
gate
.class
.stub(:where)
.and_return(obj)
gate.aasm_write_state state_sym
expect(obj).to have_received(:update_all)
.with(Hash[gate.class.aasm_column, state_code])
end
end
context "when AASM is not skipping validations" do
it "delegates state update to the helper method" do
# Let's pretend that validation is passed
gate.stub(:save).and_return(true)
gate.aasm_write_state state_sym
expect(gate).to have_received(:aasm_write_attribute).with(state_sym)
expect(gate).to_not have_received :write_attribute
end
end
end
describe "aasm_write_state_without_persistence" do
it "delegates state update to the helper method" do
gate.aasm_write_state_without_persistence state_sym
expect(gate).to have_received(:aasm_write_attribute).with(state_sym)
expect(gate).to_not have_received :write_attribute
end
end
describe "aasm_raw_attribute_value" do
it "converts state symbol to state code" do
expect(gate.send(:aasm_raw_attribute_value, state_sym))
.to eq state_code
end
end
end
context "when AASM is configured to use string field" do
let(:state_sym) { :running }
before :each do
gate
.stub(:aasm_enum)
.and_return(nil)
end
describe "aasm_raw_attribute_value" do
it "converts state symbol to string" do
expect(gate.send(:aasm_raw_attribute_value, state_sym))
.to eq state_sym.to_s
end
end
end
describe "aasm_write_attribute helper method" do
let(:sym) { :sym }
let(:value) { 42 }
before :each do
gate.stub(:write_attribute)
gate.stub(:aasm_raw_attribute_value)
.and_return(value)
gate.send(:aasm_write_attribute, sym)
end
it "generates attribute value using a helper method" do
expect(gate).to have_received(:aasm_raw_attribute_value).with(sym)
end
it "writes attribute to the model" do
expect(gate).to have_received(:write_attribute).with(:aasm_state, value)
end
end
it "should return the initial state when new and the aasm field is nil" do
expect(gate.aasm.current_state).to eq(:opened)
end