Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
88de6b2d
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,发现更多精彩内容 >>
提交
88de6b2d
编写于
1月 18, 2010
作者:
P
Pratik Naik
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Inherit named scope class Scope from Relation
上级
c6850d83
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
55 addition
and
94 deletion
+55
-94
activerecord/lib/active_record/associations/association_collection.rb
.../lib/active_record/associations/association_collection.rb
+0
-2
activerecord/lib/active_record/named_scope.rb
activerecord/lib/active_record/named_scope.rb
+42
-76
activerecord/lib/active_record/relation.rb
activerecord/lib/active_record/relation.rb
+3
-1
activerecord/lib/active_record/relation/predicate_builder.rb
activerecord/lib/active_record/relation/predicate_builder.rb
+1
-1
activerecord/lib/active_record/relation/spawn_methods.rb
activerecord/lib/active_record/relation/spawn_methods.rb
+3
-3
activerecord/test/cases/named_scope_test.rb
activerecord/test/cases/named_scope_test.rb
+6
-11
未找到文件。
activerecord/lib/active_record/associations/association_collection.rb
浏览文件 @
88de6b2d
...
...
@@ -403,8 +403,6 @@ def method_missing(method, *args)
else
super
end
elsif
@reflection
.
klass
.
scopes
.
include?
(
method
)
@reflection
.
klass
.
scopes
[
method
].
call
(
self
,
*
args
)
else
with_scope
(
construct_scope
)
do
if
block_given?
...
...
activerecord/lib/active_record/named_scope.rb
浏览文件 @
88de6b2d
...
...
@@ -24,7 +24,7 @@ module ClassMethods
# You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
def
scoped
(
options
=
{},
&
block
)
if
options
.
present?
Scope
.
new
(
self
,
options
,
&
block
)
Scope
.
init
(
self
,
options
,
&
block
)
else
current_scoped_methods
?
unscoped
.
merge
(
current_scoped_methods
)
:
unscoped
.
spawn
end
...
...
@@ -105,7 +105,7 @@ def named_scope(name, options = {}, &block)
end
scopes
[
name
]
=
lambda
do
|
parent_scope
,
*
args
|
Scope
.
new
(
parent_scope
,
case
options
Scope
.
init
(
parent_scope
,
case
options
when
Hash
,
Relation
options
when
Proc
...
...
@@ -120,117 +120,83 @@ def named_scope(name, options = {}, &block)
end
end
class
Scope
attr_reader
:klass
,
:proxy_options
,
:current_scoped_methods_when_defined
NON_DELEGATE_METHODS
=
%w(nil? send object_id class extend find size count sum average maximum minimum paginate first last empty? any? many? respond_to?)
.
to_set
[].
methods
.
each
do
|
m
|
unless
m
=~
/^__/
||
NON_DELEGATE_METHODS
.
include?
(
m
.
to_s
)
delegate
m
,
:to
=>
:proxy_found
end
end
class
Scope
<
Relation
attr_accessor
:current_scoped_methods_when_defined
delegate
:scopes
,
:with_scope
,
:with_exclusive_scope
,
:scoped_methods
,
:scoped
,
:to
=>
:klass
delegate
:new
,
:build
,
:all
,
:to
=>
:relation
def
initialize
(
klass
,
options
,
&
block
)
extend
Module
.
new
(
&
block
)
if
block_given?
def
self
.
init
(
klass
,
options
,
&
block
)
relation
=
new
(
klass
,
klass
.
arel_table
)
options
||=
{}
if
options
.
is_a?
(
Hash
)
Array
.
wrap
(
options
[
:extend
]).
each
{
|
extension
|
extend
extension
}
@proxy_options
=
options
.
except
(
:extend
)
scope
=
if
options
.
is_a?
(
Hash
)
klass
.
scoped
.
apply_finder_options
(
options
.
except
(
:extend
))
else
@proxy_options
=
options
options
?
klass
.
scoped
.
merge
(
options
)
:
klass
.
scoped
end
unless
Scope
===
klass
@current_scoped_methods_when_defined
=
klass
.
send
(
:current_scoped_methods
)
end
relation
=
relation
.
merge
(
scope
)
@klass
=
klass
end
Array
.
wrap
(
options
[
:extend
]).
each
{
|
extension
|
relation
.
send
(
:extend
,
extension
)
}
if
options
.
is_a?
(
Hash
)
relation
.
send
(
:extend
,
Module
.
new
(
&
block
))
if
block_given?
def
reload
load_found
;
self
relation
.
current_scoped_methods_when_defined
=
klass
.
send
(
:current_scoped_methods
)
relation
end
def
first
(
*
args
)
if
args
.
first
.
kind_of?
(
Integer
)
||
(
@found
&&
!
args
.
first
.
kind_of?
(
Hash
))
proxy_found
.
first
(
*
args
)
else
find
(
:first
,
*
args
)
end
end
def
find
(
*
args
)
options
=
args
.
extract_options!
relation
=
options
.
present?
?
apply_finder_options
(
options
)
:
self
def
last
(
*
args
)
if
args
.
first
.
kind_of?
(
Integer
)
||
(
@found
&&
!
args
.
first
.
kind_of?
(
Hash
))
proxy_found
.
last
(
*
args
)
case
args
.
first
when
:first
,
:last
,
:all
relation
.
send
(
args
.
first
)
else
find
(
:last
,
*
args
)
end
options
.
present?
?
relation
.
find
(
*
args
)
:
super
end
def
size
@found
?
@found
.
length
:
count
end
def
empty?
@found
?
@found
.
empty?
:
count
.
zero?
end
def
respond_to?
(
method
,
include_private
=
false
)
super
||
@klass
.
respond_to?
(
method
,
include_private
)
end
def
any?
if
block_given?
proxy_found
.
any?
{
|*
block_args
|
yield
(
*
block_args
)
}
def
first
(
*
args
)
if
args
.
first
.
kind_of?
(
Integer
)
||
(
loaded?
&&
!
args
.
first
.
kind_of?
(
Hash
))
to_a
.
first
(
*
args
)
else
!
empty?
args
.
first
.
present?
?
apply_finder_options
(
args
.
first
).
first
:
super
end
end
# Returns true if the named scope has more than 1 matching record.
def
many?
if
block_given?
proxy_found
.
many?
{
|*
block_args
|
yield
(
*
block_args
)
}
def
last
(
*
args
)
if
args
.
first
.
kind_of?
(
Integer
)
||
(
loaded?
&&
!
args
.
first
.
kind_of?
(
Hash
))
to_a
.
last
(
*
args
)
else
size
>
1
args
.
first
.
present?
?
apply_finder_options
(
args
.
first
).
last
:
super
end
end
def
relation
@relation
||=
begin
if
proxy_options
.
is_a?
(
Hash
)
scoped
.
apply_finder_options
(
proxy_options
)
else
scoped
.
merge
(
proxy_options
)
end
end
def
count
(
*
args
)
options
=
args
.
extract_options!
options
.
present?
?
apply_finder_options
(
options
).
count
(
*
args
)
:
super
end
def
proxy_found
@found
||
load_found
def
==
(
other
)
to_a
==
other
.
to_a
end
private
def
method_missing
(
method
,
*
args
,
&
block
)
with_scope
(
relation
,
:reverse_merge
)
do
if
klass
.
respond_to?
(
method
)
with_scope
(
self
)
do
if
current_scoped_methods_when_defined
&&
!
scoped_methods
.
include?
(
current_scoped_methods_when_defined
)
&&
!
scopes
.
include?
(
method
)
with_scope
current_scoped_methods_when_defined
do
klass
.
send
(
method
,
*
args
,
&
block
)
end
with_scope
(
current_scoped_methods_when_defined
)
{
klass
.
send
(
method
,
*
args
,
&
block
)
}
else
klass
.
send
(
method
,
*
args
,
&
block
)
end
end
else
super
end
def
load_found
@found
=
find
(
:all
)
end
end
end
end
activerecord/lib/active_record/relation.rb
浏览文件 @
88de6b2d
...
...
@@ -7,7 +7,7 @@ class Relation
include
FinderMethods
,
CalculationMethods
,
SpawnMethods
,
QueryMethods
delegate
:length
,
:collect
,
:map
,
:each
,
:all?
,
:to
=>
:to_a
delegate
:length
,
:collect
,
:map
,
:each
,
:all?
,
:
include?
,
:
to
=>
:to_a
attr_reader
:table
,
:klass
...
...
@@ -175,6 +175,8 @@ def method_missing(method, *args, &block)
end
end
private
def
with_create_scope
@klass
.
send
(
:with_scope
,
:create
=>
scope_for_create
,
:find
=>
{})
{
yield
}
end
...
...
activerecord/lib/active_record/relation/predicate_builder.rb
浏览文件 @
88de6b2d
...
...
@@ -24,7 +24,7 @@ def build_from_hash(attributes, default_table)
case
value
when
Array
,
ActiveRecord
::
Associations
::
AssociationCollection
,
ActiveRecord
::
NamedScope
::
Scope
attribute
.
in
(
value
)
attribute
.
in
(
value
.
to_a
)
when
Range
# TODO : Arel should handle ranges with excluded end.
if
value
.
exclude_end?
...
...
activerecord/lib/active_record/relation/spawn_methods.rb
浏览文件 @
88de6b2d
module
ActiveRecord
module
SpawnMethods
def
spawn
(
arel_table
=
self
.
table
)
relation
=
Relation
.
new
(
@klass
,
arel_table
)
relation
=
self
.
class
.
new
(
@klass
,
arel_table
)
(
Relation
::
ASSOCIATION_METHODS
+
Relation
::
MULTI_VALUE_METHODS
).
each
do
|
query_method
|
relation
.
send
(
:"
#{
query_method
}
_values="
,
send
(
:"
#{
query_method
}
_values"
))
...
...
@@ -64,7 +64,7 @@ def merge(r)
alias
:&
:merge
def
except
(
*
skips
)
result
=
Relation
.
new
(
@klass
,
table
)
result
=
self
.
class
.
new
(
@klass
,
table
)
(
Relation
::
ASSOCIATION_METHODS
+
Relation
::
MULTI_VALUE_METHODS
).
each
do
|
method
|
result
.
send
(
:"
#{
method
}
_values="
,
send
(
:"
#{
method
}
_values"
))
unless
skips
.
include?
(
method
)
...
...
@@ -78,7 +78,7 @@ def except(*skips)
end
def
only
(
*
onlies
)
result
=
Relation
.
new
(
@klass
,
table
)
result
=
self
.
class
.
new
(
@klass
,
table
)
onlies
.
each
do
|
only
|
if
(
Relation
::
ASSOCIATION_METHODS
+
Relation
::
MULTI_VALUE_METHODS
).
include?
(
only
)
...
...
activerecord/test/cases/named_scope_test.rb
浏览文件 @
88de6b2d
...
...
@@ -31,7 +31,7 @@ def test_found_items_are_cached
def
test_reload_expires_cache_of_found_items
all_posts
=
Topic
.
base
all_posts
.
inspect
all_posts
.
all
new_post
=
Topic
.
create!
assert
!
all_posts
.
include?
(
new_post
)
...
...
@@ -48,14 +48,14 @@ def test_delegates_finds_and_calculations_to_the_base_class
end
def
test_scope_should_respond_to_own_methods_and_methods_of_the_proxy
assert
Topic
.
approved
.
respond_to?
(
:
proxy_found
)
assert
Topic
.
approved
.
respond_to?
(
:
limit
)
assert
Topic
.
approved
.
respond_to?
(
:count
)
assert
Topic
.
approved
.
respond_to?
(
:length
)
end
def
test_respond_to_respects_include_private_parameter
assert
!
Topic
.
approved
.
respond_to?
(
:
load_found
)
assert
Topic
.
approved
.
respond_to?
(
:
load_found
,
true
)
assert
!
Topic
.
approved
.
respond_to?
(
:
with_create_scope
)
assert
Topic
.
approved
.
respond_to?
(
:
with_create_scope
,
true
)
end
def
test_subclasses_inherit_scopes
...
...
@@ -155,7 +155,7 @@ def test_named_scopes_honor_current_scopes_from_when_defined
assert_not_equal
Post
.
ranked_by_comments
.
limit_by
(
5
),
authors
(
:david
).
posts
.
ranked_by_comments
.
limit_by
(
5
)
assert_not_equal
Post
.
top
(
5
),
authors
(
:david
).
posts
.
top
(
5
)
# Oracle sometimes sorts differently if WHERE condition is changed
assert_equal
authors
(
:david
).
posts
.
ranked_by_comments
.
limit_by
(
5
).
sort_by
(
&
:id
),
authors
(
:david
).
posts
.
top
(
5
)
.
sort_by
(
&
:id
)
assert_equal
authors
(
:david
).
posts
.
ranked_by_comments
.
limit_by
(
5
).
to_a
.
sort_by
(
&
:id
),
authors
(
:david
).
posts
.
top
(
5
).
to_a
.
sort_by
(
&
:id
)
assert_equal
Post
.
ranked_by_comments
.
limit_by
(
5
),
Post
.
top
(
5
)
end
...
...
@@ -171,11 +171,6 @@ def test_active_records_have_scope_named__scoped__
assert_equal
Topic
.
find
(
:all
,
scope
),
Topic
.
scoped
(
scope
)
end
def
test_proxy_options
expected_proxy_options
=
{
:conditions
=>
{
:approved
=>
true
}
}
assert_equal
expected_proxy_options
,
Topic
.
approved
.
proxy_options
end
def
test_first_and_last_should_support_find_options
assert_equal
Topic
.
base
.
first
(
:order
=>
'title'
),
Topic
.
base
.
find
(
:first
,
:order
=>
'title'
)
assert_equal
Topic
.
base
.
last
(
:order
=>
'title'
),
Topic
.
base
.
find
(
:last
,
:order
=>
'title'
)
...
...
@@ -297,7 +292,7 @@ def test_should_build_with_proxy_options_chained
end
def
test_find_all_should_behave_like_select
assert_equal
Topic
.
base
.
select
(
&
:approved
),
Topic
.
base
.
find_all
(
&
:approved
)
assert_equal
Topic
.
base
.
to_a
.
select
(
&
:approved
),
Topic
.
base
.
to_a
.
find_all
(
&
:approved
)
end
def
test_rand_should_select_a_random_object_from_proxy
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录