class RSpec::Core::Hooks::HookCollections
@private
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.
Constants
- EMPTY_HOOK_ARRAY
- HOOK_TYPES
- SCOPES
- SCOPE_ALIASES
Public Class Methods
# File rspec-core/lib/rspec/core/hooks.rb, line 421 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
Public Instance Methods
# File rspec-core/lib/rspec/core/hooks.rb, line 449 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 elsif scope == :context && position == :around # TODO: consider making this an error in RSpec 4. For SemVer reasons, # we are only warning in RSpec 3. RSpec.warn_with "WARNING: `around(:context)` hooks are not supported and " \ "behave like `around(:example)`." end hook = HOOK_TYPES[position][scope].new(block, options) ensure_hooks_initialized_for(position, scope).__send__(prepend_or_append, hook, options) end
# File rspec-core/lib/rspec/core/hooks.rb, line 442 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
# File rspec-core/lib/rspec/core/hooks.rb, line 431 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
@private
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.
# File rspec-core/lib/rspec/core/hooks.rb, line 475 def run(position, scope, example_or_group) return if RSpec.configuration.dry_run? if scope == :context unless example_or_group.class.metadata[: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
Protected Instance Methods
# File rspec-core/lib/rspec/core/hooks.rb, line 523 def all_hooks_for(position, scope) hooks_for(position, scope) { return EMPTY_HOOK_ARRAY }.items_and_filters.map(&:first) end
# File rspec-core/lib/rspec/core/hooks.rb, line 507 def matching_hooks_for(position, scope, example_or_group) repository = hooks_for(position, scope) { return EMPTY_HOOK_ARRAY } # It would be nice to not have to switch on type here, but # we don't want to define `ExampleGroup#metadata` because then # `metadata` from within an individual example would return the # group's metadata but the user would probably expect it to be # the example's metadata. metadata = case example_or_group when ExampleGroup then example_or_group.class.metadata else example_or_group.metadata end repository.items_for(metadata) end
# File rspec-core/lib/rspec/core/hooks.rb, line 533 def processable_hooks_for(position, scope, host) if scope == :example all_hooks_for(position, scope) else matching_hooks_for(position, scope, host) end end
# File rspec-core/lib/rspec/core/hooks.rb, line 527 def run_owned_hooks_for(position, scope, example_or_group) matching_hooks_for(position, scope, example_or_group).each do |hook| hook.run(example_or_group) end end