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

Introduces instance level skip validation option.

This commit is contained in:
Nitin Salunke 2019-07-30 18:01:01 +05:30 committed by Anil Kumar Maurya
parent 0ce55f2c78
commit aa34bafe7c
5 changed files with 71 additions and 0 deletions

View file

@ -740,6 +740,14 @@ class Job < ActiveRecord::Base
end
```
Also You can skip the validation at instance level with `some_event_name_without_validation!` method.
With this you have the flexibility of having validation for all your transitions by default and then skip it wherever required.
Please note that only state column will be updated as mentioned in the above example.
```ruby
job.run_without_validation!
```
If you want to make sure that the _AASM_ column for storing the state is not directly assigned,
configure _AASM_ to not allow direct assignment, like this:

View file

@ -133,6 +133,8 @@ module AASM
aasm_fire_event(aasm_name, event, {:persist => false}, *args, &block)
end
skip_instance_level_validation(event, name, aasm_name, klass)
# Create aliases for the event methods. Keep the old names to maintain backwards compatibility.
if namespace?
klass.send(:alias_method, "may_#{name}_#{namespace}?", "may_#{name}?")
@ -248,5 +250,20 @@ module AASM
end
end
def skip_instance_level_validation(event, name, aasm_name, klass)
# Overrides the skip_validation config for an instance (If skip validation is set to false in original config) and
# restores it back to the original value after the event is fired.
safely_define_method klass, "#{name}_without_validation!", ->(*args, &block) do
original_config = AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save
begin
AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save = true unless original_config
aasm(aasm_name).current_event = :"#{name}!"
aasm_fire_event(aasm_name, event, {:persist => true}, *args, &block)
ensure
AASM::StateMachineStore.fetch(self.class, true).machine(aasm_name).config.skip_validation_on_save = original_config
end
end
end
end
end

View file

@ -51,4 +51,9 @@ ActiveRecord::Migration.suppress_messages do
t.string "search"
t.string "sync"
end
ActiveRecord::Migration.create_table "instance_level_skip_validation_examples", :force => true do |t|
t.string "state"
t.string "some_string"
end
end

View file

@ -0,0 +1,19 @@
class InstanceLevelSkipValidationExample < ActiveRecord::Base
include AASM
aasm :state do
state :new, :initial => true
state :draft
state :complete
event :set_draft do
transitions from: :new, to: :draft
end
event :complete do
transitions from: %i[draft new], to: :complete
end
end
validates :some_string, presence: true
end

View file

@ -748,4 +748,26 @@ if defined?(ActiveRecord)
expect { job.run }.to raise_error(AASM::InvalidTransition)
end
end
describe 'testing the instance_level skip validation with _without_validation method' do
let(:example) do
obj = InstanceLevelSkipValidationExample.new(state: 'new')
obj.save(validate: false)
obj
end
it 'should be able to change the state with invalid record' do
expect(example.valid?).to be_falsey
expect(example.complete!).to be_falsey
expect(example.complete_without_validation!).to be_truthy
expect(example.state).to eq('complete')
end
it 'shouldn\'t affect the behaviour of existing method after calling _without_validation! method' do
expect(example.set_draft!).to be_falsey
expect(example.set_draft_without_validation!).to be_truthy
expect(example.state).to eq('draft')
expect(example.complete!).to be_falsey
end
end
end