Class: RSpec::Core::Hooks::HookCollections

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/core/hooks.rb

Overview

This provides the primary API used by other parts of rspec-core. By hiding all implementation details behind this facade, it's allowed us to heavily optimize this, so that, for example, hook collection objects are only instantiated when a hook is added. This allows us to avoid many object allocations for the common case of a group having no hooks.

This is only possible because this interface provides a “tell, don't ask”-style API, so that callers tell this class what to do with the hooks, rather than asking this class for a list of hooks, and then doing something with them.

Constant Summary

SCOPES =
[:example, :context]
SCOPE_ALIASES =
{ :each => :example, :all => :context }
HOOK_TYPES =
{
  :before => Hash.new { BeforeHook },
  :after  => Hash.new { AfterHook  },
  :around => Hash.new { AroundHook }
}

Instance Method Summary collapse

Constructor Details

#initialize(owner, filterable_item_repo_class) ⇒ HookCollections

Returns a new instance of HookCollections



404
405
406
407
408
409
410
411
412
# File 'lib/rspec/core/hooks.rb', line 404

def initialize(owner, filterable_item_repo_class)
  @owner                      = owner
  @filterable_item_repo_class = filterable_item_repo_class
  @before_example_hooks       = nil
  @after_example_hooks        = nil
  @before_context_hooks       = nil
  @after_context_hooks        = nil
  @around_example_hooks       = nil
end

Instance Method Details

#register(prepend_or_append, position, *args, &block) ⇒ Object



432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# File 'lib/rspec/core/hooks.rb', line 432

def register(prepend_or_append, position, *args, &block)
  scope, options = scope_and_options_from(*args)

  if scope == :suite
    # TODO: consider making this an error in RSpec 4. For SemVer reasons,
    # we are only warning in RSpec 3.
    RSpec.warn_with "WARNING: `#{position}(:suite)` hooks are only supported on " \
                    "the RSpec configuration object. This " \
                    "`#{position}(:suite)` hook, registered on an example " \
                    "group, will be ignored."
    return
  end

  hook = HOOK_TYPES[position][scope].new(block, options)
  ensure_hooks_initialized_for(position, scope).__send__(prepend_or_append, hook, options)
end

#register_global_singleton_context_hooks(example, globals) ⇒ Object



425
426
427
428
429
430
# File 'lib/rspec/core/hooks.rb', line 425

def register_global_singleton_context_hooks(example, globals)
  parent_groups = example.example_group.parent_groups

  process(example, parent_groups, globals, :before, :context) { {} }
  process(example, parent_groups, globals, :after,  :context) { {} }
end

#register_globals(host, globals) ⇒ Object



414
415
416
417
418
419
420
421
422
423
# File 'lib/rspec/core/hooks.rb', line 414

def register_globals(host, globals)
  parent_groups = host.parent_groups

  process(host, parent_groups, globals, :before, :example, &:options)
  process(host, parent_groups, globals, :after,  :example, &:options)
  process(host, parent_groups, globals, :around, :example, &:options)

  process(host, parent_groups, globals, :before, :context, &:options)
  process(host, parent_groups, globals, :after,  :context, &:options)
end

#run(position, scope, example_or_group) ⇒ Object

Runs all of the blocks stored with the hook in the context of the example. If no example is provided, just calls the hook directly.



453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'lib/rspec/core/hooks.rb', line 453

def run(position, scope, example_or_group)
  return if RSpec.configuration.dry_run?

  if scope == :context
    unless example_or_group.class.[:skip]
      run_owned_hooks_for(position, :context, example_or_group)
    end
  else
    case position
    when :before then run_example_hooks_for(example_or_group, :before, :reverse_each)
    when :after  then run_example_hooks_for(example_or_group, :after,  :each)
    when :around then run_around_example_hooks_for(example_or_group) { yield }
    end
  end
end