@@ -1749,8 +1749,7 @@ def before(scope=nil, *meta, &block)
1749
1749
handle_suite_hook ( scope , meta ) do
1750
1750
@before_suite_hooks << Hooks ::BeforeHook . new ( block , { } )
1751
1751
end || begin
1752
- metadata = Metadata . build_hash_from ( meta . dup )
1753
- on_existing_matching_groups ( metadata , scope ) { |g | g . before ( scope , *meta , &block ) }
1752
+ add_hook_to_existing_matching_groups ( meta , scope ) { |g | g . before ( scope , *meta , &block ) }
1754
1753
super ( scope , *meta , &block )
1755
1754
end
1756
1755
end
@@ -1773,8 +1772,7 @@ def prepend_before(scope=nil, *meta, &block)
1773
1772
handle_suite_hook ( scope , meta ) do
1774
1773
@before_suite_hooks . unshift Hooks ::BeforeHook . new ( block , { } )
1775
1774
end || begin
1776
- metadata = Metadata . build_hash_from ( meta . dup )
1777
- on_existing_matching_groups ( metadata , scope ) { |g | g . prepend_before ( scope , *meta , &block ) }
1775
+ add_hook_to_existing_matching_groups ( meta , scope ) { |g | g . prepend_before ( scope , *meta , &block ) }
1778
1776
super ( scope , *meta , &block )
1779
1777
end
1780
1778
end
@@ -1792,8 +1790,7 @@ def after(scope=nil, *meta, &block)
1792
1790
handle_suite_hook ( scope , meta ) do
1793
1791
@after_suite_hooks . unshift Hooks ::AfterHook . new ( block , { } )
1794
1792
end || begin
1795
- metadata = Metadata . build_hash_from ( meta . dup )
1796
- on_existing_matching_groups ( metadata , scope ) { |g | g . after ( scope , *meta , &block ) }
1793
+ add_hook_to_existing_matching_groups ( meta , scope ) { |g | g . after ( scope , *meta , &block ) }
1797
1794
super ( scope , *meta , &block )
1798
1795
end
1799
1796
end
@@ -1816,8 +1813,7 @@ def append_after(scope=nil, *meta, &block)
1816
1813
handle_suite_hook ( scope , meta ) do
1817
1814
@after_suite_hooks << Hooks ::AfterHook . new ( block , { } )
1818
1815
end || begin
1819
- metadata = Metadata . build_hash_from ( meta . dup )
1820
- on_existing_matching_groups ( metadata , scope ) { |g | g . append_after ( scope , *meta , &block ) }
1816
+ add_hook_to_existing_matching_groups ( meta , scope ) { |g | g . append_after ( scope , *meta , &block ) }
1821
1817
super ( scope , *meta , &block )
1822
1818
end
1823
1819
end
@@ -1826,8 +1822,7 @@ def append_after(scope=nil, *meta, &block)
1826
1822
#
1827
1823
# See {Hooks#around} for full `around` hook docs.
1828
1824
def around ( scope = nil , *meta , &block )
1829
- metadata = Metadata . build_hash_from ( meta . dup )
1830
- on_existing_matching_groups ( metadata , scope ) { |g | g . around ( scope , *meta , &block ) }
1825
+ add_hook_to_existing_matching_groups ( meta , scope ) { |g | g . around ( scope , *meta , &block ) }
1831
1826
super ( scope , *meta , &block )
1832
1827
end
1833
1828
@@ -2031,21 +2026,32 @@ def configure_group_with(group, module_list, application_method)
2031
2026
end
2032
2027
end
2033
2028
2034
- def on_existing_matching_groups ( meta , scope = :ignore )
2035
- groups = world . example_groups . dup
2036
-
2037
- until groups . empty?
2038
- group = groups . shift
2029
+ def add_hook_to_existing_matching_groups ( meta , scope , &block )
2030
+ # For example hooks, we have to apply it to each of the top level
2031
+ # groups, even if the groups do not match. When we apply it, we
2032
+ # apply it with the metadata, so it will only apply to examples
2033
+ # in the group that match the metadata.
2034
+ # #2280 for background and discussion.
2035
+ if scope == :example || scope == :each || scope . nil?
2036
+ world . example_groups . each ( &block )
2037
+ else
2038
+ meta = Metadata . build_hash_from ( meta . dup )
2039
+ on_existing_matching_groups ( meta , &block )
2040
+ end
2041
+ end
2039
2042
2040
- if scope == :example || scope == :each || scope . nil? ||
2041
- meta . empty? || MetadataFilter . apply? ( :any? , meta , group . metadata )
2042
- yield group
2043
- else
2044
- groups . concat ( group . children )
2043
+ def on_existing_matching_groups ( meta )
2044
+ world . traverse_example_group_trees_until do |group |
2045
+ metadata_applies_to_group? ( meta , group ) . tap do |applies |
2046
+ yield group if applies
2045
2047
end
2046
2048
end
2047
2049
end
2048
2050
2051
+ def metadata_applies_to_group? ( meta , group )
2052
+ meta . empty? || MetadataFilter . apply? ( :any? , meta , group . metadata )
2053
+ end
2054
+
2049
2055
if RSpec ::Support ::RubyFeatures . module_prepends_supported?
2050
2056
def safe_prepend ( mod , host )
2051
2057
host . __send__ ( :prepend , mod ) unless host < mod
0 commit comments