Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
3b7754c9
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
3b7754c9
编写于
10月 29, 2013
作者:
J
John Barnette
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #25 from github/activesupport-concern
Pull in ActiveSupport::Concern
上级
76884dd7
75638c57
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
232 addition
and
0 deletion
+232
-0
activesupport/lib/active_support/concern.rb
activesupport/lib/active_support/concern.rb
+134
-0
activesupport/test/concern_test.rb
activesupport/test/concern_test.rb
+98
-0
未找到文件。
activesupport/lib/active_support/concern.rb
0 → 100644
浏览文件 @
3b7754c9
module
ActiveSupport
# A typical module looks like this:
#
# module M
# def self.included(base)
# base.extend ClassMethods
# base.class_eval do
# scope :disabled, -> { where(disabled: true) }
# end
# end
#
# module ClassMethods
# ...
# end
# end
#
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
# written as:
#
# require 'active_support/concern'
#
# module M
# extend ActiveSupport::Concern
#
# included do
# scope :disabled, -> { where(disabled: true) }
# end
#
# module ClassMethods
# ...
# end
# end
#
# Moreover, it gracefully handles module dependencies. Given a +Foo+ module
# and a +Bar+ module which depends on the former, we would typically write the
# following:
#
# module Foo
# def self.included(base)
# base.class_eval do
# def self.method_injected_by_foo
# ...
# end
# end
# end
# end
#
# module Bar
# def self.included(base)
# base.method_injected_by_foo
# end
# end
#
# class Host
# include Foo # We need to include this dependency for Bar
# include Bar # Bar is the module that Host really needs
# end
#
# But why should +Host+ care about +Bar+'s dependencies, namely +Foo+? We
# could try to hide these from +Host+ directly including +Foo+ in +Bar+:
#
# module Bar
# include Foo
# def self.included(base)
# base.method_injected_by_foo
# end
# end
#
# class Host
# include Bar
# end
#
# Unfortunately this won't work, since when +Foo+ is included, its <tt>base</tt>
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
# module dependencies are properly resolved:
#
# require 'active_support/concern'
#
# module Foo
# extend ActiveSupport::Concern
# included do
# def self.method_injected_by_foo
# ...
# end
# end
# end
#
# module Bar
# extend ActiveSupport::Concern
# include Foo
#
# included do
# self.method_injected_by_foo
# end
# end
#
# class Host
# include Bar # works, Bar takes care now of its dependencies
# end
module
Concern
class
MultipleIncludedBlocks
<
StandardError
#:nodoc:
def
initialize
super
"Cannot define multiple 'included' blocks for a Concern"
end
end
def
self
.
extended
(
base
)
#:nodoc:
base
.
instance_variable_set
(
:@_dependencies
,
[])
end
def
append_features
(
base
)
if
base
.
instance_variable_defined?
(
:@_dependencies
)
base
.
instance_variable_get
(
:@_dependencies
)
<<
self
return
false
else
return
false
if
base
<
self
@_dependencies
.
each
{
|
dep
|
base
.
send
(
:include
,
dep
)
}
super
base
.
extend
const_get
(
:ClassMethods
)
if
const_defined?
(
:ClassMethods
)
base
.
class_eval
(
&
@_included_block
)
if
instance_variable_defined?
(
:@_included_block
)
end
end
def
included
(
base
=
nil
,
&
block
)
if
base
.
nil?
raise
MultipleIncludedBlocks
if
instance_variable_defined?
(
:@_included_block
)
@_included_block
=
block
else
super
end
end
end
end
\ No newline at end of file
activesupport/test/concern_test.rb
0 → 100644
浏览文件 @
3b7754c9
require
'abstract_unit'
require
'active_support/concern'
class
ConcernTest
<
ActiveSupport
::
TestCase
module
Baz
extend
ActiveSupport
::
Concern
module
ClassMethods
def
baz
"baz"
end
def
included_ran
=
(
value
)
@@included_ran
=
value
end
def
included_ran
@@included_ran
end
end
included
do
self
.
included_ran
=
true
end
def
baz
"baz"
end
end
module
Bar
extend
ActiveSupport
::
Concern
include
Baz
def
bar
"bar"
end
def
baz
"bar+"
+
super
end
end
module
Foo
extend
ActiveSupport
::
Concern
include
Bar
,
Baz
end
def
setup
@klass
=
Class
.
new
end
def
test_module_is_included_normally
@klass
.
send
(
:include
,
Baz
)
assert_equal
"baz"
,
@klass
.
new
.
baz
assert
@klass
.
included_modules
.
include?
(
ConcernTest
::
Baz
)
end
def
test_class_methods_are_extended
@klass
.
send
(
:include
,
Baz
)
assert_equal
"baz"
,
@klass
.
baz
assert_equal
ConcernTest
::
Baz
::
ClassMethods
,
(
class
<<
@klass
;
self
.
included_modules
;
end
)[
0
]
end
def
test_included_block_is_ran
@klass
.
send
(
:include
,
Baz
)
assert_equal
true
,
@klass
.
included_ran
end
def
test_modules_dependencies_are_met
@klass
.
send
(
:include
,
Bar
)
assert_equal
"bar"
,
@klass
.
new
.
bar
assert_equal
"bar+baz"
,
@klass
.
new
.
baz
assert_equal
"baz"
,
@klass
.
baz
assert
@klass
.
included_modules
.
include?
(
ConcernTest
::
Bar
)
end
def
test_dependencies_with_multiple_modules
@klass
.
send
(
:include
,
Foo
)
assert_equal
[
ConcernTest
::
Foo
,
ConcernTest
::
Bar
,
ConcernTest
::
Baz
],
@klass
.
included_modules
[
0
..
2
]
end
def
test_raise_on_multiple_included_calls
assert_raises
(
ActiveSupport
::
Concern
::
MultipleIncludedBlocks
)
do
Module
.
new
do
extend
ActiveSupport
::
Concern
included
do
end
included
do
end
end
end
end
end
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录