Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
877ea784
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,发现更多精彩内容 >>
提交
877ea784
编写于
7月 12, 2014
作者:
S
Sean Griffin
提交者:
Godfrey Chan
8月 16, 2014
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement `_was` and `changes` for in-place mutations of AR attributes
上级
88d27ae9
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
62 addition
and
21 deletion
+62
-21
activemodel/lib/active_model/dirty.rb
activemodel/lib/active_model/dirty.rb
+16
-3
activerecord/lib/active_record/associations/has_many_association.rb
...rd/lib/active_record/associations/has_many_association.rb
+1
-1
activerecord/lib/active_record/attribute.rb
activerecord/lib/active_record/attribute.rb
+6
-2
activerecord/lib/active_record/attribute_methods/dirty.rb
activerecord/lib/active_record/attribute_methods/dirty.rb
+14
-11
activerecord/lib/active_record/enum.rb
activerecord/lib/active_record/enum.rb
+2
-2
activerecord/lib/active_record/persistence.rb
activerecord/lib/active_record/persistence.rb
+1
-1
activerecord/lib/active_record/timestamp.rb
activerecord/lib/active_record/timestamp.rb
+1
-1
activerecord/test/cases/dirty_test.rb
activerecord/test/cases/dirty_test.rb
+21
-0
未找到文件。
activemodel/lib/active_model/dirty.rb
浏览文件 @
877ea784
...
...
@@ -114,7 +114,7 @@ module Dirty
include
ActiveModel
::
AttributeMethods
included
do
attribute_method_suffix
'_changed?'
,
'_change'
,
'_will_change!'
,
'_was'
attribute_method_suffix
'_changed?'
,
'_change'
,
'_will_change!'
,
'_was'
,
'_was='
attribute_method_affix
prefix:
'reset_'
,
suffix:
'!'
attribute_method_affix
prefix:
'restore_'
,
suffix:
'!'
end
...
...
@@ -180,13 +180,26 @@ def attribute_was(attr) # :nodoc:
attribute_changed?
(
attr
)
?
changed_attributes
[
attr
]
:
__send__
(
attr
)
end
# Handle <tt>*_was=</tt> for +method_missing+
def
attribute_was
=
(
attr
,
old_value
)
attributes_changed_by_setter
[
attr
]
=
old_value
end
alias_method
:set_attribute_was
,
:attribute_was
=
# Restore all previous data of the provided attributes.
def
restore_attributes
(
attributes
=
changed
)
attributes
.
each
{
|
attr
|
restore_attribute!
attr
}
end
# Remove changes information for the provided attributes.
def
clear_attribute_changes
(
attributes
)
attributes_changed_by_setter
.
except!
(
*
attributes
)
end
private
alias_method
:attributes_changed_by_setter
,
:changed_attributes
# :nodoc:
# Removes current changes and makes them accessible through +previous_changes+.
def
changes_applied
# :doc:
@previously_changed
=
changes
...
...
@@ -219,7 +232,7 @@ def attribute_will_change!(attr)
rescue
TypeError
,
NoMethodError
end
changed_attributes
[
attr
]
=
value
set_attribute_was
(
attr
,
value
)
end
# Handle <tt>reset_*!</tt> for +method_missing+.
...
...
@@ -233,7 +246,7 @@ def reset_attribute!(attr)
def
restore_attribute!
(
attr
)
if
attribute_changed?
(
attr
)
__send__
(
"
#{
attr
}
="
,
changed_attributes
[
attr
])
c
hanged_attributes
.
delete
(
attr
)
c
lear_attribute_changes
([
attr
]
)
end
end
end
...
...
activerecord/lib/active_record/associations/has_many_association.rb
浏览文件 @
877ea784
...
...
@@ -103,7 +103,7 @@ def update_counter_in_memory(difference, reflection = reflection())
if
has_cached_counter?
(
reflection
)
counter
=
cached_counter_attribute_name
(
reflection
)
owner
[
counter
]
+=
difference
owner
.
c
hanged_attributes
.
delete
(
counter
)
# eww
owner
.
c
lear_attribute_changes
([
counter
]
)
# eww
end
end
...
...
activerecord/lib/active_record/attribute.rb
浏览文件 @
877ea784
...
...
@@ -30,10 +30,14 @@ def initialize(name, value_before_type_cast, type)
def
value
# `defined?` is cheaper than `||=` when we get back falsy values
@value
=
type_cast
(
value_before_type_cast
)
unless
defined?
(
@value
)
@value
=
original_value
unless
defined?
(
@value
)
@value
end
def
original_value
type_cast
(
value_before_type_cast
)
end
def
value_for_database
type
.
type_cast_for_database
(
value
)
end
...
...
@@ -54,7 +58,7 @@ def with_value_from_database(value)
self
.
class
.
from_database
(
name
,
value
,
type
)
end
def
type_cast
def
type_cast
(
*
)
raise
NotImplementedError
end
...
...
activerecord/lib/active_record/attribute_methods/dirty.rb
浏览文件 @
877ea784
...
...
@@ -51,14 +51,6 @@ def changed
super
|
changed_in_place
end
def
attribute_changed?
(
attr_name
,
options
=
{})
result
=
super
# We can't change "from" something in place. Only setters can define
# "from" and "to"
result
||=
changed_in_place?
(
attr_name
)
unless
options
.
key?
(
:from
)
result
end
def
changes_applied
super
store_original_raw_attributes
...
...
@@ -69,12 +61,16 @@ def clear_changes_information
original_raw_attributes
.
clear
end
def
changed_attributes
super
.
reverse_merge
(
attributes_changed_in_place
).
freeze
end
private
def
calculate_changes_from_defaults
@changed_attributes
=
nil
self
.
class
.
column_defaults
.
each
do
|
attr
,
orig_value
|
changed_attributes
[
attr
]
=
orig_value
if
_field_changed?
(
attr
,
orig_value
)
set_attribute_was
(
attr
,
orig_value
)
if
_field_changed?
(
attr
,
orig_value
)
end
end
...
...
@@ -100,9 +96,9 @@ def raw_write_attribute(attr, value)
def
save_changed_attribute
(
attr
,
old_value
)
if
attribute_changed?
(
attr
)
c
hanged_attributes
.
delete
(
attr
)
unless
_field_changed?
(
attr
,
old_value
)
c
lear_attribute_changes
(
attr
)
unless
_field_changed?
(
attr
,
old_value
)
else
changed_attributes
[
attr
]
=
old_value
if
_field_changed?
(
attr
,
old_value
)
set_attribute_was
(
attr
,
old_value
)
if
_field_changed?
(
attr
,
old_value
)
end
end
...
...
@@ -132,6 +128,13 @@ def _field_changed?(attr, old_value)
@attributes
[
attr
].
changed_from?
(
old_value
)
end
def
attributes_changed_in_place
changed_in_place
.
each_with_object
({})
do
|
attr_name
,
h
|
orig
=
@attributes
[
attr_name
].
original_value
h
[
attr_name
]
=
orig
end
end
def
changed_in_place
self
.
class
.
attribute_names
.
select
do
|
attr_name
|
changed_in_place?
(
attr_name
)
...
...
activerecord/lib/active_record/enum.rb
浏览文件 @
877ea784
...
...
@@ -145,11 +145,11 @@ def save_changed_attribute(attr_name, old)
value
=
read_attribute
(
attr_name
)
if
attribute_changed?
(
attr_name
)
if
mapping
[
old
]
==
value
c
hanged_attributes
.
delete
(
attr_name
)
c
lear_attribute_changes
([
attr_name
]
)
end
else
if
old
!=
value
changed_attributes
[
attr_name
]
=
mapping
.
key
old
set_attribute_was
(
attr_name
,
mapping
.
key
(
old
))
end
end
else
...
...
activerecord/lib/active_record/persistence.rb
浏览文件 @
877ea784
...
...
@@ -466,7 +466,7 @@ def touch(*names)
changes
[
self
.
class
.
locking_column
]
=
increment_lock
if
locking_enabled?
c
hanged_attributes
.
except!
(
*
changes
.
keys
)
c
lear_attribute_changes
(
changes
.
keys
)
primary_key
=
self
.
class
.
primary_key
self
.
class
.
unscoped
.
where
(
primary_key
=>
self
[
primary_key
]).
update_all
(
changes
)
==
1
else
...
...
activerecord/lib/active_record/timestamp.rb
浏览文件 @
877ea784
...
...
@@ -114,7 +114,7 @@ def current_time_from_proper_timezone
def
clear_timestamp_attributes
all_timestamp_attributes_in_model
.
each
do
|
attribute_name
|
self
[
attribute_name
]
=
nil
c
hanged_attributes
.
delete
(
attribute_name
)
c
lear_attribute_changes
([
attribute_name
]
)
end
end
end
...
...
activerecord/test/cases/dirty_test.rb
浏览文件 @
877ea784
...
...
@@ -661,6 +661,27 @@ def type_cast_for_database(value)
assert_not
model
.
foo_changed?
end
test
"in place mutation detection"
do
pirate
=
Pirate
.
create!
(
catchphrase:
"arrrr"
)
pirate
.
catchphrase
<<
" matey!"
assert
pirate
.
catchphrase_changed?
expected_changes
=
{
"catchphrase"
=>
[
"arrrr"
,
"arrrr matey!"
]
}
assert_equal
(
expected_changes
,
pirate
.
changes
)
assert_equal
(
"arrrr"
,
pirate
.
catchphrase_was
)
assert
pirate
.
catchphrase_changed?
(
from:
"arrrr"
)
assert_not
pirate
.
catchphrase_changed?
(
from:
"anything else"
)
assert
pirate
.
changed_attributes
.
include?
(
:catchphrase
)
pirate
.
save!
pirate
.
reload
assert_equal
"arrrr matey!"
,
pirate
.
catchphrase
assert_not
pirate
.
changed?
end
private
def
with_partial_writes
(
klass
,
on
=
true
)
old
=
klass
.
partial_writes?
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录