stator 0.8.0 → 0.9.0.beta
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/.github/workflows/build.yml +10 -5
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/Appraisals +12 -15
- data/Gemfile +7 -6
- data/README.md +4 -20
- data/gemfiles/{activerecord_7.2.gemfile → activerecord_5.1.gemfile} +2 -1
- data/gemfiles/activerecord_5.1.gemfile.lock +74 -0
- data/gemfiles/{activerecord_8.0.gemfile → activerecord_5.2.gemfile} +2 -1
- data/gemfiles/activerecord_5.2.gemfile.lock +74 -0
- data/gemfiles/{activerecord_7.1.gemfile → activerecord_5.gemfile} +2 -1
- data/gemfiles/activerecord_5.gemfile.lock +74 -0
- data/gemfiles/activerecord_6.0.gemfile +2 -2
- data/gemfiles/activerecord_6.0.gemfile.lock +41 -69
- data/gemfiles/activerecord_6.1.gemfile +2 -2
- data/gemfiles/activerecord_6.1.gemfile.lock +41 -68
- data/gemfiles/activerecord_7.0.gemfile +2 -2
- data/gemfiles/activerecord_7.0.gemfile.lock +40 -66
- data/lib/stator/alias.rb +51 -30
- data/lib/stator/integration.rb +42 -49
- data/lib/stator/machine.rb +59 -58
- data/lib/stator/model.rb +78 -73
- data/lib/stator/transition.rb +61 -60
- data/lib/stator/version.rb +3 -5
- data/lib/stator.rb +13 -0
- data/spec/model_spec.rb +203 -318
- data/spec/spec_helper.rb +6 -2
- data/spec/support/models.rb +26 -45
- data/spec/support/schema.rb +42 -42
- data/stator.gemspec +3 -10
- metadata +19 -75
- data/.github/CODEOWNERS +0 -1
- data/.github/dependabot.yml +0 -24
- data/gemfiles/activerecord_7.1.gemfile.lock +0 -114
- data/gemfiles/activerecord_7.2.gemfile.lock +0 -113
- data/gemfiles/activerecord_8.0.gemfile.lock +0 -116
data/lib/stator/machine.rb
CHANGED
@@ -1,57 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Stator
|
2
4
|
class Machine
|
5
|
+
attr_reader :initial_state, :field, :transitions, :states, :namespace,
|
6
|
+
:class_name, :name, :aliases, :options, :tracking_enabled, :klass
|
7
|
+
|
8
|
+
def self.find_or_create(klass, *kwargs)
|
9
|
+
kwargs = kwargs.first
|
10
|
+
|
11
|
+
klass._stators[kwargs[:namespace]] ||= new(klass, **kwargs)
|
12
|
+
end
|
13
|
+
|
14
|
+
def klass
|
15
|
+
@klass ||= class_name.constantize
|
16
|
+
end
|
3
17
|
|
4
|
-
|
5
|
-
|
6
|
-
attr_reader :transition_names
|
7
|
-
attr_reader :transitions
|
8
|
-
attr_reader :states
|
9
|
-
attr_reader :namespace
|
18
|
+
def initialize(klass, *options)
|
19
|
+
options = options.first
|
10
20
|
|
11
|
-
def initialize(klass, options = {})
|
12
21
|
@class_name = klass.name
|
13
22
|
@field = options[:field] || :state
|
14
|
-
@namespace = options[:namespace]
|
23
|
+
@namespace = (options[:namespace] || Stator.default_namespace).to_sym
|
15
24
|
|
16
|
-
@initial_state = options[:initial]
|
25
|
+
@initial_state = options[:initial]&.to_sym
|
26
|
+
@states = [initial_state].compact
|
17
27
|
@tracking_enabled = options[:track] || false
|
18
28
|
|
19
29
|
@transitions = []
|
20
30
|
@aliases = []
|
21
31
|
|
22
|
-
|
23
|
-
@transition_names = []
|
24
|
-
@states = [@initial_state].compact
|
25
|
-
|
26
|
-
@options = options
|
32
|
+
@options = options
|
27
33
|
end
|
28
34
|
|
29
|
-
|
30
|
-
|
35
|
+
alias tracking_enabled? tracking_enabled
|
36
|
+
|
37
|
+
def evaluate_dsl(&block)
|
38
|
+
instance_eval(&block)
|
39
|
+
evaluate
|
31
40
|
end
|
32
41
|
|
33
|
-
def
|
34
|
-
|
42
|
+
def integration(record)
|
43
|
+
Stator::Integration.new(self, record)
|
35
44
|
end
|
36
45
|
|
37
46
|
def transition(name, &block)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
verify_transition_validity(t)
|
47
|
+
Stator::Transition.new(class_name, name, namespace).tap do |t|
|
48
|
+
t.instance_eval(&block) if block_given?
|
42
49
|
|
43
|
-
|
44
|
-
@transition_names |= [t.full_name] unless t.full_name.blank?
|
45
|
-
@states |= [t.to_state] unless t.to_state.nil?
|
50
|
+
verify_transition_validity(t)
|
46
51
|
|
47
|
-
t
|
52
|
+
@transitions << t
|
53
|
+
@states |= [t.to_state] unless t.to_state.nil?
|
54
|
+
end
|
48
55
|
end
|
49
56
|
|
50
57
|
def state_alias(name, options = {}, &block)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
Stator::Alias.new(self, name, options).tap do |a|
|
59
|
+
# puts "ALIAS: #{a.inspect}"
|
60
|
+
a.instance_eval(&block) if block_given?
|
61
|
+
@aliases << a
|
62
|
+
end
|
55
63
|
end
|
56
64
|
|
57
65
|
def state(name, &block)
|
@@ -62,33 +70,31 @@ module Stator
|
|
62
70
|
end
|
63
71
|
end
|
64
72
|
|
65
|
-
def tracking_enabled?
|
66
|
-
@tracking_enabled
|
67
|
-
end
|
68
|
-
|
69
73
|
def conditional(*states, &block)
|
70
|
-
|
74
|
+
state_check = proc { states.include?(current_state) }
|
71
75
|
|
72
|
-
klass.instance_exec(
|
76
|
+
klass.instance_exec(state_check, &block)
|
73
77
|
end
|
74
78
|
|
75
79
|
def matching_transition(from, to)
|
76
|
-
|
77
|
-
transition.valid?(from, to)
|
78
|
-
end
|
80
|
+
transitions.detect { |transition| transition.valid?(from, to) }
|
79
81
|
end
|
80
82
|
|
81
83
|
def evaluate
|
82
|
-
|
83
|
-
|
84
|
+
transitions.each(&:evaluate)
|
85
|
+
aliases.each(&:evaluate)
|
84
86
|
generate_methods
|
85
87
|
end
|
86
88
|
|
87
|
-
|
88
|
-
@class_name.constantize
|
89
|
-
end
|
89
|
+
private
|
90
90
|
|
91
|
-
|
91
|
+
def attr_name(name)
|
92
|
+
if namespace == Stator.default_namespace
|
93
|
+
name.to_sym
|
94
|
+
else
|
95
|
+
[namespace, name].compact.join('_').to_sym
|
96
|
+
end
|
97
|
+
end
|
92
98
|
|
93
99
|
def verify_transition_validity(transition)
|
94
100
|
verify_state_singularity_of_transition(transition)
|
@@ -98,34 +104,29 @@ module Stator
|
|
98
104
|
def verify_state_singularity_of_transition(transition)
|
99
105
|
transition.from_states.each do |from|
|
100
106
|
if matching_transition(from, transition.to_state)
|
101
|
-
raise "[Stator] another transition already exists which moves #{
|
107
|
+
raise "[Stator] another transition already exists which moves #{class_name} from #{from} to #{transition}"
|
102
108
|
end
|
103
109
|
end
|
104
110
|
end
|
105
111
|
|
106
112
|
def verify_name_singularity_of_transition(transition)
|
107
|
-
if
|
108
|
-
raise "[Stator] another transition already exists with the name of #{transition.name
|
113
|
+
if transitions.detect { |other| transition.name && transition.name == other.name }
|
114
|
+
raise "[Stator] another transition already exists with the name of #{transition.name} in the #{class_name} class"
|
109
115
|
end
|
110
116
|
end
|
111
117
|
|
112
118
|
def generate_methods
|
113
|
-
|
114
|
-
method_name = [@namespace, state].compact.join('_')
|
119
|
+
states.each do |state|
|
115
120
|
klass.class_eval <<-EV, __FILE__, __LINE__ + 1
|
116
|
-
def #{
|
117
|
-
|
118
|
-
integration.state == #{state.to_s.inspect}
|
121
|
+
def #{attr_name(state)}?
|
122
|
+
_stator_integration(:#{namespace}).state.to_sym == :#{state}
|
119
123
|
end
|
120
124
|
|
121
|
-
def #{
|
122
|
-
|
123
|
-
integration.state_by?(#{state.to_s.inspect}, time)
|
125
|
+
def #{attr_name(state)}_state_by?(time)
|
126
|
+
_stator_integration(:#{namespace}).state_by?(:#{state}.to_sym, time)
|
124
127
|
end
|
125
128
|
EV
|
126
129
|
end
|
127
130
|
end
|
128
|
-
|
129
|
-
|
130
131
|
end
|
131
132
|
end
|
data/lib/stator/model.rb
CHANGED
@@ -1,113 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Stator
|
2
4
|
module Model
|
5
|
+
extend ActiveSupport::Concern
|
3
6
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
+
included do
|
8
|
+
class_attribute :_stators
|
9
|
+
attr_accessor :_stator_integrations
|
7
10
|
|
8
|
-
|
9
|
-
include TrackerMethods if options[:track] == true
|
11
|
+
validate :_stator_validate_transition
|
10
12
|
|
11
13
|
self._stators ||= {}
|
12
14
|
|
13
|
-
|
14
|
-
f = options[:field] || :state
|
15
|
-
# rescue nil since the table may not exist yet.
|
16
|
-
initial = self.columns_hash[f.to_s].default rescue nil
|
17
|
-
options = options.merge(initial: initial) if initial
|
18
|
-
end
|
19
|
-
|
20
|
-
machine = (self._stators[options[:namespace].to_s] ||= ::Stator::Machine.new(self, options))
|
21
|
-
|
22
|
-
if block_given?
|
23
|
-
machine.instance_eval(&block)
|
24
|
-
machine.evaluate
|
25
|
-
end
|
26
|
-
|
27
|
-
machine
|
15
|
+
before_save :_stator_maybe_track_transition, prepend: true
|
28
16
|
end
|
29
17
|
|
30
|
-
|
31
|
-
|
32
|
-
|
18
|
+
class_methods do
|
19
|
+
def stator(namespace: nil, field: :state, initial: nil, track: true, &block)
|
20
|
+
unless abstract_class?
|
21
|
+
# Discover the default value (usually initial) from the table...
|
22
|
+
# but rescue nil since the table may not exist yet.
|
23
|
+
initial = _determine_initial_stator_state(field)
|
24
|
+
end
|
33
25
|
|
34
|
-
|
26
|
+
opts = { namespace: _stator_namespace(namespace), field: field.to_sym, initial: initial, track: track }
|
35
27
|
|
36
|
-
|
37
|
-
|
38
|
-
before_save :_stator_maybe_track_transition, prepend: true
|
28
|
+
Stator::Machine.find_or_create(self, **opts).tap do |machine|
|
29
|
+
machine.evaluate_dsl(&block) if block_given?
|
39
30
|
end
|
40
31
|
end
|
41
32
|
|
42
|
-
def
|
43
|
-
|
33
|
+
def _stator(namespace)
|
34
|
+
self._stators[_stator_namespace(namespace)]
|
44
35
|
end
|
45
36
|
|
46
|
-
def
|
47
|
-
|
48
|
-
end
|
37
|
+
def _stator_namespace(namespace = nil)
|
38
|
+
namespace = nil if namespace.blank?
|
49
39
|
|
50
|
-
|
51
|
-
_integration(namespace).state_by?(state, t)
|
40
|
+
(namespace || Stator.default_namespace).to_sym
|
52
41
|
end
|
53
42
|
|
54
|
-
|
43
|
+
def _determine_initial_stator_state(field)
|
44
|
+
columns_hash[field.to_s].default.to_sym
|
45
|
+
rescue StandardError
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
55
49
|
|
56
|
-
|
57
|
-
|
58
|
-
|
50
|
+
def initialize_dup(other)
|
51
|
+
@_stator_integrations = {}
|
52
|
+
super
|
53
|
+
end
|
59
54
|
|
60
|
-
|
61
|
-
|
55
|
+
def without_state_transition_validations(namespace = '')
|
56
|
+
_stator_integration(namespace).without_validation do
|
57
|
+
yield self
|
58
|
+
end
|
59
|
+
end
|
62
60
|
|
63
|
-
|
61
|
+
def without_state_transition_tracking(namespace = '')
|
62
|
+
_stator_integration(namespace).without_transition_tracking do
|
63
|
+
yield self
|
64
64
|
end
|
65
|
+
end
|
65
66
|
|
67
|
+
def current_state
|
68
|
+
_stator_integration.state&.to_sym
|
66
69
|
end
|
67
70
|
|
68
|
-
|
71
|
+
def in_state_at?(state, t, namespace = '')
|
72
|
+
_stator_integration(namespace).in_state_at?(state, t)
|
73
|
+
end
|
69
74
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
75
|
+
def likely_state_at(t, namespace = '')
|
76
|
+
_stator_integration(namespace).likely_state_at(t)
|
77
|
+
end
|
75
78
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
79
|
+
def state_by?(state, t, namespace = '')
|
80
|
+
_stator_integration(namespace).state_by?(state, t)
|
81
|
+
end
|
80
82
|
|
81
|
-
|
82
|
-
_integration(namespace).without_validation do
|
83
|
-
yield self
|
84
|
-
end
|
85
|
-
end
|
83
|
+
private
|
86
84
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
85
|
+
# core methods
|
86
|
+
def _stator(namespace = nil)
|
87
|
+
self.class._stator(namespace)
|
88
|
+
end
|
92
89
|
|
93
|
-
|
90
|
+
def _stator_namespace(namespace = nil)
|
91
|
+
self.class._stator_namespace(namespace)
|
92
|
+
end
|
94
93
|
|
95
|
-
|
96
|
-
|
97
|
-
_integration(namespace).validate_transition
|
98
|
-
end
|
99
|
-
end
|
94
|
+
def _stator_integration(namespace = nil)
|
95
|
+
ns = _stator_namespace(namespace)
|
100
96
|
|
101
|
-
|
102
|
-
|
97
|
+
self._stator_integrations ||= {}
|
98
|
+
self._stator_integrations[ns] ||= self.class._stator(ns).integration(self)
|
99
|
+
end
|
100
|
+
|
101
|
+
# validation/transitional
|
102
|
+
def _stator_validate_transition
|
103
|
+
self._stators.each_key do |namespace|
|
104
|
+
_stator_integration(namespace).validate_transition
|
103
105
|
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def _stator_maybe_track_transition
|
109
|
+
self._stators.each do |namespace, machine|
|
110
|
+
next unless machine.tracking_enabled?
|
104
111
|
|
105
|
-
|
106
|
-
@_integrations ||= {}
|
107
|
-
@_integrations[namespace] ||= _stator(namespace).integration(self)
|
108
|
-
@_integrations[namespace]
|
112
|
+
_stator_integration(namespace).track_transition
|
109
113
|
end
|
110
114
|
|
115
|
+
true
|
111
116
|
end
|
112
117
|
end
|
113
118
|
end
|
data/lib/stator/transition.rb
CHANGED
@@ -1,44 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Stator
|
2
4
|
class Transition
|
3
|
-
|
4
|
-
ANY = '__any__'
|
5
|
-
|
6
|
-
attr_reader :name
|
7
|
-
attr_reader :full_name
|
5
|
+
attr_reader :namespace, :name, :attr_name, :from_states, :to_state, :class_name, :callbacks
|
8
6
|
|
9
7
|
def initialize(class_name, name, namespace = nil)
|
10
|
-
@class_name
|
11
|
-
@name
|
12
|
-
@namespace
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@callbacks = {}
|
8
|
+
@class_name = class_name
|
9
|
+
@name = name&.to_sym
|
10
|
+
@namespace = namespace&.to_sym
|
11
|
+
@from_states = []
|
12
|
+
@to_state = nil
|
13
|
+
@callbacks = {}
|
17
14
|
end
|
18
15
|
|
19
|
-
def
|
20
|
-
@
|
16
|
+
def attr_name
|
17
|
+
@attr_name ||= generate_attr_name
|
21
18
|
end
|
22
19
|
|
23
|
-
def
|
24
|
-
@
|
20
|
+
def from_states(*new_froms)
|
21
|
+
@from_states |= new_froms
|
25
22
|
end
|
23
|
+
alias from from_states
|
26
24
|
|
27
|
-
def
|
28
|
-
@
|
29
|
-
end
|
30
|
-
|
31
|
-
def from_states
|
32
|
-
@froms
|
25
|
+
def to(new_to)
|
26
|
+
@to_state = new_to
|
33
27
|
end
|
34
28
|
|
35
29
|
def can?(current_state)
|
36
|
-
|
30
|
+
from_states.include?(current_state) || from_states.include?(Stator::ANY) || current_state == Stator::ANY
|
37
31
|
end
|
38
32
|
|
39
|
-
def valid?(
|
40
|
-
|
41
|
-
|
33
|
+
def valid?(from_check, to_check)
|
34
|
+
from_check = from_check&.to_sym # coming from the database, i suspect
|
35
|
+
|
36
|
+
can?(from_check) && (to_check == to_state || to_check == ANY || to_state == ANY)
|
42
37
|
end
|
43
38
|
|
44
39
|
def conditional(options = {}, &block)
|
@@ -46,79 +41,85 @@ module Stator
|
|
46
41
|
end
|
47
42
|
|
48
43
|
def any
|
49
|
-
ANY
|
44
|
+
Stator::ANY
|
50
45
|
end
|
51
46
|
|
52
47
|
def evaluate
|
53
|
-
generate_methods
|
48
|
+
generate_methods if attr_name.present?
|
54
49
|
end
|
55
50
|
|
56
|
-
|
51
|
+
private
|
57
52
|
|
58
53
|
def klass
|
59
|
-
|
54
|
+
class_name.constantize
|
55
|
+
end
|
56
|
+
|
57
|
+
def generate_attr_name
|
58
|
+
if namespace == Stator.default_namespace
|
59
|
+
name
|
60
|
+
else
|
61
|
+
[namespace, name].compact.join('_').to_sym
|
62
|
+
end
|
60
63
|
end
|
61
64
|
|
62
65
|
def callbacks(kind)
|
63
|
-
|
66
|
+
callbacks[kind] || []
|
64
67
|
end
|
65
68
|
|
66
69
|
def conditional_block(options = {})
|
67
70
|
options[:use_previous] ||= false
|
68
71
|
|
69
|
-
_namespace =
|
70
|
-
_froms =
|
71
|
-
_to =
|
72
|
-
|
73
|
-
|
74
|
-
(
|
75
|
-
|
76
|
-
) &&
|
77
|
-
_froms.include?(
|
78
|
-
_froms.include?(
|
79
|
-
|
80
|
-
self._stator(_namespace).integration(self).state == _to ||
|
81
|
-
_to == ::Stator::Transition::ANY
|
82
|
-
)
|
72
|
+
_namespace = namespace
|
73
|
+
_froms = from_states
|
74
|
+
_to = to_state
|
75
|
+
|
76
|
+
proc do
|
77
|
+
integration = self.class._stator(_namespace).integration(self)
|
78
|
+
|
79
|
+
integration.state_changed?(options[:use_previous]) &&
|
80
|
+
_froms.include?(integration.state_was(options[:use_previous])) ||
|
81
|
+
_froms.include?(Stator::ANY) &&
|
82
|
+
integration.state == _to || _to == Stator::ANY
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
def generate_methods
|
87
87
|
klass.class_eval <<-EV, __FILE__, __LINE__ + 1
|
88
|
-
def #{
|
89
|
-
integration =
|
88
|
+
def #{attr_name}(should_save = true)
|
89
|
+
integration = _stator_integration(:#{namespace})
|
90
90
|
|
91
|
-
unless can_#{
|
92
|
-
integration.invalid_transition!(integration.state,
|
91
|
+
unless can_#{attr_name}?
|
92
|
+
integration.invalid_transition!(integration.state, :#{to_state}) if should_save
|
93
93
|
return false
|
94
94
|
end
|
95
95
|
|
96
|
-
integration.state =
|
96
|
+
integration.state = :#{to_state}
|
97
|
+
|
97
98
|
self.save if should_save
|
98
99
|
end
|
99
100
|
|
100
|
-
def #{
|
101
|
-
integration =
|
101
|
+
def #{attr_name}!
|
102
|
+
integration = _stator_integration(:#{namespace})
|
102
103
|
|
103
|
-
unless can_#{
|
104
|
-
integration.invalid_transition!(integration.state,
|
104
|
+
unless can_#{attr_name}?
|
105
|
+
integration.invalid_transition!(integration.state, :#{to_state})
|
105
106
|
raise ActiveRecord::RecordInvalid.new(self)
|
106
107
|
end
|
107
108
|
|
108
|
-
integration.state =
|
109
|
+
integration.state = :#{to_state}
|
109
110
|
self.save!
|
110
111
|
end
|
111
112
|
|
112
|
-
def can_#{
|
113
|
-
integration =
|
113
|
+
def can_#{attr_name}?
|
114
|
+
integration = _stator_integration(:#{namespace})
|
114
115
|
return true if integration.skip_validations
|
115
116
|
|
116
|
-
machine = self._stator(
|
117
|
-
transition = machine.transitions.detect{|t| t.
|
117
|
+
machine = self._stator(:#{namespace})
|
118
|
+
transition = machine.transitions.detect { |t| t.attr_name == :#{attr_name} }
|
119
|
+
|
118
120
|
transition.can?(integration.state)
|
119
121
|
end
|
120
122
|
EV
|
121
123
|
end
|
122
|
-
|
123
124
|
end
|
124
125
|
end
|
data/lib/stator/version.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Stator
|
4
|
-
|
5
4
|
MAJOR = 0
|
6
|
-
MINOR =
|
5
|
+
MINOR = 9
|
7
6
|
PATCH = 0
|
8
|
-
PRERELEASE =
|
9
|
-
|
10
|
-
VERSION = [MAJOR, MINOR, PATCH, PRERELEASE].compact.join(".")
|
7
|
+
PRERELEASE = "beta"
|
11
8
|
|
9
|
+
VERSION = [MAJOR, MINOR, PATCH, PRERELEASE].compact.join('.')
|
12
10
|
end
|
data/lib/stator.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'stator/version'
|
2
4
|
require 'stator/alias'
|
3
5
|
require 'stator/integration'
|
4
6
|
require 'stator/machine'
|
5
7
|
require 'stator/model'
|
6
8
|
require 'stator/transition'
|
9
|
+
|
10
|
+
require 'active_support/concern'
|
11
|
+
require 'debug'
|
12
|
+
|
13
|
+
module Stator
|
14
|
+
ANY = :__ANY__
|
15
|
+
|
16
|
+
def self.default_namespace
|
17
|
+
ENV.fetch('STATOR_NAMESPACE', :default).to_sym
|
18
|
+
end
|
19
|
+
end
|