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 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 ### 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

View file

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

View file

@ -85,10 +85,11 @@ module AASM
# 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)
old_value = read_attribute(self.class.aasm_column) 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 success = if aasm_skipping_validations
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm_column => state.to_s) == 1 value = aasm_raw_attribute_value state
self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm_column => value) == 1
else else
self.save self.save
end end
@ -113,10 +114,29 @@ module AASM
# #
# 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)
write_attribute(self.class.aasm_column, state.to_s) aasm_write_attribute state
end end
private 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 # Ensures that if the aasm_state column is nil and the record is new
# that the initial state gets populated before validation on create # 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) expect(gate).to respond_to(:aasm_write_state_without_persistence)
end 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 it "should return the initial state when new and the aasm field is nil" do
expect(gate.aasm.current_state).to eq(:opened) expect(gate.aasm.current_state).to eq(:opened)
end end