Skip to content

Commit

Permalink
More tests for concerning
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkarns authored and kaspth committed Feb 10, 2020
1 parent ba2bea5 commit 54ecc90
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
20 changes: 20 additions & 0 deletions activesupport/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
* Support `prepend` with `ActiveSupport::Concern`.

Allows a module with `extend ActiveSupport::Concern` to be prepended.

module Imposter
extend ActiveSupport::Concern

# Same as `included`, except only run when prepended.
prepended do
end
end

class Person
prepend Imposter
end

Concerning is also updated: `concerning :Imposter, prepend: true do`

*Jason Karns*

* Deprecate using `Range#include?` method to check the inclusion of a value
in a date time range. It is recommended to use `Range#cover?` method
instead of `Range#include?` to check the inclusion of a value
Expand Down
8 changes: 8 additions & 0 deletions activesupport/lib/active_support/concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ module ActiveSupport
# class Host
# include Bar # It works, now Bar takes care of its dependencies
# end
#
# === Prepending concerns
#
# Just like `include`, concerns also support `prepend` with a corresponding
# `prepended do` callback. `module ClassMethods` or `class_methods do` are
# still extended.
#
# `prepend` is also used for any dependencies.
module Concern
class MultipleIncludedBlocks < StandardError #:nodoc:
def initialize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ class Module
# * grok the behavior of our class in one glance,
# * clean up monolithic junk-drawer classes by separating their concerns, and
# * stop leaning on protected/private for crude "this is internal stuff" modularity.
#
# === Prepending `concerning`
#
# `concerning` supports a `prepend: true` argument which will `prepend` the
# concern instead of using `include` for it.
module Concerning
# Define a new concern and mix it in.
def concerning(topic, prepend: false, &block)
Expand Down
38 changes: 38 additions & 0 deletions activesupport/test/core_ext/module/concerning_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class ModuleConcerningTest < ActiveSupport::TestCase
def test_concerning_declares_a_concern_and_includes_it_immediately
klass = Class.new { concerning(:Foo) { } }
assert_includes klass.ancestors, klass::Foo, klass.ancestors.inspect

klass = Class.new { concerning(:Foo, prepend: true) { } }
assert_includes klass.ancestors, klass::Foo, klass.ancestors.inspect
end

def test_concerning_can_prepend_concern
Expand All @@ -27,6 +30,7 @@ def test_concern_creates_a_module_extended_with_active_support_concern
klass = Class.new do
concern :Baz do
included { @foo = 1 }
prepended { @foo = 2 }
def should_be_public; end
end
end
Expand All @@ -42,6 +46,9 @@ def should_be_public; end

# Calls included hook
assert_equal 1, Class.new { include klass::Baz }.instance_variable_get("@foo")

# Calls prepended hook
assert_equal 2, Class.new { prepend klass::Baz }.instance_variable_get("@foo")
end

class Foo
Expand All @@ -64,6 +71,26 @@ def nicer_dsl; end
def doesnt_clobber; end
end
end

concerning :Baz, prepend:true do
module ClassMethods
def will_be_orphaned_also; end
end

const_set :ClassMethods, Module.new {
def hacked_on_also; end
}

# Doesn't overwrite existing ClassMethods module.
class_methods do
def nicer_dsl_also; end
end

# Doesn't overwrite previous class_methods definitions.
class_methods do
def doesnt_clobber_also; end
end
end
end

def test_using_class_methods_blocks_instead_of_ClassMethods_module
Expand All @@ -76,4 +103,15 @@ def test_using_class_methods_blocks_instead_of_ClassMethods_module
assert Foo.const_defined?(:ClassMethods)
assert Foo::ClassMethods.method_defined?(:will_be_orphaned)
end

def test_using_class_methods_blocks_instead_of_ClassMethods_module_prepend
assert_not_respond_to Foo, :will_be_orphaned_also
assert_respond_to Foo, :hacked_on_also
assert_respond_to Foo, :nicer_dsl_also
assert_respond_to Foo, :doesnt_clobber_also

# Orphan in Foo::ClassMethods, not Bar::ClassMethods.
assert Foo.const_defined?(:ClassMethods)
assert Foo::ClassMethods.method_defined?(:will_be_orphaned_also)
end
end

0 comments on commit 54ecc90

Please sign in to comment.