Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
1e8b7518
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,发现更多精彩内容 >>
提交
1e8b7518
编写于
12月 15, 2011
作者:
J
José Valim
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make with_scope public so we stop using send
💣
上级
22bd21dc
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
104 addition
and
91 deletion
+104
-91
activerecord/examples/performance.rb
activerecord/examples/performance.rb
+12
-0
activerecord/lib/active_record/base.rb
activerecord/lib/active_record/base.rb
+91
-90
activerecord/lib/active_record/relation.rb
activerecord/lib/active_record/relation.rb
+1
-1
未找到文件。
activerecord/examples/performance.rb
浏览文件 @
1e8b7518
...
...
@@ -29,6 +29,14 @@ class Exhibit < ActiveRecord::Base
def
look
;
attributes
end
def
feel
;
look
;
user
.
name
end
def
self
.
with_name
where
(
"name IS NOT NULL"
)
end
def
self
.
with_notes
where
(
"notes IS NOT NULL"
)
end
def
self
.
look
(
exhibits
)
exhibits
.
each
{
|
e
|
e
.
look
}
end
def
self
.
feel
(
exhibits
)
exhibits
.
each
{
|
e
|
e
.
feel
}
end
end
...
...
@@ -109,6 +117,10 @@ def self.email
TIMES
.
times
{
Exhibit
.
first
.
look
}
end
x
.
report
'Model.named_scope'
do
TIMES
.
times
{
Exhibit
.
limit
(
10
).
with_name
.
with_notes
}
end
x
.
report
(
"Model.all limit(100) (x
#{
(
TIMES
/
10
).
ceil
}
)"
)
do
(
TIMES
/
10
).
ceil
.
times
{
Exhibit
.
look
Exhibit
.
limit
(
100
)
}
end
...
...
activerecord/lib/active_record/base.rb
浏览文件 @
1e8b7518
...
...
@@ -1032,6 +1032,97 @@ def instantiate(record)
instance
end
# with_scope lets you apply options to inner block incrementally. It takes a hash and the keys must be
# <tt>:find</tt> or <tt>:create</tt>. <tt>:find</tt> parameter is <tt>Relation</tt> while
# <tt>:create</tt> parameters are an attributes hash.
#
# class Article < ActiveRecord::Base
# def self.create_with_scope
# with_scope(:find => where(:blog_id => 1), :create => { :blog_id => 1 }) do
# find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1
# a = create(1)
# a.blog_id # => 1
# end
# end
# end
#
# In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of
# <tt>where</tt>, <tt>includes</tt>, and <tt>joins</tt> operations in <tt>Relation</tt>, which are merged.
#
# <tt>joins</tt> operations are uniqued so multiple scopes can join in the same table without table aliasing
# problems. If you need to join multiple tables, but still want one of the tables to be uniqued, use the
# array of strings format for your joins.
#
# class Article < ActiveRecord::Base
# def self.find_with_scope
# with_scope(:find => where(:blog_id => 1).limit(1), :create => { :blog_id => 1 }) do
# with_scope(:find => limit(10)) do
# all # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
# end
# with_scope(:find => where(:author_id => 3)) do
# all # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1
# end
# end
# end
# end
#
# You can ignore any previous scopings by using the <tt>with_exclusive_scope</tt> method.
#
# class Article < ActiveRecord::Base
# def self.find_with_exclusive_scope
# with_scope(:find => where(:blog_id => 1).limit(1)) do
# with_exclusive_scope(:find => limit(10)) do
# all # => SELECT * from articles LIMIT 10
# end
# end
# end
# end
#
# *Note*: the +:find+ scope also has effect on update and deletion methods, like +update_all+ and +delete_all+.
def
with_scope
(
scope
=
{},
action
=
:merge
,
&
block
)
# If another Active Record class has been passed in, get its current scope
scope
=
scope
.
current_scope
if
!
scope
.
is_a?
(
Relation
)
&&
scope
.
respond_to?
(
:current_scope
)
previous_scope
=
self
.
current_scope
if
scope
.
is_a?
(
Hash
)
# Dup first and second level of hash (method and params).
scope
=
scope
.
dup
scope
.
each
do
|
method
,
params
|
scope
[
method
]
=
params
.
dup
unless
params
==
true
end
scope
.
assert_valid_keys
([
:find
,
:create
])
relation
=
construct_finder_arel
(
scope
[
:find
]
||
{})
relation
.
default_scoped
=
true
unless
action
==
:overwrite
if
previous_scope
&&
previous_scope
.
create_with_value
&&
scope
[
:create
]
scope_for_create
=
if
action
==
:merge
previous_scope
.
create_with_value
.
merge
(
scope
[
:create
])
else
scope
[
:create
]
end
relation
=
relation
.
create_with
(
scope_for_create
)
else
scope_for_create
=
scope
[
:create
]
scope_for_create
||=
previous_scope
.
create_with_value
if
previous_scope
relation
=
relation
.
create_with
(
scope_for_create
)
if
scope_for_create
end
scope
=
relation
end
scope
=
previous_scope
.
merge
(
scope
)
if
previous_scope
&&
action
==
:merge
self
.
current_scope
=
scope
begin
yield
ensure
self
.
current_scope
=
previous_scope
end
end
private
def
relation
#:nodoc:
...
...
@@ -1159,96 +1250,6 @@ def all_attributes_exists?(attribute_names)
end
protected
# with_scope lets you apply options to inner block incrementally. It takes a hash and the keys must be
# <tt>:find</tt> or <tt>:create</tt>. <tt>:find</tt> parameter is <tt>Relation</tt> while
# <tt>:create</tt> parameters are an attributes hash.
#
# class Article < ActiveRecord::Base
# def self.create_with_scope
# with_scope(:find => where(:blog_id => 1), :create => { :blog_id => 1 }) do
# find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1
# a = create(1)
# a.blog_id # => 1
# end
# end
# end
#
# In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of
# <tt>where</tt>, <tt>includes</tt>, and <tt>joins</tt> operations in <tt>Relation</tt>, which are merged.
#
# <tt>joins</tt> operations are uniqued so multiple scopes can join in the same table without table aliasing
# problems. If you need to join multiple tables, but still want one of the tables to be uniqued, use the
# array of strings format for your joins.
#
# class Article < ActiveRecord::Base
# def self.find_with_scope
# with_scope(:find => where(:blog_id => 1).limit(1), :create => { :blog_id => 1 }) do
# with_scope(:find => limit(10)) do
# all # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
# end
# with_scope(:find => where(:author_id => 3)) do
# all # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1
# end
# end
# end
# end
#
# You can ignore any previous scopings by using the <tt>with_exclusive_scope</tt> method.
#
# class Article < ActiveRecord::Base
# def self.find_with_exclusive_scope
# with_scope(:find => where(:blog_id => 1).limit(1)) do
# with_exclusive_scope(:find => limit(10)) do
# all # => SELECT * from articles LIMIT 10
# end
# end
# end
# end
#
# *Note*: the +:find+ scope also has effect on update and deletion methods, like +update_all+ and +delete_all+.
def
with_scope
(
scope
=
{},
action
=
:merge
,
&
block
)
# If another Active Record class has been passed in, get its current scope
scope
=
scope
.
current_scope
if
!
scope
.
is_a?
(
Relation
)
&&
scope
.
respond_to?
(
:current_scope
)
previous_scope
=
self
.
current_scope
if
scope
.
is_a?
(
Hash
)
# Dup first and second level of hash (method and params).
scope
=
scope
.
dup
scope
.
each
do
|
method
,
params
|
scope
[
method
]
=
params
.
dup
unless
params
==
true
end
scope
.
assert_valid_keys
([
:find
,
:create
])
relation
=
construct_finder_arel
(
scope
[
:find
]
||
{})
relation
.
default_scoped
=
true
unless
action
==
:overwrite
if
previous_scope
&&
previous_scope
.
create_with_value
&&
scope
[
:create
]
scope_for_create
=
if
action
==
:merge
previous_scope
.
create_with_value
.
merge
(
scope
[
:create
])
else
scope
[
:create
]
end
relation
=
relation
.
create_with
(
scope_for_create
)
else
scope_for_create
=
scope
[
:create
]
scope_for_create
||=
previous_scope
.
create_with_value
if
previous_scope
relation
=
relation
.
create_with
(
scope_for_create
)
if
scope_for_create
end
scope
=
relation
end
scope
=
previous_scope
.
merge
(
scope
)
if
previous_scope
&&
action
==
:merge
self
.
current_scope
=
scope
begin
yield
ensure
self
.
current_scope
=
previous_scope
end
end
# Works like with_scope, but discards any nested properties.
def
with_exclusive_scope
(
method_scoping
=
{},
&
block
)
...
...
activerecord/lib/active_record/relation.rb
浏览文件 @
1e8b7518
...
...
@@ -251,7 +251,7 @@ def many?
# Please check unscoped if you want to remove all previous scopes (including
# the default_scope) during the execution of a block.
def
scoping
@klass
.
send
(
:with_scope
,
self
,
:overwrite
)
{
yield
}
@klass
.
with_scope
(
self
,
:overwrite
)
{
yield
}
end
# Updates all records with details given if they match a set of conditions supplied, limits and order can
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录