estate 0.0.2 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +54 -6
- data/lib/estate/configuration.rb +4 -2
- data/lib/estate/constants/orm.rb +10 -0
- data/lib/estate/estate.rb +16 -9
- data/lib/estate/logic/active_record/setup.rb +19 -0
- data/lib/estate/logic/active_record/specific_logic.rb +30 -0
- data/lib/estate/logic/common_logic.rb +26 -0
- data/lib/estate/logic/core.rb +19 -0
- data/lib/estate/logic/sequel/setup.rb +21 -0
- data/lib/estate/logic/sequel/specific_logic.rb +26 -0
- data/lib/estate/requirements.rb +3 -1
- data/lib/estate/setup.rb +17 -0
- data/lib/estate/state_machine.rb +10 -15
- data/lib/estate/version.rb +1 -1
- data/lib/estate.rb +6 -4
- metadata +24 -3
- data/lib/estate/active_record.rb +0 -35
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0777265b6deae44f96eb4fbc8f150bb73b1f2d98849107b9750eeb0ac025ca49
|
|
4
|
+
data.tar.gz: 916c2a835c05ed793d87e25883cb6999ebf87687c260f39eba90e994cf0aa228
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 37e595f2f4451386df31a2b563af980037c90f91786760c9c88f9090418ffd3b640473bc5c2d16a1826c3646302d2041b151a0807d106e1dbc6c85dc126bbfbd
|
|
7
|
+
data.tar.gz: f939381283ace662a7d97169cc7e0bf26ad8d05a78eb40585f456e84768bda4474c1ae0501d5f7d232eb401d577341d2ce09f4fa3b02137adca8019e87c65114
|
data/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
1
3
|
# Estate Gem
|
|
2
4
|
|
|
3
|
-
Estate is a Ruby gem designed to simplify state management in ActiveRecord models. The primary focus of this gem is to provide a straightforward way to define states and transitions using a clean syntax
|
|
5
|
+
Estate is a Ruby gem designed to simplify state management in both ActiveRecord and Sequel models. The primary focus of this gem is to provide a straightforward way to define states and transitions using a clean syntax.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -17,8 +19,8 @@ gem install estate
|
|
|
17
19
|
```
|
|
18
20
|
|
|
19
21
|
## Usage
|
|
20
|
-
|
|
21
|
-
To use the Estate gem, include it in your
|
|
22
|
+
### ActiveRecord
|
|
23
|
+
To use the Estate gem with ActiveRecord, include it in your model and define your states and transitions inside a block using the `estate` method. Here's a simple example:
|
|
22
24
|
|
|
23
25
|
```ruby
|
|
24
26
|
class MyModel < ApplicationRecord
|
|
@@ -36,13 +38,59 @@ class MyModel < ApplicationRecord
|
|
|
36
38
|
end
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
And then
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
model = MyModel.create(state: :state_1)
|
|
45
|
+
model.update(state: :state_2) # you don't need to call any extra code to change the state; treat it like a normal field
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The default field for storing the state is named "state". You can customize this name by providing options to the estate method:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
class MyModel < ApplicationRecord
|
|
52
|
+
include Estate
|
|
53
|
+
|
|
54
|
+
estate column: :custom_state_field do
|
|
55
|
+
# ...
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
You can also use the `empty_initial_state: true` option to enable the creation of a model with a `nil` initial state:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
class MyModel < ApplicationRecord
|
|
64
|
+
include Estate
|
|
65
|
+
|
|
66
|
+
estate empty_initial_state: true do
|
|
67
|
+
# ...
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The `estate` method now supports a `raise_on_error` option. When set to `true`, the gem will raise a specific exception instead of the standard ActiveRecord validation error upon a validation failure.
|
|
40
73
|
|
|
41
74
|
```ruby
|
|
42
75
|
class MyModel < ApplicationRecord
|
|
43
76
|
include Estate
|
|
44
77
|
|
|
45
|
-
estate
|
|
78
|
+
estate raise_on_error: true do
|
|
79
|
+
# ...
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Sequel
|
|
85
|
+
To use the Estate gem with Sequel, include it in your model, and ensure you have the `plugin: dirty` enabled for validation to work correctly. The `raise_on_error` option is not needed with Sequel, as exceptions are always raised on validation errors.
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
class MySequelModel < Sequel::Model
|
|
89
|
+
include Estate
|
|
90
|
+
|
|
91
|
+
plugin :dirty # Ensure the dirty plugin is enabled for validation to work
|
|
92
|
+
|
|
93
|
+
estate do
|
|
46
94
|
state :state_1
|
|
47
95
|
state :state_2
|
|
48
96
|
state :state_3
|
|
@@ -54,7 +102,7 @@ class MyModel < ApplicationRecord
|
|
|
54
102
|
end
|
|
55
103
|
```
|
|
56
104
|
|
|
57
|
-
## Migration Example
|
|
105
|
+
## Migration Example for ActiveRecord
|
|
58
106
|
|
|
59
107
|
```bash
|
|
60
108
|
bundle exec rails generate migration AddStateToMyModels state:string
|
data/lib/estate/configuration.rb
CHANGED
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
module Estate
|
|
4
4
|
module Configuration
|
|
5
5
|
class << self
|
|
6
|
-
def init_config(column_name
|
|
6
|
+
def init_config(column_name, allow_empty_initial_state, raise_on_error)
|
|
7
7
|
@column_name = column_name
|
|
8
8
|
@allow_empty_initial_state = allow_empty_initial_state
|
|
9
|
+
@raise_on_error = raise_on_error
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
attr_reader :column_name, :allow_empty_initial_state
|
|
12
|
+
attr_reader :column_name, :allow_empty_initial_state, :raise_on_error
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
module Defaults
|
|
15
16
|
COLUMN_NAME = :state
|
|
16
17
|
ALLOW_EMPTY_INITIAL_STATE = false
|
|
18
|
+
RAISE_ON_ERROR = false
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
data/lib/estate/estate.rb
CHANGED
|
@@ -5,21 +5,22 @@ module Estate
|
|
|
5
5
|
base.extend Estate::ClassMethods
|
|
6
6
|
|
|
7
7
|
Estate::Requirements.check_requirements(base)
|
|
8
|
-
Estate::ActiveRecord.setup_callbacks(base)
|
|
9
8
|
Estate::StateMachine.create_store
|
|
10
|
-
|
|
11
|
-
super
|
|
9
|
+
Estate::Setup.call(base)
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
module ClassMethods
|
|
15
13
|
def estate(column: Estate::Configuration::Defaults::COLUMN_NAME,
|
|
16
|
-
empty_initial_state: Estate::Configuration::Defaults::ALLOW_EMPTY_INITIAL_STATE
|
|
17
|
-
|
|
14
|
+
empty_initial_state: Estate::Configuration::Defaults::ALLOW_EMPTY_INITIAL_STATE,
|
|
15
|
+
raise_on_error: Estate::Configuration::Defaults::RAISE_ON_ERROR)
|
|
16
|
+
Estate::Configuration.init_config(column, empty_initial_state, raise_on_error)
|
|
18
17
|
|
|
19
18
|
yield if block_given?
|
|
20
19
|
end
|
|
21
20
|
|
|
22
|
-
def state(name)
|
|
21
|
+
def state(name = nil)
|
|
22
|
+
raise(StandardError, 'state must be a Symbol or a String') unless Estate::StateMachine.argument_valid?(name)
|
|
23
|
+
|
|
23
24
|
if Estate::StateMachine.state_exists?(name)
|
|
24
25
|
raise(StandardError, "state `:#{name}` is already defined")
|
|
25
26
|
else
|
|
@@ -27,16 +28,22 @@ module Estate
|
|
|
27
28
|
end
|
|
28
29
|
end
|
|
29
30
|
|
|
30
|
-
def transition(from
|
|
31
|
+
def transition(from: nil, to: nil)
|
|
32
|
+
unless Estate::StateMachine.argument_valid?(from)
|
|
33
|
+
raise(StandardError, 'argument `from` must be a Symbol or a String')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
raise(StandardError, 'argument `to` must be a Symbol or a String') unless Estate::StateMachine.argument_valid?(to)
|
|
37
|
+
|
|
31
38
|
raise(StandardError, "state `#{from}` is not defined") unless Estate::StateMachine.state_exists?(from)
|
|
32
39
|
|
|
33
40
|
raise(StandardError, "state `#{to}` is not defined") unless Estate::StateMachine.state_exists?(to)
|
|
34
41
|
|
|
35
|
-
if Estate::StateMachine.transition_exists?(from
|
|
42
|
+
if Estate::StateMachine.transition_exists?(from, to)
|
|
36
43
|
raise(StandardError, "`transition from: :#{from}, to: :#{to}` already defined")
|
|
37
44
|
end
|
|
38
45
|
|
|
39
|
-
Estate::StateMachine.register_transition(from
|
|
46
|
+
Estate::StateMachine.register_transition(from, to)
|
|
40
47
|
end
|
|
41
48
|
end
|
|
42
49
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Estate
|
|
4
|
+
module Logic
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module Setup
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def call(base)
|
|
10
|
+
base.class_eval do
|
|
11
|
+
public_send(:before_validation) do
|
|
12
|
+
Estate::Logic::Core.call(Estate::Constants::Orm::ACTIVE_RECORD, self)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'estate/logic/common_logic'
|
|
4
|
+
|
|
5
|
+
module Estate
|
|
6
|
+
module Logic
|
|
7
|
+
module ActiveRecord
|
|
8
|
+
module SpecificLogic
|
|
9
|
+
extend Estate::Logic::CommonLogic
|
|
10
|
+
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
def add_error(instance, message, attribute: :base)
|
|
14
|
+
if Estate::Configuration.raise_on_error
|
|
15
|
+
exception_message = attribute == :base ? message : "#{attribute}: #{message}"
|
|
16
|
+
raise(StandardError, exception_message)
|
|
17
|
+
else
|
|
18
|
+
instance.errors.add(attribute, message) unless instance.errors[attribute].include?(message)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def get_states(instance)
|
|
23
|
+
from_state = instance.public_send("#{Estate::Configuration.column_name}_was")
|
|
24
|
+
to_state = instance.public_send(Estate::Configuration.column_name)
|
|
25
|
+
[from_state, to_state]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Estate
|
|
4
|
+
module Logic
|
|
5
|
+
module CommonLogic
|
|
6
|
+
def validate_state_changes(instance, from_state, to_state)
|
|
7
|
+
if from_state == to_state
|
|
8
|
+
if from_state.nil? && !Estate::Configuration.allow_empty_initial_state
|
|
9
|
+
add_error(instance, "empty `#{Estate::Configuration.column_name}` is not allowed")
|
|
10
|
+
end
|
|
11
|
+
elsif to_state.nil?
|
|
12
|
+
add_error(instance, 'transition to empty state is not allowed')
|
|
13
|
+
elsif !Estate::StateMachine.state_exists?(to_state)
|
|
14
|
+
add_error(instance, "state `#{to_state}` is not defined")
|
|
15
|
+
elsif !transition_allowed?(from_state, to_state)
|
|
16
|
+
add_error(instance, "transition from `#{from_state}` to `#{to_state}` is not allowed",
|
|
17
|
+
attribute: Estate::Configuration.column_name)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def transition_allowed?(from_state, to_state)
|
|
22
|
+
from_state.nil? || Estate::StateMachine.transition_exists?(from_state, to_state)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Estate
|
|
4
|
+
module Logic
|
|
5
|
+
module Core
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def call(orm, instance)
|
|
9
|
+
require 'estate/logic/common_logic'
|
|
10
|
+
require File.join(File.dirname(__FILE__), orm, 'specific_logic')
|
|
11
|
+
|
|
12
|
+
extend Estate::Logic::CommonLogic
|
|
13
|
+
extend "Estate::Logic::#{orm.classify}::SpecificLogic".safe_constantize
|
|
14
|
+
|
|
15
|
+
validate_state_changes(instance, *get_states(instance))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Estate
|
|
4
|
+
module Logic
|
|
5
|
+
module Sequel
|
|
6
|
+
module Setup
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def call(base)
|
|
10
|
+
base.class_eval do
|
|
11
|
+
def validate
|
|
12
|
+
super
|
|
13
|
+
|
|
14
|
+
Estate::Logic::Core.call(Estate::Constants::Orm::SEQUEL, self)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'estate/logic/common_logic'
|
|
4
|
+
|
|
5
|
+
module Estate
|
|
6
|
+
module Logic
|
|
7
|
+
module Sequel
|
|
8
|
+
module SpecificLogic
|
|
9
|
+
extend Estate::Logic::CommonLogic
|
|
10
|
+
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
# TODO: remove :base
|
|
14
|
+
def add_error(instance, message, attribute: :base)
|
|
15
|
+
instance.errors.add(attribute, message)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def get_states(instance)
|
|
19
|
+
from_state, = instance.column_change(Estate::Configuration.column_name)
|
|
20
|
+
to_state = instance.values[Estate::Configuration.column_name]
|
|
21
|
+
[from_state, to_state]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/estate/requirements.rb
CHANGED
|
@@ -5,7 +5,9 @@ module Estate
|
|
|
5
5
|
def check_requirements(base)
|
|
6
6
|
ancestors = base.ancestors.map(&:to_s)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
unless 'Sequel::Model'.in?(ancestors) || 'ActiveRecord::Base'.in?(ancestors)
|
|
9
|
+
raise(StandardError, 'Estate requires ActiveRecord or Sequel')
|
|
10
|
+
end
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
module_function :check_requirements
|
data/lib/estate/setup.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Estate
|
|
4
|
+
module Setup
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def call(base)
|
|
8
|
+
if base.ancestors.map(&:to_s).include? 'ActiveRecord::Base'
|
|
9
|
+
require File.join(File.dirname(__FILE__), 'logic', 'active_record', 'setup')
|
|
10
|
+
Estate::Logic::ActiveRecord::Setup.call(base)
|
|
11
|
+
else
|
|
12
|
+
require File.join(File.dirname(__FILE__), 'logic', 'sequel', 'setup')
|
|
13
|
+
Estate::Logic::Sequel::Setup.call(base)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/estate/state_machine.rb
CHANGED
|
@@ -9,32 +9,27 @@ module Estate
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def state_exists?(state)
|
|
12
|
-
|
|
12
|
+
states.key?(state.to_sym)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def register_state(state)
|
|
16
|
-
|
|
17
|
-
when Symbol
|
|
18
|
-
states[state] = nil
|
|
19
|
-
when String
|
|
20
|
-
states[state.to_sym] = nil
|
|
21
|
-
else
|
|
22
|
-
raise(ArgumentError, 'State must be a Symbol or a String')
|
|
23
|
-
end
|
|
16
|
+
states[state.to_sym] = nil
|
|
24
17
|
end
|
|
25
18
|
|
|
26
|
-
def transition_exists?(
|
|
27
|
-
|
|
28
|
-
transition_key = { from: from.to_sym, to: to.to_sym }
|
|
19
|
+
def transition_exists?(from_state, to_state)
|
|
20
|
+
transition_key = { from: from_state.to_sym, to: to_state.to_sym }
|
|
29
21
|
transitions.key?(transition_key)
|
|
30
22
|
end
|
|
31
23
|
|
|
32
|
-
def register_transition(
|
|
33
|
-
|
|
34
|
-
transition_key = { from: from.to_sym, to: to.to_sym }
|
|
24
|
+
def register_transition(from_state, to_state)
|
|
25
|
+
transition_key = { from: from_state.to_sym, to: to_state.to_sym }
|
|
35
26
|
transitions[transition_key] = nil
|
|
36
27
|
end
|
|
37
28
|
|
|
29
|
+
def argument_valid?(argument)
|
|
30
|
+
argument.is_a?(Symbol) || argument.is_a?(String)
|
|
31
|
+
end
|
|
32
|
+
|
|
38
33
|
attr_reader :states, :transitions
|
|
39
34
|
end
|
|
40
35
|
end
|
data/lib/estate/version.rb
CHANGED
data/lib/estate.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'estate/version'
|
|
4
|
-
require 'estate/requirements'
|
|
5
3
|
require 'estate/configuration'
|
|
6
|
-
require 'estate/
|
|
7
|
-
require 'estate/active_record'
|
|
4
|
+
require 'estate/constants/orm'
|
|
8
5
|
require 'estate/estate'
|
|
6
|
+
require 'estate/logic/core'
|
|
7
|
+
require 'estate/requirements'
|
|
8
|
+
require 'estate/setup'
|
|
9
|
+
require 'estate/state_machine'
|
|
10
|
+
require 'estate/version'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: estate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Igor Korepanov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-01-
|
|
11
|
+
date: 2024-01-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rubocop
|
|
@@ -66,6 +66,20 @@ dependencies:
|
|
|
66
66
|
- - '='
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: 3.12.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: simplecov
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - '='
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 0.22.0
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - '='
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 0.22.0
|
|
69
83
|
description: Estate is a Ruby gem designed to simplify state management in ActiveRecord
|
|
70
84
|
models
|
|
71
85
|
email: noemail@example.com
|
|
@@ -76,10 +90,17 @@ files:
|
|
|
76
90
|
- LICENSE.txt
|
|
77
91
|
- README.md
|
|
78
92
|
- lib/estate.rb
|
|
79
|
-
- lib/estate/active_record.rb
|
|
80
93
|
- lib/estate/configuration.rb
|
|
94
|
+
- lib/estate/constants/orm.rb
|
|
81
95
|
- lib/estate/estate.rb
|
|
96
|
+
- lib/estate/logic/active_record/setup.rb
|
|
97
|
+
- lib/estate/logic/active_record/specific_logic.rb
|
|
98
|
+
- lib/estate/logic/common_logic.rb
|
|
99
|
+
- lib/estate/logic/core.rb
|
|
100
|
+
- lib/estate/logic/sequel/setup.rb
|
|
101
|
+
- lib/estate/logic/sequel/specific_logic.rb
|
|
82
102
|
- lib/estate/requirements.rb
|
|
103
|
+
- lib/estate/setup.rb
|
|
83
104
|
- lib/estate/state_machine.rb
|
|
84
105
|
- lib/estate/version.rb
|
|
85
106
|
homepage: https://github.com/igorkorepanov/estate
|
data/lib/estate/active_record.rb
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Estate
|
|
4
|
-
module ActiveRecord
|
|
5
|
-
CALLBACK_NAMES = [:before_validation].freeze
|
|
6
|
-
|
|
7
|
-
def setup_callbacks(base)
|
|
8
|
-
base.class_eval do
|
|
9
|
-
CALLBACK_NAMES.each do |callback_name|
|
|
10
|
-
public_send(callback_name) { Estate::ActiveRecord.validate_state_changes(self) }
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def validate_state_changes(instance)
|
|
16
|
-
from_state = instance.public_send("#{Estate::Configuration.column_name}_was")
|
|
17
|
-
to_state = instance.public_send(Estate::Configuration.column_name)
|
|
18
|
-
|
|
19
|
-
if from_state == to_state
|
|
20
|
-
if to_state.nil? && !Estate::Configuration.allow_empty_initial_state
|
|
21
|
-
raise(StandardError, "empty `#{Estate::Configuration.column_name}` is not allowed")
|
|
22
|
-
end
|
|
23
|
-
elsif Estate::StateMachine.state_exists?(to_state) # TODO: check to_state.nil?
|
|
24
|
-
unless Estate::StateMachine.transition_exists?(from: from_state, to: to_state)
|
|
25
|
-
instance.errors.add(Estate::Configuration.column_name,
|
|
26
|
-
message: "transition from `#{from_state}` to `#{to_state}` is not allowed")
|
|
27
|
-
end
|
|
28
|
-
else
|
|
29
|
-
instance.errors.add(:base, "state `#{to_state}` is not defined")
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
module_function :setup_callbacks, :validate_state_changes
|
|
34
|
-
end
|
|
35
|
-
end
|