Skip to content

Commit 54ecc90

Browse files
jasonkarnskaspth
authored andcommitted
More tests for concerning
1 parent ba2bea5 commit 54ecc90

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed

activesupport/CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
* Support `prepend` with `ActiveSupport::Concern`.
2+
3+
Allows a module with `extend ActiveSupport::Concern` to be prepended.
4+
5+
module Imposter
6+
extend ActiveSupport::Concern
7+
8+
# Same as `included`, except only run when prepended.
9+
prepended do
10+
end
11+
end
12+
13+
class Person
14+
prepend Imposter
15+
end
16+
17+
Concerning is also updated: `concerning :Imposter, prepend: true do`
18+
19+
*Jason Karns*
20+
121
* Deprecate using `Range#include?` method to check the inclusion of a value
222
in a date time range. It is recommended to use `Range#cover?` method
323
instead of `Range#include?` to check the inclusion of a value

activesupport/lib/active_support/concern.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ module ActiveSupport
9999
# class Host
100100
# include Bar # It works, now Bar takes care of its dependencies
101101
# end
102+
#
103+
# === Prepending concerns
104+
#
105+
# Just like `include`, concerns also support `prepend` with a corresponding
106+
# `prepended do` callback. `module ClassMethods` or `class_methods do` are
107+
# still extended.
108+
#
109+
# `prepend` is also used for any dependencies.
102110
module Concern
103111
class MultipleIncludedBlocks < StandardError #:nodoc:
104112
def initialize

activesupport/lib/active_support/core_ext/module/concerning.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ class Module
104104
# * grok the behavior of our class in one glance,
105105
# * clean up monolithic junk-drawer classes by separating their concerns, and
106106
# * stop leaning on protected/private for crude "this is internal stuff" modularity.
107+
#
108+
# === Prepending `concerning`
109+
#
110+
# `concerning` supports a `prepend: true` argument which will `prepend` the
111+
# concern instead of using `include` for it.
107112
module Concerning
108113
# Define a new concern and mix it in.
109114
def concerning(topic, prepend: false, &block)

activesupport/test/core_ext/module/concerning_test.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class ModuleConcerningTest < ActiveSupport::TestCase
77
def test_concerning_declares_a_concern_and_includes_it_immediately
88
klass = Class.new { concerning(:Foo) { } }
99
assert_includes klass.ancestors, klass::Foo, klass.ancestors.inspect
10+
11+
klass = Class.new { concerning(:Foo, prepend: true) { } }
12+
assert_includes klass.ancestors, klass::Foo, klass.ancestors.inspect
1013
end
1114

1215
def test_concerning_can_prepend_concern
@@ -27,6 +30,7 @@ def test_concern_creates_a_module_extended_with_active_support_concern
2730
klass = Class.new do
2831
concern :Baz do
2932
included { @foo = 1 }
33+
prepended { @foo = 2 }
3034
def should_be_public; end
3135
end
3236
end
@@ -42,6 +46,9 @@ def should_be_public; end
4246

4347
# Calls included hook
4448
assert_equal 1, Class.new { include klass::Baz }.instance_variable_get("@foo")
49+
50+
# Calls prepended hook
51+
assert_equal 2, Class.new { prepend klass::Baz }.instance_variable_get("@foo")
4552
end
4653

4754
class Foo
@@ -64,6 +71,26 @@ def nicer_dsl; end
6471
def doesnt_clobber; end
6572
end
6673
end
74+
75+
concerning :Baz, prepend:true do
76+
module ClassMethods
77+
def will_be_orphaned_also; end
78+
end
79+
80+
const_set :ClassMethods, Module.new {
81+
def hacked_on_also; end
82+
}
83+
84+
# Doesn't overwrite existing ClassMethods module.
85+
class_methods do
86+
def nicer_dsl_also; end
87+
end
88+
89+
# Doesn't overwrite previous class_methods definitions.
90+
class_methods do
91+
def doesnt_clobber_also; end
92+
end
93+
end
6794
end
6895

6996
def test_using_class_methods_blocks_instead_of_ClassMethods_module
@@ -76,4 +103,15 @@ def test_using_class_methods_blocks_instead_of_ClassMethods_module
76103
assert Foo.const_defined?(:ClassMethods)
77104
assert Foo::ClassMethods.method_defined?(:will_be_orphaned)
78105
end
106+
107+
def test_using_class_methods_blocks_instead_of_ClassMethods_module_prepend
108+
assert_not_respond_to Foo, :will_be_orphaned_also
109+
assert_respond_to Foo, :hacked_on_also
110+
assert_respond_to Foo, :nicer_dsl_also
111+
assert_respond_to Foo, :doesnt_clobber_also
112+
113+
# Orphan in Foo::ClassMethods, not Bar::ClassMethods.
114+
assert Foo.const_defined?(:ClassMethods)
115+
assert Foo::ClassMethods.method_defined?(:will_be_orphaned_also)
116+
end
79117
end

0 commit comments

Comments
 (0)