Module: Mongoid::Interceptable
- Extended by:
- ActiveSupport::Concern
- Included in:
- Composable
- Defined in:
- lib/mongoid/interceptable.rb
Overview
This module contains all the callback hooks for Mongoid.
Constant Summary collapse
- CALLBACKS =
%i[ after_build after_create after_destroy after_find after_initialize after_save after_touch after_update after_upsert after_validation around_create around_destroy around_save around_update around_upsert before_create before_destroy before_save before_update before_upsert before_validation ].freeze
Instance Method Summary collapse
-
#_mongoid_run_child_after_callbacks(callback_list: []) ⇒ Object
Execute the after callbacks.
-
#_mongoid_run_child_before_callbacks(kind, children: [], callback_list: []) ⇒ Object
private
Execute the before callbacks of given kind for embedded documents.
-
#_mongoid_run_child_callbacks(kind, children: nil, &block) ⇒ Object
private
Run the callbacks for embedded documents.
-
#_mongoid_run_child_callbacks_with_around(kind, children: nil, &block) ⇒ Object
Execute the callbacks of given kind for embedded documents including around callbacks.
-
#_mongoid_run_child_callbacks_without_around(kind, children: nil, &block) ⇒ Object
private
Execute the callbacks of given kind for embedded documents without around callbacks.
-
#callback_executable?(kind) ⇒ true | false
Is the provided type of callback executable by this document?.
-
#in_callback_state?(kind) ⇒ true | false
Is the document currently in a state that could potentially require callbacks to be executed?.
-
#pending_callbacks ⇒ Array<Symbol>
private
Returns the stored callbacks to be executed later.
-
#pending_callbacks=(value) ⇒ Array<Symbol>
private
Stores callbacks to be executed later.
-
#run_after_callbacks(*kinds) ⇒ Object
Run only the after callbacks for the specific event.
-
#run_before_callbacks(*kinds) ⇒ Object
Run only the before callbacks for the specific event.
-
#run_callbacks(kind, with_children: true, skip_if: nil, &block) ⇒ Object
Run the callbacks for the document.
-
#run_pending_callbacks ⇒ Object
private
Run the pending callbacks.
Instance Method Details
#_mongoid_run_child_after_callbacks(callback_list: []) ⇒ Object
Execute the after callbacks.
247 248 249 250 251 252 |
# File 'lib/mongoid/interceptable.rb', line 247 def _mongoid_run_child_after_callbacks(callback_list: []) callback_list.reverse_each do |next_sequence, env| next_sequence.invoke_after(env) return false if env.halted end end |
#_mongoid_run_child_before_callbacks(kind, children: [], callback_list: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Execute the before callbacks of given kind for embedded documents.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/mongoid/interceptable.rb', line 225 def _mongoid_run_child_before_callbacks(kind, children: [], callback_list: []) children.each do |child| chain = child.__callbacks[child_callback_type(kind, child)] env = ActiveSupport::Callbacks::Filters::Environment.new(child, false, nil) next_sequence = compile_callbacks(chain) unless next_sequence.final? Mongoid.logger.warn("Around callbacks are disabled for embedded documents. Skipping around callbacks for #{child.class.name}.") Mongoid.logger.warn('To enable around callbacks for embedded documents, set Mongoid::Config.around_callbacks_for_embeds to true.') end next_sequence.invoke_before(env) return false if env.halted env.value = !env.halted callback_list << [ next_sequence, env ] end callback_list end |
#_mongoid_run_child_callbacks(kind, children: nil, &block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Run the callbacks for embedded documents.
148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/mongoid/interceptable.rb', line 148 def _mongoid_run_child_callbacks(kind, children: nil, &block) if Mongoid::Config. _mongoid_run_child_callbacks_with_around(kind, children: children, &block) else _mongoid_run_child_callbacks_without_around(kind, children: children, &block) end end |
#_mongoid_run_child_callbacks_with_around(kind, children: nil, &block) ⇒ Object
Execute the callbacks of given kind for embedded documents including around callbacks.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/mongoid/interceptable.rb', line 169 def _mongoid_run_child_callbacks_with_around(kind, children: nil, &block) children ||= cascadable_children(kind) with_children = !Mongoid::Config. return block&.call if children.empty? fibers = children.map do |child| Fiber.new do child.run_callbacks(child_callback_type(kind, child), with_children: with_children) do Fiber.yield end end end fibers.each do |fiber| fiber.resume raise Mongoid::Errors::InvalidAroundCallback unless fiber.alive? end block&.call fibers.reverse.each(&:resume) end |
#_mongoid_run_child_callbacks_without_around(kind, children: nil, &block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Execute the callbacks of given kind for embedded documents without around callbacks.
202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/mongoid/interceptable.rb', line 202 def _mongoid_run_child_callbacks_without_around(kind, children: nil, &block) children ||= cascadable_children(kind) callback_list = _mongoid_run_child_before_callbacks(kind, children: children) return false if callback_list == false value = block&.call callback_list.each do |_next_sequence, env| env.value &&= value end return false if _mongoid_run_child_after_callbacks(callback_list: callback_list) == false value end |
#callback_executable?(kind) ⇒ true | false
Is the provided type of callback executable by this document?
60 61 62 |
# File 'lib/mongoid/interceptable.rb', line 60 def callback_executable?(kind) respond_to?("_#{kind}_callbacks") end |
#in_callback_state?(kind) ⇒ true | false
Is the document currently in a state that could potentially require callbacks to be executed?
73 74 75 |
# File 'lib/mongoid/interceptable.rb', line 73 def in_callback_state?(kind) %i[create destroy].include?(kind) || new_record? || flagged_for_destroy? || changed? end |
#pending_callbacks ⇒ Array<Symbol>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the stored callbacks to be executed later.
259 260 261 |
# File 'lib/mongoid/interceptable.rb', line 259 def pending_callbacks @pending_callbacks ||= [].to_set end |
#pending_callbacks=(value) ⇒ Array<Symbol>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Stores callbacks to be executed later. A good use case for this is delaying the after_find and after_initialize callbacks until the associations are set on the document. This can also be used to delay applying the defaults on a document.
273 274 275 |
# File 'lib/mongoid/interceptable.rb', line 273 def pending_callbacks=(value) @pending_callbacks = value end |
#run_after_callbacks(*kinds) ⇒ Object
ActiveSupport does not allow this type of behavior by default, so Mongoid has to get around it and implement itself.
Run only the after callbacks for the specific event.
88 89 90 91 92 |
# File 'lib/mongoid/interceptable.rb', line 88 def run_after_callbacks(*kinds) kinds.each do |kind| run_targeted_callbacks(:after, kind) end end |
#run_before_callbacks(*kinds) ⇒ Object
ActiveSupport does not allow this type of behavior by default, so Mongoid has to get around it and implement itself.
Run only the before callbacks for the specific event.
105 106 107 108 109 |
# File 'lib/mongoid/interceptable.rb', line 105 def run_before_callbacks(*kinds) kinds.each do |kind| run_targeted_callbacks(:before, kind) end end |
#run_callbacks(kind, with_children: true, skip_if: nil, &block) ⇒ Object
Run the callbacks for the document. This overrides active support's functionality to cascade callbacks to embedded documents that have been flagged as such.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/mongoid/interceptable.rb', line 125 def run_callbacks(kind, with_children: true, skip_if: nil, &block) return block&.call if skip_if&.call if with_children cascadable_children(kind).each do |child| return false if child.run_callbacks(child_callback_type(kind, child), with_children: with_children) == false end end if callback_executable?(kind) super(kind, &block) else true end end |
#run_pending_callbacks ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Run the pending callbacks. If the callback is :apply_defaults, we will apply the defaults for this document. Otherwise, the callback is passed to the run_callbacks function.
282 283 284 285 286 287 288 289 290 291 |
# File 'lib/mongoid/interceptable.rb', line 282 def run_pending_callbacks pending_callbacks.each do |cb| if %i[apply_defaults apply_post_processed_defaults].include?(cb) send(cb) else run_callbacks(cb, with_children: false) end end pending_callbacks.clear end |