Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
cc109111
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,发现更多精彩内容 >>
提交
cc109111
编写于
8月 01, 2015
作者:
S
Sean Griffin
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #20884
Add #cache_key to ActiveRecord::Relation.
上级
c7a9f572
476e3f55
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
137 addition
and
0 deletion
+137
-0
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+10
-0
activerecord/lib/active_record.rb
activerecord/lib/active_record.rb
+1
-0
activerecord/lib/active_record/base.rb
activerecord/lib/active_record/base.rb
+1
-0
activerecord/lib/active_record/collection_cache_key.rb
activerecord/lib/active_record/collection_cache_key.rb
+29
-0
activerecord/lib/active_record/relation.rb
activerecord/lib/active_record/relation.rb
+26
-0
activerecord/test/cases/collection_cache_key_test.rb
activerecord/test/cases/collection_cache_key_test.rb
+70
-0
未找到文件。
activerecord/CHANGELOG.md
浏览文件 @
cc109111
*
Add
`cache_key`
to ActiveRecord::Relation.
Example:
@users = User.where("name like ?", "%Alberto%")
@users.cache_key
=> "/users/query-5942b155a43b139f2471b872ac54251f-3-20150714212107656125000"
*Alberto Fernández-Capel*
*
Properly allow uniqueness validations on primary keys.
Fixes #20966.
...
...
activerecord/lib/active_record.rb
浏览文件 @
cc109111
...
...
@@ -53,6 +53,7 @@ module ActiveRecord
autoload
:Persistence
autoload
:QueryCache
autoload
:Querying
autoload
:CollectionCacheKey
autoload
:ReadonlyAttributes
autoload
:RecordInvalid
,
'active_record/validations'
autoload
:Reflection
...
...
activerecord/lib/active_record/base.rb
浏览文件 @
cc109111
...
...
@@ -280,6 +280,7 @@ class Base
extend
Explain
extend
Enum
extend
Delegation
::
DelegateCache
extend
CollectionCacheKey
include
Core
include
Persistence
...
...
activerecord/lib/active_record/collection_cache_key.rb
0 → 100644
浏览文件 @
cc109111
module
ActiveRecord
module
CollectionCacheKey
def
collection_cache_key
(
collection
=
all
,
timestamp_column
=
:updated_at
)
# :nodoc:
query_signature
=
Digest
::
MD5
.
hexdigest
(
collection
.
to_sql
)
key
=
"
#{
collection
.
model_name
.
cache_key
}
/query-
#{
query_signature
}
"
if
collection
.
loaded?
size
=
collection
.
size
timestamp
=
collection
.
max_by
(
&
timestamp_column
).
public_send
(
timestamp_column
)
else
column_type
=
type_for_attribute
(
timestamp_column
.
to_s
)
column
=
"
#{
connection
.
quote_table_name
(
collection
.
table_name
)
}
.
#{
connection
.
quote_column_name
(
timestamp_column
)
}
"
query
=
collection
.
select
(
"COUNT(*) AS size"
,
"MAX(
#{
column
}
) AS timestamp"
)
result
=
connection
.
select_one
(
query
)
size
=
result
[
"size"
]
timestamp
=
column_type
.
deserialize
(
result
[
"timestamp"
])
end
if
timestamp
"
#{
key
}
-
#{
size
}
-
#{
timestamp
.
utc
.
to_s
(
cache_timestamp_format
)
}
"
else
"
#{
key
}
-
#{
size
}
"
end
end
end
end
activerecord/lib/active_record/relation.rb
浏览文件 @
cc109111
...
...
@@ -298,6 +298,32 @@ def many?
limit_value
?
to_a
.
many?
:
size
>
1
end
# Returns a cache key that can be used to identify the records fetched by
# this query. The cache key is built with a fingerprint of the sql query,
# the number of records matched by the query and a timestamp of the last
# updated record. When a new record comes to match the query, or any of
# the existing records is updated or deleted, the cache key changes.
#
# Product.where("name like ?", "%Cosmic Encounter%").cache_key
# => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
#
# If the collection is loaded, the method will iterate through the records
# to generate the timestamp, otherwise it will trigger one SQL query like:
#
# SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
#
# You can also pass a custom timestamp column to fetch the timestamp of the
# last updated record.
#
# Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
#
# You can customize the strategy to generate the key on a per model basis
# overriding ActiveRecord::Base#collection_cache_key.
def
cache_key
(
timestamp_column
=
:updated_at
)
@cache_keys
||=
{}
@cache_keys
[
timestamp_column
]
||=
@klass
.
collection_cache_key
(
self
,
timestamp_column
)
end
# Scope all queries to the current scope.
#
# Comment.where(post_id: 1).scoping do
...
...
activerecord/test/cases/collection_cache_key_test.rb
0 → 100644
浏览文件 @
cc109111
require
"cases/helper"
require
"models/computer"
require
"models/developer"
require
"models/project"
require
"models/topic"
require
"models/post"
require
"models/comment"
module
ActiveRecord
class
CollectionCacheKeyTest
<
ActiveRecord
::
TestCase
fixtures
:developers
,
:projects
,
:developers_projects
,
:topics
,
:comments
,
:posts
test
"collection_cache_key on model"
do
assert_match
(
/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\Z/
,
Developer
.
collection_cache_key
)
end
test
"cache_key for relation"
do
developers
=
Developer
.
where
(
name:
"David"
)
last_developer_timestamp
=
developers
.
order
(
updated_at: :desc
).
first
.
updated_at
assert_match
/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\Z/
,
developers
.
cache_key
/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\Z/
=~
developers
.
cache_key
assert_equal
Digest
::
MD5
.
hexdigest
(
developers
.
to_sql
),
$1
assert_equal
developers
.
count
.
to_s
,
$2
assert_equal
last_developer_timestamp
.
to_s
(
ActiveRecord
::
Base
.
cache_timestamp_format
),
$3
end
test
"it triggers at most one query"
do
developers
=
Developer
.
where
(
name:
"David"
)
assert_queries
(
1
)
{
developers
.
cache_key
}
assert_queries
(
0
)
{
developers
.
cache_key
}
end
test
"it doesn't trigger any query if the relation is already loaded"
do
developers
=
Developer
.
where
(
name:
"David"
).
load
assert_queries
(
0
)
{
developers
.
cache_key
}
end
test
"relation cache_key changes when the sql query changes"
do
developers
=
Developer
.
where
(
name:
"David"
)
other_relation
=
Developer
.
where
(
name:
"David"
).
where
(
"1 = 1"
)
assert_not_equal
developers
.
cache_key
,
other_relation
.
cache_key
end
test
"cache_key for empty relation"
do
developers
=
Developer
.
where
(
name:
"Non Existent Developer"
)
assert_match
(
/\Adevelopers\/query-(\h+)-0\Z/
,
developers
.
cache_key
)
end
test
"cache_key with custom timestamp column"
do
topics
=
Topic
.
where
(
"title like ?"
,
"%Topic%"
)
last_topic_timestamp
=
topics
(
:fifth
).
written_on
.
utc
.
to_s
(
:nsec
)
assert_match
(
last_topic_timestamp
,
topics
.
cache_key
(
:written_on
))
end
test
"cache_key with unknown timestamp column"
do
topics
=
Topic
.
where
(
"title like ?"
,
"%Topic%"
)
assert_raises
(
ActiveRecord
::
StatementInvalid
)
{
topics
.
cache_key
(
:published_at
)
}
end
test
"collection proxy provides a cache_key"
do
developers
=
projects
(
:active_record
).
developers
assert_match
(
/\Adevelopers\/query-(\h+)-(\d+)-(\d+)\Z/
,
developers
.
cache_key
)
end
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录