Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
85a1c025
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,发现更多精彩内容 >>
提交
85a1c025
编写于
10月 03, 2015
作者:
B
Bogdan Gusiev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make #increment! and #decrement! methods concurency safe
上级
210f33c4
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
41 addition
and
40 deletion
+41
-40
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+4
-0
activerecord/lib/active_record/associations/belongs_to_association.rb
.../lib/active_record/associations/belongs_to_association.rb
+19
-27
activerecord/lib/active_record/associations/has_many_association.rb
...rd/lib/active_record/associations/has_many_association.rb
+2
-8
activerecord/lib/active_record/persistence.rb
activerecord/lib/active_record/persistence.rb
+7
-5
activerecord/test/cases/persistence_test.rb
activerecord/test/cases/persistence_test.rb
+9
-0
未找到文件。
activerecord/CHANGELOG.md
浏览文件 @
85a1c025
*
Make AR::Base #increment! and decrement! concurrency safe
*Bogdan Gusiev*
*
Don't require a database connection to load a class which uses acceptance
validations.
...
...
activerecord/lib/active_record/associations/belongs_to_association.rb
浏览文件 @
85a1c025
...
...
@@ -10,7 +10,7 @@ def handle_dependency
def
replace
(
record
)
if
record
raise_on_type_mismatch!
(
record
)
update_counters
(
record
)
update_counters
_on_replace
(
record
)
replace_keys
(
record
)
set_inverse_instance
(
record
)
@updated
=
true
...
...
@@ -32,45 +32,37 @@ def updated?
end
def
decrement_counters
# :nodoc:
with_cache_name
{
|
name
|
decrement_counter
name
}
update_counters
(
-
1
)
end
def
increment_counters
# :nodoc:
with_cache_name
{
|
name
|
increment_counter
name
}
update_counters
(
1
)
end
private
def
find_target?
!
loaded?
&&
foreign_key_present?
&&
klass
end
def
with_cache_nam
e
counter_cache_name
=
reflection
.
counter_cache_column
return
unless
counter_cache_name
&&
owner
.
persisted?
yield
counter_cache_name
def
update_counters
(
by
)
if
require_counter_update?
&&
foreign_key_present?
if
target
&&
!
stale_target?
target
.
increment!
(
reflection
.
counter_cache_column
,
by
)
els
e
klass
.
update_counters
(
target_id
,
reflection
.
counter_cache_column
=>
by
)
end
end
end
def
update_counters
(
record
)
with_cache_name
do
|
name
|
return
unless
different_target?
record
record
.
class
.
increment_counter
(
name
,
record
.
id
)
decrement_counter
name
end
def
find_target?
!
loaded?
&&
foreign_key_present?
&&
klass
end
def
decrement_counter
(
counter_cache_name
)
if
foreign_key_present?
klass
.
decrement_counter
(
counter_cache_name
,
target_id
)
end
def
require_counter_update?
reflection
.
counter_cache_column
&&
owner
.
persisted?
end
def
increment_counter
(
counter_cache_name
)
if
foreign_key_present?
klass
.
increment_counter
(
counter_cache_name
,
target_id
)
if
target
&&
!
stale_target?
target
.
increment
(
counter_cache_name
)
end
def
update_counters_on_replace
(
record
)
if
require_counter_update?
&&
different_target?
(
record
)
record
.
increment!
(
reflection
.
counter_cache_column
)
decrement_counters
end
end
...
...
activerecord/lib/active_record/associations/has_many_association.rb
浏览文件 @
85a1c025
...
...
@@ -88,21 +88,15 @@ def count_records
end
def
update_counter
(
difference
,
reflection
=
reflection
())
update_counter_in_database
(
difference
,
reflection
)
update_counter_in_memory
(
difference
,
reflection
)
end
def
update_counter_in_database
(
difference
,
reflection
=
reflection
())
if
reflection
.
has_cached_counter?
owner
.
class
.
update_counters
(
owner
.
id
,
reflection
.
counter_cache_column
=>
difference
)
owner
.
increment!
(
reflection
.
counter_cache_column
,
difference
)
end
end
def
update_counter_in_memory
(
difference
,
reflection
=
reflection
())
if
reflection
.
counter_must_be_updated_by_has_many?
counter
=
reflection
.
counter_cache_column
owner
[
counter
]
||=
0
owner
[
counter
]
+=
difference
owner
.
increment
(
counter
,
difference
)
owner
.
send
(
:clear_attribute_change
,
counter
)
# eww
end
end
...
...
activerecord/lib/active_record/persistence.rb
浏览文件 @
85a1c025
...
...
@@ -332,16 +332,18 @@ def increment(attribute, by = 1)
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def
increment!
(
attribute
,
by
=
1
)
increment
(
attribute
,
by
).
update_attribute
(
attribute
,
self
[
attribute
])
increment
(
attribute
,
by
)
change
=
public_send
(
attribute
)
-
(
attribute_was
(
attribute
.
to_s
)
||
0
)
self
.
class
.
update_counters
(
id
,
attribute
=>
change
)
clear_attribute_change
(
attribute
)
# eww
self
end
# Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
# The decrement is performed directly on the underlying attribute, no setter is invoked.
# Only makes sense for number-based attributes. Returns +self+.
def
decrement
(
attribute
,
by
=
1
)
self
[
attribute
]
||=
0
self
[
attribute
]
-=
by
self
increment
(
attribute
,
-
by
)
end
# Wrapper around +decrement+ that saves the record. This method differs from
...
...
@@ -349,7 +351,7 @@ def decrement(attribute, by = 1)
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
def
decrement!
(
attribute
,
by
=
1
)
decrement
(
attribute
,
by
).
update_attribute
(
attribute
,
self
[
attribute
]
)
increment!
(
attribute
,
-
by
)
end
# Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
...
...
activerecord/test/cases/persistence_test.rb
浏览文件 @
85a1c025
...
...
@@ -120,6 +120,15 @@ def test_increment_attribute_by
assert_equal
59
,
accounts
(
:signals37
,
:reload
).
credit_limit
end
def
test_increment_updates_counter_in_db_using_offset
a1
=
accounts
(
:signals37
)
initial_credit
=
a1
.
credit_limit
a2
=
Account
.
find
(
accounts
(
:signals37
).
id
)
a1
.
increment!
(
:credit_limit
)
a2
.
increment!
(
:credit_limit
)
assert_equal
initial_credit
+
2
,
a1
.
reload
.
credit_limit
end
def
test_destroy_all
conditions
=
"author_name = 'Mary'"
topics_by_mary
=
Topic
.
all
.
merge!
(
:where
=>
conditions
,
:order
=>
'id'
).
to_a
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录