state_gate 1.2.3 → 1.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a3a28a8136472a91cd7c75616e189dd2c92a7b57a0bc18645395a46c55ff906
4
- data.tar.gz: c909cd3d3a1101056ff1fe33ea6b94e38008f26a093476d7aaeb4ac17847b1ad
3
+ metadata.gz: c914825dceae121cfabc62d93c48e952d0d1ae4995bc0e477d1e2aa2e0cf9107
4
+ data.tar.gz: e49f5d7fd2517d88a7ae8c225baa452c75aa6cba94828e2e182fcb3462ffccec
5
5
  SHA512:
6
- metadata.gz: 6b9cae6865505456fafa9da807e8472eb148f8af294c7631690b28ebba7b01c20e93f27b2bbe3ccf16c7ec27ea872e604726323bebb7639c7e7db726eb4bdd34
7
- data.tar.gz: 7c104de800820cedee61c177a44504e2e1f052aaf529fd4990d3407ae337a4004c925f12162762f2db66b34a96ecda327e06e0c96c4dfc299feef63885b0e6f6
6
+ metadata.gz: 1042ce00609a2501647803fce1a41b689c45084726011c6f0f36e2498b9ca48110cf7d99160311eed74204f939255332be79894056098ccf2c1883dd88d0e6da
7
+ data.tar.gz: ba89c3bd3d36181c109ab56d5d9a6d8f68f735bfc645075d3dd16f2e8c7f829ff82746ef1db093f76743d05532159b864e75f78a4e960389d22c8ad818d76f84
@@ -14,54 +14,73 @@ module StateGate
14
14
  # ======================================================================
15
15
  private
16
16
 
17
+ ##
17
18
  # Check if a class method is already defined. Checks are made:
18
19
  # 1 --> is it an ActiveRecord dangerous method?
19
20
  # 2 --> is it an ActiveRecord defined class method?
20
21
  # 3 --> is it a singleton method of the klass?
21
22
  # 4 --> is it defined within any of the klass ancestors?
22
23
  #
23
- # If found, raise an error giving a guide to where the method has been defined
24
+ # @param [Symbol] method_name
25
+ # the class method name to test for conclict
24
26
  #
25
- def detect_class_method_conflict!(method_name)
27
+ # @raise [ConflictError]
28
+ # if the method name has already been defined
29
+ #
30
+ def _detect_class_method_conflict!(method_name)
26
31
  defining_klass = _active_record_protected_method?(method_name) ||
27
32
  _klass_singleton_method?(method_name) ||
28
33
  _klass_ancestor_singleton_method?(method_name)
29
34
 
30
35
  return unless defining_klass
31
36
 
32
- raise_conflict_error method_name, type: 'a class', source: defining_klass
37
+ _raise_conflict_error method_name, type: 'a class', source: defining_klass
33
38
  end
34
39
 
35
40
 
36
41
 
42
+ ##
37
43
  # Check an instance method is already defined. Checks are made:
38
44
  # 1 --> is it an ActiveRecord dangerous method?
39
45
  # 2 --> is it an ActiveRecord defined instance method?
40
46
  # 3 --> is it an instance method of the klass?
41
47
  # 4 --> is it defined within any of the klass ancestors?
42
48
  #
43
- # If found, raise an error giving a guide to where the method has been defined
49
+ # @param [Symbol] method_name
50
+ # the instance method name to test for conclict
51
+ #
52
+ # @raise [ConflictError]
53
+ # if the method name has already been defined
44
54
  #
45
- def detect_instance_method_conflict!(method_name)
55
+ def _detect_instance_method_conflict!(method_name)
46
56
  defining_klass = _active_record_protected_method?(method_name) ||
47
57
  _klass_instance_method?(method_name) ||
48
58
  _klass_ancestor_instance_method?(method_name)
49
59
 
50
60
  return unless defining_klass
51
61
 
52
- raise_conflict_error method_name, source: defining_klass
62
+ _raise_conflict_error method_name, source: defining_klass
53
63
  end
54
64
 
55
65
 
56
66
 
57
67
  # Raise a StateGate::ConflictError with a details message of the problem
58
68
  #
59
- # = Message
69
+ # @param [Symbol] method_name
70
+ # the method name
71
+ #
72
+ # @param [String] type
73
+ # the optional definition of which type of errors this is: instance or class
60
74
  #
61
- # StateGate for Klass#attribute will generate a class
62
- # method 'statuses', which is already defined by ActiveRecord.
75
+ # @param [String] source
76
+ # the optional class name
63
77
  #
64
- def raise_conflict_error(method_name, type: 'an instance', source: 'ActiveRecord')
78
+ # @raise [ConflictError]
79
+ # with the message:
80
+ # StateGate for Klass#attribute will generate a class
81
+ # method 'statuses', which is already defined by ActiveRecord.
82
+ #
83
+ def _raise_conflict_error(method_name, type: 'an instance', source: 'ActiveRecord')
65
84
  fail StateGate::ConflictError, I18n.t('state_gate.builder.conflict_err',
66
85
  klass: @klass,
67
86
  attribute: @attribute,
@@ -72,25 +91,37 @@ module StateGate
72
91
 
73
92
 
74
93
 
94
+ ##
75
95
  # Check if the method is an ActiveRecord dangerous method name
76
96
  #
77
- def _active_record_protected_method?(method_name) #:nodoc:
97
+ # @param [Symbol] method_name
98
+ # the method name
99
+ #
100
+ def _active_record_protected_method?(method_name)
78
101
  'ActiveRecord' if _dangerous_method_names.include?(method_name)
79
102
  end
80
103
 
81
104
 
82
105
 
106
+ ##
83
107
  # Check if the method is a singleton method of the klass
84
108
  #
85
- def _klass_singleton_method?(method_name) #:nodoc:
109
+ # @param [Symbol] method_name
110
+ # the method name
111
+ #
112
+ def _klass_singleton_method?(method_name)
86
113
  @klass.name if @klass.singleton_methods(false).include?(method_name.to_sym)
87
114
  end
88
115
 
89
116
 
90
117
 
118
+ ##
91
119
  # Check if the method is an ancestral singleton method of the klass
92
120
  #
93
- def _klass_ancestor_singleton_method?(method_name) #:nodoc:
121
+ # @param [Symbol] method_name
122
+ # the method name
123
+ #
124
+ def _klass_ancestor_singleton_method?(method_name)
94
125
  return nil unless @klass.respond_to?(method_name)
95
126
 
96
127
  @klass.singleton_class
@@ -101,17 +132,25 @@ module StateGate
101
132
 
102
133
 
103
134
 
135
+ ##
104
136
  # Check if the method an instance method of the klass
105
137
  #
106
- def _klass_instance_method?(method_name) #:nodoc:
138
+ # @param [Symbol] method_name
139
+ # the method name
140
+ #
141
+ def _klass_instance_method?(method_name)
107
142
  @klass.instance_methods(false).include?(method_name.to_sym) ? @klass.name : nil
108
143
  end
109
144
 
110
145
 
111
146
 
147
+ ##
112
148
  # Check if the method is an ancestral singleton method of the klass
113
149
  #
114
- def _klass_ancestor_instance_method?(method_name) #:nodoc:
150
+ # @param [Symbol] method_name
151
+ # the method name
152
+ #
153
+ def _klass_ancestor_instance_method?(method_name)
115
154
  return nil unless @klass.instance_methods.include?(method_name.to_sym)
116
155
 
117
156
  @klass.ancestors
@@ -121,9 +160,11 @@ module StateGate
121
160
 
122
161
 
123
162
 
124
- # returns an array of dagerous methods names found in
125
- # ActiveRecord::AttributeMethods::RESTRICTED_CLASS_METHODS (which is called
126
- # BLACKLISTED_CLASS_METHODS in 5.0 and 5.1)
163
+ ##
164
+ # @return [Array[Symbol]]
165
+ # array of dagerous methods names found in
166
+ # ActiveRecord::AttributeMethods::RESTRICTED_CLASS_METHODS (which is called
167
+ # BLACKLISTED_CLASS_METHODS in 5.0 and 5.1)
127
168
  #
128
169
  def _dangerous_method_names
129
170
  %w[private public protected allocate new name parent superclass]
@@ -19,14 +19,15 @@ module StateGate
19
19
  # = Dynamic Module Creation
20
20
  # ======================================================================
21
21
 
22
+ ##
22
23
  # Dynamically generated module to hold the StateGate helper methods. This
23
24
  # keeps a clear distinction between the state machine helper methods and the klass'
24
25
  # own methods.
25
26
  #
26
27
  # The module is named after the class and is created if needed, or reused if exisitng.
27
28
  #
28
- # Note:
29
- # the module is named "<klass>::StateGate_HelperMethods"
29
+ # @note
30
+ # the module is named "<klass>::StateGate_HelperMethods"
30
31
  #
31
32
  def _helper_methods_module
32
33
  @_helper_methods_module ||= begin
@@ -46,6 +47,7 @@ module StateGate
46
47
  # ======================================================================
47
48
 
48
49
 
50
+ ##
49
51
  # Adds the hook method :method_added to the Klass, detecting any new method
50
52
  # definitions for an attribute already defined as a StateGate.
51
53
  #
@@ -54,16 +56,15 @@ module StateGate
54
56
  #
55
57
  # method_name - the name of the newly defined method.
56
58
  #
57
- # Note
59
+ # @note
60
+ # This method is added last so it does not trigger when StateGate adds
61
+ # the attribute methods.
58
62
  #
59
- # This method is added last so it does not trigger when StateGate adds
60
- # the attribute methods.
63
+ # meta
61
64
  #
62
- # meta
63
- #
64
- # * loop though each state machine attribute.
65
- # * does the new defined method use 'attr' or 'attr='?
66
- # * if so then record an error logger if denied, othewise use `puts`
65
+ # - loop though each state machine attribute.
66
+ # - does the new defined method use 'attr' or 'attr='?
67
+ # - if so then record an error logger if denied, othewise use `puts`
67
68
  #
68
69
  def _generate_method_redefine_detection # rubocop:disable Metrics/MethodLength
69
70
  @klass.instance_eval(%(
@@ -89,29 +90,42 @@ module StateGate
89
90
  # Method Creation
90
91
  # ======================================================================
91
92
 
93
+ ##
92
94
  # Add an Class helper method to the _helper_methods_module
93
95
  #
94
- # method_name - a String name for the method, needed to check for conflicts
95
- # file - a String file name for error reporting
96
- # line - a String or Integer line number for error reporting
97
- # method_body - a String to bhe evaluates in the module
96
+ # @param [String] method_name
97
+ # name for the method to check for conflicts
98
+ #
99
+ # @param [String] file
100
+ # file name for error reporting
101
+ #
102
+ # @param [String,Integer] line
103
+ # line number for error reporting
104
+ #
105
+ # @param [String] method_body
106
+ # a String to be evaluated in the module
98
107
  #
99
- def add__klass__helper_method(method_name, file, line, method_body)
100
- detect_class_method_conflict!(method_name)
108
+ def _add__klass__helper_method(method_name, file, line, method_body)
109
+ _detect_class_method_conflict!(method_name)
101
110
  @klass.instance_eval(method_body, file, line)
102
111
  end
103
112
 
104
113
 
105
114
 
115
+ ##
106
116
  # Add an instance helper method to the _helper_methods_module
107
117
  #
108
- # method_name - a String name for the method, needed to check for conflicts
109
- # file - a String file name for error reporting
110
- # line - a String or Integer line number for error reporting
111
- # method_body - a String to bhe evaluates in the module
118
+ # @param [String] method_name
119
+ # name for the method to check for conflicts
120
+ # @param [String] file
121
+ # file name for error reporting
122
+ # @param [String] line
123
+ # line number for error reporting
124
+ # @param [String] method_body
125
+ # a String to bhe evaluates in the module
112
126
  #
113
- def add__instance__helper_method(method_name, file, line, method_body)
114
- detect_instance_method_conflict!(method_name)
127
+ def _add__instance__helper_method(method_name, file, line, method_body)
128
+ _detect_instance_method_conflict!(method_name)
115
129
  _helper_methods_module.module_eval(method_body, file, line)
116
130
  end
117
131
 
@@ -8,14 +8,14 @@ module StateGate
8
8
  # Multiple private methods enabling StateGate::Builder to generate
9
9
  # scopes for each state.
10
10
  #
11
- # * fetch all records with the given state:
12
- # Klass.active # => Klass.where(state: :active)
11
+ # - fetch all records with the given state:
12
+ # Klass.active #=> Klass.where(state: :active)
13
13
  #
14
- # * fetch all records without the given state:
15
- # Klass.not_active # => Klass.where.not(state: :active)
14
+ # - fetch all records without the given state:
15
+ # Klass.not_active #=> Klass.where.not(state: :active)
16
16
  #
17
- # * fetch all records with the supplied states:
18
- # Klass.with_statuses(:pending, :active) # => Klass.where(state: [:pending, :active])
17
+ # - fetch all records with the supplied states:
18
+ # Klass.with_statuses(:pending, :active) #=> Klass.where(state: [:pending, :active])
19
19
  #
20
20
  module ScopeMethods
21
21
 
@@ -24,12 +24,13 @@ module StateGate
24
24
  private
25
25
 
26
26
 
27
+ ##
27
28
  # Add scopes to the klass for filtering by state
28
29
  #
29
- # Note:
30
- # The scope name is a concatenation of <prefix><state name><suffix>
30
+ # @note
31
+ # The scope name is a concatenation of <prefix><state name><suffix>
31
32
  #
32
- def generate_scope_methods
33
+ def _generate_scope_methods
33
34
  return unless @engine.include_scopes?
34
35
 
35
36
  _add__klass__state_scopes
@@ -45,49 +46,58 @@ module StateGate
45
46
  # Klass methods
46
47
  # ======================================================================
47
48
 
49
+ ##
48
50
  # Add a klass method that scopes records to the specified state.
49
- # eg:
50
- # Klass.active # => ActiveRecord::Relation
51
- # Klass.active_status # => ActiveRecord::Relation
51
+ #
52
+ # @example
53
+ # Klass.active #=> ActiveRecord::Relation
54
+ # Klass.active_status #=> ActiveRecord::Relation
52
55
  #
53
56
  def _add__klass__state_scopes
54
57
  attr_name = @attribute
55
58
 
56
59
  @engine.states.each do |state|
57
60
  scope_name = @engine.scope_name_for_state(state)
58
- detect_class_method_conflict! scope_name
61
+ _detect_class_method_conflict! scope_name
59
62
  @klass.scope(scope_name, -> { where(attr_name => state) })
60
63
  end # each state
61
64
  end # _add__klass__state_scopes
62
65
 
63
66
 
64
67
 
68
+ ##
65
69
  # Add a klass method that scopes records to those without the specified state.
66
- # eg:
67
- # Klass.not_active # => ActiveRecord::Relation
68
- # Klass.not_active_status # => ActiveRecord::Relation
70
+ #
71
+ # @example
72
+ # Klass.not_active #=> ActiveRecord::Relation
73
+ # Klass.not_active_status #=> ActiveRecord::Relation
69
74
  #
70
75
  def _add__klass__not_state_scopes
71
76
  attr_name = @attribute
72
77
 
73
78
  @engine.states.each do |state|
74
79
  scope_name = @engine.scope_name_for_state(state)
75
- detect_class_method_conflict! "not_#{scope_name}"
80
+ _detect_class_method_conflict! "not_#{scope_name}"
76
81
  @klass.scope "not_#{scope_name}", -> { where.not(attr_name => state) }
77
82
  end # each state
78
83
  end # _add__klass__not_state_scopes
79
84
 
80
85
 
81
86
 
87
+ ##
82
88
  # Add a klass method that scopes records to the given states.
83
- # eg:
84
- # Klass.with_statuses(:active, :pending) # => ActiveRecord::Relation
89
+ #
90
+ # @param [Symbol] method_name
91
+ # the method name for the new scope
92
+ #
93
+ # @example
94
+ # Klass.with_statuses(:active, :pending) #=> ActiveRecord::Relation
85
95
  #
86
96
  def _add__klass__with_attrs_scope(method_name = @attribute)
87
97
  attr_name = @attribute
88
98
  method_name = "with_#{method_name.to_s.pluralize}"
89
99
 
90
- detect_class_method_conflict! method_name
100
+ _detect_class_method_conflict! method_name
91
101
  @klass.scope method_name, ->(states) { where(attr_name => Array(states)) }
92
102
  end # _add__klass__with_attrs_scope
93
103