Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
24074796
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,发现更多精彩内容 >>
提交
24074796
编写于
9月 21, 2009
作者:
J
José Valim
提交者:
Yehuda Katz
9月 21, 2009
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixes Sam Ruby tests suite.
Signed-off-by:
N
Yehuda Katz
<
wycats@gmail.com
>
上级
1bbb9b2d
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
113 addition
and
56 deletion
+113
-56
actionpack/lib/action_dispatch/middleware/callbacks.rb
actionpack/lib/action_dispatch/middleware/callbacks.rb
+1
-6
actionpack/test/controller/caching_test.rb
actionpack/test/controller/caching_test.rb
+2
-3
activesupport/lib/active_support/new_callbacks.rb
activesupport/lib/active_support/new_callbacks.rb
+109
-46
activesupport/test/new_callback_inheritance_test.rb
activesupport/test/new_callback_inheritance_test.rb
+1
-1
未找到文件。
actionpack/lib/action_dispatch/middleware/callbacks.rb
浏览文件 @
24074796
...
...
@@ -2,7 +2,7 @@ module ActionDispatch
class
Callbacks
include
ActiveSupport
::
NewCallbacks
define_callbacks
:call
,
:terminator
=>
"result == false"
,
:
scope
=>
:kind
define_callbacks
:call
,
:terminator
=>
"result == false"
,
:
rescuable
=>
true
define_callbacks
:prepare
,
:scope
=>
:name
# Add a preparation callback. Preparation callbacks are run before every
...
...
@@ -25,10 +25,6 @@ def self.before(*args, &block)
set_callback
(
:call
,
:before
,
*
args
,
&
block
)
end
def
self
.
around
(
*
args
,
&
block
)
set_callback
(
:call
,
:around
,
*
args
,
&
block
)
end
def
self
.
after
(
*
args
,
&
block
)
set_callback
(
:call
,
:after
,
*
args
,
&
block
)
end
...
...
@@ -36,7 +32,6 @@ def self.after(*args, &block)
class
<<
self
# DEPRECATED
alias_method
:before_dispatch
,
:before
alias_method
:around_dispatch
,
:around
alias_method
:after_dispatch
,
:after
end
...
...
actionpack/test/controller/caching_test.rb
浏览文件 @
24074796
...
...
@@ -631,9 +631,8 @@ def test_fragment_for_logging
buffer
=
'generated till now -> '
@controller
.
fragment_for
(
buffer
,
'expensive'
)
{
fragment_computed
=
true
}
assert_equal
2
,
listener
.
size
assert_equal
:fragment_exist?
,
listener
[
0
].
name
assert_equal
:write_fragment
,
listener
[
1
].
name
assert_equal
1
,
listener
.
count
{
|
e
|
e
.
name
==
:fragment_exist?
}
assert_equal
1
,
listener
.
count
{
|
e
|
e
.
name
==
:write_fragment
}
assert
fragment_computed
assert_equal
'generated till now -> '
,
buffer
...
...
activesupport/lib/active_support/new_callbacks.rb
浏览文件 @
24074796
...
...
@@ -92,10 +92,10 @@ def run_callbacks(kind, options = {}, &blk)
class
Callback
@@_callback_sequence
=
0
attr_accessor
:
name
,
:filter
,
:kind
,
:options
,
:per_key
,
:klass
attr_accessor
:
chain
,
:filter
,
:kind
,
:options
,
:per_key
,
:klass
def
initialize
(
name
,
filter
,
kind
,
options
,
klass
)
@
name
,
@kind
,
@klass
=
name
,
kind
,
klass
def
initialize
(
chain
,
filter
,
kind
,
options
,
klass
)
@
chain
,
@kind
,
@klass
=
chain
,
kind
,
klass
normalize_options!
(
options
)
@per_key
=
options
.
delete
(
:per_key
)
...
...
@@ -107,9 +107,9 @@ def initialize(name, filter, kind, options, klass)
_compile_per_key_options
end
def
clone
(
klass
)
def
clone
(
chain
,
klass
)
obj
=
super
()
obj
.
name
=
name
obj
.
chain
=
chain
obj
.
klass
=
klass
obj
.
per_key
=
@per_key
.
dup
obj
.
options
=
@options
.
dup
...
...
@@ -117,7 +117,6 @@ def clone(klass)
obj
.
per_key
[
:unless
]
=
@per_key
[
:unless
].
dup
obj
.
options
[
:if
]
=
@options
[
:if
].
dup
obj
.
options
[
:unless
]
=
@options
[
:unless
].
dup
obj
.
options
[
:scope
]
=
@options
[
:scope
].
dup
obj
end
...
...
@@ -125,14 +124,15 @@ def normalize_options!(options)
options
[
:if
]
=
Array
.
wrap
(
options
[
:if
])
options
[
:unless
]
=
Array
.
wrap
(
options
[
:unless
])
options
[
:scope
]
||=
[
:kind
]
options
[
:scope
]
=
Array
.
wrap
(
options
[
:scope
])
options
[
:per_key
]
||=
{}
options
[
:per_key
][
:if
]
=
Array
.
wrap
(
options
[
:per_key
][
:if
])
options
[
:per_key
][
:unless
]
=
Array
.
wrap
(
options
[
:per_key
][
:unless
])
end
def
name
chain
.
name
end
def
next_id
@@_callback_sequence
+=
1
end
...
...
@@ -168,15 +168,12 @@ def _one_time_conditions_valid_#{@callback_id}?
# This will supply contents for before and around filters, and no
# contents for after filters (for the forward pass).
def
start
(
key
=
nil
,
options
=
{})
object
,
terminator
=
(
options
||
{}).
values_at
(
:object
,
:terminator
)
def
start
(
key
=
nil
,
object
=
nil
)
return
if
key
&&
!
object
.
send
(
"_one_time_conditions_valid_
#{
@callback_id
}
?"
)
terminator
||=
false
# options[0] is the compiled form of supplied conditions
# options[1] is the "end" for the conditional
#
if
@kind
==
:before
||
@kind
==
:around
if
@kind
==
:before
# if condition # before_save :filter_name, :if => :condition
...
...
@@ -185,7 +182,7 @@ def start(key = nil, options = {})
filter
=
<<-
RUBY_EVAL
unless halted
result =
#{
@filter
}
halted = (
#{
terminator
}
)
halted = (
#{
chain
.
config
[
:terminator
]
}
)
end
RUBY_EVAL
...
...
@@ -226,8 +223,7 @@ def #{name}(halted)
# This will supply contents for around and after filters, but not
# before filters (for the backward pass).
def
end
(
key
=
nil
,
options
=
{})
object
=
(
options
||
{})[
:object
]
def
end
(
key
=
nil
,
object
=
nil
)
return
if
key
&&
!
object
.
send
(
"_one_time_conditions_valid_
#{
@callback_id
}
?"
)
if
@kind
==
:around
||
@kind
==
:after
...
...
@@ -302,7 +298,8 @@ def _compile_filter(filter)
@klass
.
send
(
:define_method
,
"
#{
method_name
}
_object"
)
{
filter
}
_normalize_legacy_filter
(
kind
,
filter
)
method_to_call
=
@options
[
:scope
].
map
{
|
s
|
s
.
is_a?
(
Symbol
)
?
send
(
s
)
:
s
}.
join
(
"_"
)
scopes
=
Array
.
wrap
(
chain
.
config
[
:scope
])
method_to_call
=
scopes
.
map
{
|
s
|
s
.
is_a?
(
Symbol
)
?
send
(
s
)
:
s
}.
join
(
"_"
)
@klass
.
class_eval
<<-
RUBY_EVAL
,
__FILE__
,
__LINE__
+
1
def
#{
method_name
}
(&blk)
...
...
@@ -331,37 +328,52 @@ def filter.around(context)
# An Array with a compile method
class
CallbackChain
<
Array
attr_reader
:symbol
,
:config
def
initialize
(
symbol
,
config
)
@symbol
=
symbol
@config
=
config
attr_reader
:name
,
:config
def
initialize
(
name
,
config
)
@name
=
name
@config
=
{
:terminator
=>
"false"
,
:rescuable
=>
false
,
:scope
=>
[
:kind
]
}.
merge
(
config
)
end
def
compile
(
key
=
nil
,
options
=
{})
options
=
config
.
merge
(
options
)
def
compile
(
key
=
nil
,
object
=
nil
)
method
=
[]
method
<<
"value = nil"
method
<<
"halted = false"
each
do
|
callback
|
method
<<
callback
.
start
(
key
,
options
)
method
<<
callback
.
start
(
key
,
object
)
end
if
config
[
:rescuable
]
method
<<
"rescued_error = nil"
method
<<
"begin"
end
method
<<
"value = yield if block_given? && !halted"
if
config
[
:rescuable
]
method
<<
"rescue Exception => e"
method
<<
"rescued_error = e"
method
<<
"end"
end
reverse_each
do
|
callback
|
method
<<
callback
.
end
(
key
,
o
ptions
)
method
<<
callback
.
end
(
key
,
o
bject
)
end
method
<<
"raise rescued_error if rescued_error"
if
config
[
:rescuable
]
method
<<
"halted ? false : (block_given? ? value : true)"
method
.
compact
.
join
(
"
\n
"
)
end
def
clone
(
klass
)
chain
=
CallbackChain
.
new
(
@symbol
,
@config
.
dup
)
chain
.
push
(
*
map
{
|
c
|
c
.
clone
(
klass
)})
chain
=
CallbackChain
.
new
(
@name
,
@config
.
dup
)
callbacks
=
map
{
|
c
|
c
.
clone
(
chain
,
klass
)
}
chain
.
push
(
*
callbacks
)
end
end
...
...
@@ -407,32 +419,35 @@ def _run_#{symbol}_callbacks(key = nil, &blk)
# key. It creates a new callback method for the key, calculating
# which callbacks can be omitted because of per_key conditions.
#
def
__create_keyed_callback
(
name
,
kind
,
obj
,
&
blk
)
#:nodoc:
def
__create_keyed_callback
(
name
,
kind
,
obj
ect
,
&
blk
)
#:nodoc:
@_keyed_callbacks
||=
{}
@_keyed_callbacks
[
name
]
||=
begin
str
=
send
(
"_
#{
kind
}
_callbacks"
).
compile
(
name
,
:object
=>
obj
)
str
=
send
(
"_
#{
kind
}
_callbacks"
).
compile
(
name
,
object
)
class_eval
"def
#{
name
}
()
#{
str
}
end"
,
__FILE__
,
__LINE__
true
end
end
def
__update_callbacks
(
name
,
filters
=
CallbackChain
.
new
(
name
,
{}),
block
=
nil
)
# This is used internally to append, prepend and skip callbacks to the
# CallbackChain.
#
def
__update_callbacks
(
name
,
filters
=
[],
block
=
nil
)
#:nodoc:
type
=
[
:before
,
:after
,
:around
].
include?
(
filters
.
first
)
?
filters
.
shift
:
:before
options
=
filters
.
last
.
is_a?
(
Hash
)
?
filters
.
pop
:
{}
filters
.
unshift
(
block
)
if
block
c
allbacks
=
send
(
"_
#{
name
}
_callbacks"
)
yield
c
allbacks
,
type
,
filters
,
options
if
block_given?
c
hain
=
send
(
"_
#{
name
}
_callbacks"
)
yield
c
hain
,
type
,
filters
,
options
if
block_given?
__define_runner
(
name
)
end
#
Define callbacks
.
#
Set callbacks for a previously defined callback
.
#
# Syntax:
# set_callback :save, :before, :before_meth
# set_callback :save, :after, :after_meth, :if => :condition
# set_callback :save, :around
{
|r| stuff; yield; stuff }
# set_callback :save, :around
, lambda {
|r| stuff; yield; stuff }
#
# It also updates the _run_<name>_callbacks method, which is the public
# API to run the callbacks. Use skip_callback to skip any defined one.
...
...
@@ -448,43 +463,91 @@ def __update_callbacks(name, filters = CallbackChain.new(name, {}), block = nil)
# Per-Key conditions are evaluated only once per use of a given key.
# In the case of the above example, you would do:
#
# run_dispatch_callbacks(action_name) { ... dispatch stuff ... }
#
_
run_dispatch_callbacks(action_name) { ... dispatch stuff ... }
#
# In that case, each action_name would get its own compiled callback
# method that took into consideration the per_key conditions. This
# is a speed improvement for ActionPack.
#
def
set_callback
(
name
,
*
filters
,
&
block
)
__update_callbacks
(
name
,
filters
,
block
)
do
|
c
allbacks
,
type
,
filters
,
options
|
__update_callbacks
(
name
,
filters
,
block
)
do
|
c
hain
,
type
,
filters
,
options
|
filters
.
map!
do
|
filter
|
c
allbacks
.
delete_if
{
|
c
|
c
.
matches?
(
type
,
filter
)
}
Callback
.
new
(
name
,
filter
,
type
,
options
.
merge
(
callbacks
.
config
)
,
self
)
c
hain
.
delete_if
{
|
c
|
c
.
matches?
(
type
,
filter
)
}
Callback
.
new
(
chain
,
filter
,
type
,
options
.
dup
,
self
)
end
options
[
:prepend
]
?
c
allbacks
.
unshift
(
*
filters
)
:
callbacks
.
push
(
*
filters
)
options
[
:prepend
]
?
c
hain
.
unshift
(
*
filters
)
:
chain
.
push
(
*
filters
)
end
end
# Skip a previously defined callback for a given type.
#
def
skip_callback
(
name
,
*
filters
,
&
block
)
__update_callbacks
(
name
,
filters
,
block
)
do
|
callbacks
,
type
,
filters
,
options
|
__update_callbacks
(
name
,
filters
,
block
)
do
|
chain
,
type
,
filters
,
options
|
chain
=
send
(
"_
#{
name
}
_callbacks="
,
chain
.
clone
(
self
))
filters
.
each
do
|
filter
|
callbacks
=
send
(
"_
#{
name
}
_callbacks="
,
callbacks
.
clone
(
self
))
filter
=
callbacks
.
find
{
|
c
|
c
.
matches?
(
type
,
filter
)
}
filter
=
chain
.
find
{
|
c
|
c
.
matches?
(
type
,
filter
)
}
if
filter
&&
options
.
any?
filter
.
recompile!
(
options
,
options
[
:per_key
]
||
{})
else
c
allbacks
.
delete
(
filter
)
c
hain
.
delete
(
filter
)
end
end
end
end
# Reset callbacks for a given type.
#
def
reset_callbacks
(
symbol
)
send
(
"_
#{
symbol
}
_callbacks"
).
clear
__define_runner
(
symbol
)
end
# Define callbacks types.
#
# ==== Example
#
# define_callbacks :validate
#
# ==== Options
#
# * <tt>:terminator</tt> - Indicates when a before filter is considered
# to be halted.
#
# define_callbacks :validate, :terminator => "result == false"
#
# In the example above, if any before validate callbacks returns false,
# other callbacks are not executed. Defaults to "false".
#
# * <tt>:rescuable</tt> - By default, after filters are not executed if
# the given block or an before_filter raises an error. Supply :rescuable => true
# to change this behavior.
#
# * <tt>:scope</tt> - Show which methods should be executed when a class
# is giben as callback:
#
# define_callbacks :filters, :scope => [ :kind ]
#
# When a class is given:
#
# before_filter MyFilter
#
# It will call the type of the filter in the given class, which in this
# case, is "before".
#
# If, for instance, you supply the given scope:
#
# define_callbacks :validate, :scope => [ :kind, :name ]
#
# It will call "#{kind}_#{name}" in the given class. So "before_validate"
# will be called in the class below:
#
# before_validate MyValidation
#
# Defaults to :kind.
#
def
define_callbacks
(
*
symbols
)
config
=
symbols
.
last
.
is_a?
(
Hash
)
?
symbols
.
pop
:
{}
symbols
.
each
do
|
symbol
|
...
...
activesupport/test/new_callback_inheritance_test.rb
浏览文件 @
24074796
...
...
@@ -112,4 +112,4 @@ def test_crazy_mix_on
def
test_crazy_mix_off
assert_equal
%w(before1 before2 update after2 after1)
,
@update2
.
log
end
end
\ No newline at end of file
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录