Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
fbf50858
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,发现更多精彩内容 >>
提交
fbf50858
编写于
10月 16, 2013
作者:
A
Arthur Neves
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix some indentation on autosave association
上级
827d42e1
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
196 addition
and
196 deletion
+196
-196
activerecord/lib/active_record/autosave_association.rb
activerecord/lib/active_record/autosave_association.rb
+196
-196
未找到文件。
activerecord/lib/active_record/autosave_association.rb
浏览文件 @
fbf50858
...
...
@@ -143,71 +143,71 @@ def self.valid_options
module
ClassMethods
private
def
define_non_cyclic_method
(
name
,
&
block
)
define_method
(
name
)
do
|*
args
|
result
=
true
;
@_already_called
||=
{}
# Loop prevention for validation of associations
unless
@_already_called
[
name
]
begin
@_already_called
[
name
]]
=
true
result
=
instance_eval
(
&
block
)
ensure
@_already_called
[
name
]
=
false
def
define_non_cyclic_method
(
name
,
&
block
)
define_method
(
name
)
do
|*
args
|
result
=
true
;
@_already_called
||=
{}
# Loop prevention for validation of associations
unless
@_already_called
[
name
]
begin
@_already_called
[
name
]
=
true
result
=
instance_eval
(
&
block
)
ensure
@_already_called
[
name
]
=
false
end
end
end
result
result
end
end
end
# Adds validation and save callbacks for the association as specified by
# the +reflection+.
#
# For performance reasons, we don't check whether to validate at runtime.
# However the validation and callback methods are lazy and those methods
# get created when they are invoked for the very first time. However,
# this can change, for instance, when using nested attributes, which is
# called _after_ the association has been defined. Since we don't want
# the callbacks to get defined multiple times, there are guards that
# check if the save or validation methods have already been defined
# before actually defining them.
def
add_autosave_association_callbacks
(
reflection
)
save_method
=
:"autosave_associated_records_for_
#{
reflection
.
name
}
"
validation_method
=
:"validate_associated_records_for_
#{
reflection
.
name
}
"
collection
=
reflection
.
collection?
unless
method_defined?
(
save_method
)
if
collection
before_save
:before_save_collection_association
define_non_cyclic_method
(
save_method
)
{
save_collection_association
(
reflection
)
}
# Doesn't use after_save as that would save associations added in after_create/after_update twice
after_create
save_method
after_update
save_method
elsif
reflection
.
macro
==
:has_one
define_method
(
save_method
)
{
save_has_one_association
(
reflection
)
}
# Configures two callbacks instead of a single after_save so that
# the model may rely on their execution order relative to its
# own callbacks.
#
# For example, given that after_creates run before after_saves, if
# we configured instead an after_save there would be no way to fire
# a custom after_create callback after the child association gets
# created.
after_create
save_method
after_update
save_method
else
define_non_cyclic_method
(
save_method
)
{
save_belongs_to_association
(
reflection
)
}
before_save
save_method
# Adds validation and save callbacks for the association as specified by
# the +reflection+.
#
# For performance reasons, we don't check whether to validate at runtime.
# However the validation and callback methods are lazy and those methods
# get created when they are invoked for the very first time. However,
# this can change, for instance, when using nested attributes, which is
# called _after_ the association has been defined. Since we don't want
# the callbacks to get defined multiple times, there are guards that
# check if the save or validation methods have already been defined
# before actually defining them.
def
add_autosave_association_callbacks
(
reflection
)
save_method
=
:"autosave_associated_records_for_
#{
reflection
.
name
}
"
validation_method
=
:"validate_associated_records_for_
#{
reflection
.
name
}
"
collection
=
reflection
.
collection?
unless
method_defined?
(
save_method
)
if
collection
before_save
:before_save_collection_association
define_non_cyclic_method
(
save_method
)
{
save_collection_association
(
reflection
)
}
# Doesn't use after_save as that would save associations added in after_create/after_update twice
after_create
save_method
after_update
save_method
elsif
reflection
.
macro
==
:has_one
define_method
(
save_method
)
{
save_has_one_association
(
reflection
)
}
# Configures two callbacks instead of a single after_save so that
# the model may rely on their execution order relative to its
# own callbacks.
#
# For example, given that after_creates run before after_saves, if
# we configured instead an after_save there would be no way to fire
# a custom after_create callback after the child association gets
# created.
after_create
save_method
after_update
save_method
else
define_non_cyclic_method
(
save_method
)
{
save_belongs_to_association
(
reflection
)
}
before_save
save_method
end
end
end
if
reflection
.
validate?
&&
!
method_defined?
(
validation_method
)
method
=
(
collection
?
:validate_collection_association
:
:validate_single_association
)
define_non_cyclic_method
(
validation_method
)
{
send
(
method
,
reflection
)
}
validate
validation_method
if
reflection
.
validate?
&&
!
method_defined?
(
validation_method
)
method
=
(
collection
?
:validate_collection_association
:
:validate_single_association
)
define_non_cyclic_method
(
validation_method
)
{
send
(
method
,
reflection
)
}
validate
validation_method
end
end
end
end
# Reloads the attributes of the object as usual and clears <tt>marked_for_destruction</tt> flag.
...
...
@@ -254,173 +254,173 @@ def changed_for_autosave?
private
# Returns the record for an association collection that should be validated
# or saved. If +autosave+ is +false+ only new records will be returned,
# unless the parent is/was a new record itself.
def
associated_records_to_validate_or_save
(
association
,
new_record
,
autosave
)
if
new_record
association
&&
association
.
target
elsif
autosave
association
.
target
.
find_all
{
|
record
|
record
.
changed_for_autosave?
}
else
association
.
target
.
find_all
{
|
record
|
record
.
new_record?
}
# Returns the record for an association collection that should be validated
# or saved. If +autosave+ is +false+ only new records will be returned,
# unless the parent is/was a new record itself.
def
associated_records_to_validate_or_save
(
association
,
new_record
,
autosave
)
if
new_record
association
&&
association
.
target
elsif
autosave
association
.
target
.
find_all
{
|
record
|
record
.
changed_for_autosave?
}
else
association
.
target
.
find_all
{
|
record
|
record
.
new_record?
}
end
end
end
# go through nested autosave associations that are loaded in memory (without loading
# any new ones), and return true if is changed for autosave
def
nested_records_changed_for_autosave?
self
.
class
.
reflect_on_all_autosave_associations
.
any?
do
|
reflection
|
association
=
association_instance_get
(
reflection
.
name
)
association
&&
Array
.
wrap
(
association
.
target
).
any?
{
|
a
|
a
.
changed_for_autosave?
}
# go through nested autosave associations that are loaded in memory (without loading
# any new ones), and return true if is changed for autosave
def
nested_records_changed_for_autosave?
self
.
class
.
reflect_on_all_autosave_associations
.
any?
do
|
reflection
|
association
=
association_instance_get
(
reflection
.
name
)
association
&&
Array
.
wrap
(
association
.
target
).
any?
{
|
a
|
a
.
changed_for_autosave?
}
end
end
end
# Validate the association if <tt>:validate</tt> or <tt>:autosave</tt> is
# turned on for the association.
def
validate_single_association
(
reflection
)
association
=
association_instance_get
(
reflection
.
name
)
record
=
association
&&
association
.
reader
association_valid?
(
reflection
,
record
)
if
record
end
# Validate the association if <tt>:validate</tt> or <tt>:autosave</tt> is
# turned on for the association.
def
validate_single_association
(
reflection
)
association
=
association_instance_get
(
reflection
.
name
)
record
=
association
&&
association
.
reader
association_valid?
(
reflection
,
record
)
if
record
end
# Validate the associated records if <tt>:validate</tt> or
# <tt>:autosave</tt> is turned on for the association specified by
# +reflection+.
def
validate_collection_association
(
reflection
)
if
association
=
association_instance_get
(
reflection
.
name
)
if
records
=
associated_records_to_validate_or_save
(
association
,
new_record?
,
reflection
.
options
[
:autosave
])
records
.
each
{
|
record
|
association_valid?
(
reflection
,
record
)
}
# Validate the associated records if <tt>:validate</tt> or
# <tt>:autosave</tt> is turned on for the association specified by
# +reflection+.
def
validate_collection_association
(
reflection
)
if
association
=
association_instance_get
(
reflection
.
name
)
if
records
=
associated_records_to_validate_or_save
(
association
,
new_record?
,
reflection
.
options
[
:autosave
])
records
.
each
{
|
record
|
association_valid?
(
reflection
,
record
)
}
end
end
end
end
# Returns whether or not the association is valid and applies any errors to
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
# enabled records if they're marked_for_destruction? or destroyed.
def
association_valid?
(
reflection
,
record
)
return
true
if
record
.
destroyed?
||
record
.
marked_for_destruction?
unless
valid
=
record
.
valid?
if
reflection
.
options
[
:autosave
]
record
.
errors
.
each
do
|
attribute
,
message
|
attribute
=
"
#{
reflection
.
name
}
.
#{
attribute
}
"
errors
[
attribute
]
<<
message
errors
[
attribute
].
uniq!
# Returns whether or not the association is valid and applies any errors to
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
# enabled records if they're marked_for_destruction? or destroyed.
def
association_valid?
(
reflection
,
record
)
return
true
if
record
.
destroyed?
||
record
.
marked_for_destruction?
unless
valid
=
record
.
valid?
if
reflection
.
options
[
:autosave
]
record
.
errors
.
each
do
|
attribute
,
message
|
attribute
=
"
#{
reflection
.
name
}
.
#{
attribute
}
"
errors
[
attribute
]
<<
message
errors
[
attribute
].
uniq!
end
else
errors
.
add
(
reflection
.
name
)
end
else
errors
.
add
(
reflection
.
name
)
end
valid
end
valid
end
# Is used as a before_save callback to check while saving a collection
# association whether or not the parent was a new record before saving.
def
before_save_collection_association
@new_record_before_save
=
new_record?
true
end
# Is used as a before_save callback to check while saving a collection
# association whether or not the parent was a new record before saving.
def
before_save_collection_association
@new_record_before_save
=
new_record?
true
end
# Saves any new associated records, or all loaded autosave associations if
# <tt>:autosave</tt> is enabled on the association.
#
# In addition, it destroys all children that were marked for destruction
# with mark_for_destruction.
#
# This all happens inside a transaction, _if_ the Transactions module is included into
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
def
save_collection_association
(
reflection
)
if
association
=
association_instance_get
(
reflection
.
name
)
autosave
=
reflection
.
options
[
:autosave
]
if
records
=
associated_records_to_validate_or_save
(
association
,
@new_record_before_save
,
autosave
)
if
autosave
records_to_destroy
=
records
.
select
(
&
:marked_for_destruction?
)
records_to_destroy
.
each
{
|
record
|
association
.
destroy
(
record
)
}
records
-=
records_to_destroy
end
# Saves any new associated records, or all loaded autosave associations if
# <tt>:autosave</tt> is enabled on the association.
#
# In addition, it destroys all children that were marked for destruction
# with mark_for_destruction.
#
# This all happens inside a transaction, _if_ the Transactions module is included into
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
def
save_collection_association
(
reflection
)
if
association
=
association_instance_get
(
reflection
.
name
)
autosave
=
reflection
.
options
[
:autosave
]
if
records
=
associated_records_to_validate_or_save
(
association
,
@new_record_before_save
,
autosave
)
if
autosave
records_to_destroy
=
records
.
select
(
&
:marked_for_destruction?
)
records_to_destroy
.
each
{
|
record
|
association
.
destroy
(
record
)
}
records
-=
records_to_destroy
end
records
.
each
do
|
record
|
next
if
record
.
destroyed?
records
.
each
do
|
record
|
next
if
record
.
destroyed?
saved
=
true
saved
=
true
if
autosave
!=
false
&&
(
@new_record_before_save
||
record
.
new_record?
)
if
autosave
saved
=
association
.
insert_record
(
record
,
false
)
else
association
.
insert_record
(
record
)
unless
reflection
.
nested?
if
autosave
!=
false
&&
(
@new_record_before_save
||
record
.
new_record?
)
if
autosave
saved
=
association
.
insert_record
(
record
,
false
)
else
association
.
insert_record
(
record
)
unless
reflection
.
nested?
end
elsif
autosave
saved
=
record
.
save
(
:validate
=>
false
)
end
elsif
autosave
saved
=
record
.
save
(
:validate
=>
false
)
end
raise
ActiveRecord
::
Rollback
unless
saved
raise
ActiveRecord
::
Rollback
unless
saved
end
end
end
# reconstruct the scope now that we know the owner's id
association
.
reset_scope
if
association
.
respond_to?
(
:reset_scope
)
# reconstruct the scope now that we know the owner's id
association
.
reset_scope
if
association
.
respond_to?
(
:reset_scope
)
end
end
end
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled
# on the association.
#
# In addition, it will destroy the association if it was marked for
# destruction with mark_for_destruction.
#
# This all happens inside a transaction, _if_ the Transactions module is included into
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
def
save_has_one_association
(
reflection
)
association
=
association_instance_get
(
reflection
.
name
)
record
=
association
&&
association
.
load_target
if
record
&&
!
record
.
destroyed?
autosave
=
reflection
.
options
[
:autosave
]
if
autosave
&&
record
.
marked_for_destruction?
record
.
destroy
else
key
=
reflection
.
options
[
:primary_key
]
?
send
(
reflection
.
options
[
:primary_key
])
:
id
if
autosave
!=
false
&&
(
new_record?
||
record
.
new_record?
||
record
[
reflection
.
foreign_key
]
!=
key
||
autosave
)
unless
reflection
.
through_reflection
record
[
reflection
.
foreign_key
]
=
key
end
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled
# on the association.
#
# In addition, it will destroy the association if it was marked for
# destruction with mark_for_destruction.
#
# This all happens inside a transaction, _if_ the Transactions module is included into
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
def
save_has_one_association
(
reflection
)
association
=
association_instance_get
(
reflection
.
name
)
record
=
association
&&
association
.
load_target
if
record
&&
!
record
.
destroyed?
autosave
=
reflection
.
options
[
:autosave
]
saved
=
record
.
save
(
:validate
=>
!
autosave
)
raise
ActiveRecord
::
Rollback
if
!
saved
&&
autosave
saved
if
autosave
&&
record
.
marked_for_destruction?
record
.
destroy
else
key
=
reflection
.
options
[
:primary_key
]
?
send
(
reflection
.
options
[
:primary_key
])
:
id
if
autosave
!=
false
&&
(
new_record?
||
record
.
new_record?
||
record
[
reflection
.
foreign_key
]
!=
key
||
autosave
)
unless
reflection
.
through_reflection
record
[
reflection
.
foreign_key
]
=
key
end
saved
=
record
.
save
(
:validate
=>
!
autosave
)
raise
ActiveRecord
::
Rollback
if
!
saved
&&
autosave
saved
end
end
end
end
end
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
#
# In addition, it will destroy the association if it was marked for destruction.
def
save_belongs_to_association
(
reflection
)
association
=
association_instance_get
(
reflection
.
name
)
record
=
association
&&
association
.
load_target
if
record
&&
!
record
.
destroyed?
autosave
=
reflection
.
options
[
:autosave
]
if
autosave
&&
record
.
marked_for_destruction?
self
[
reflection
.
foreign_key
]
=
nil
record
.
destroy
elsif
autosave
!=
false
saved
=
record
.
save
(
:validate
=>
!
autosave
)
if
record
.
new_record?
||
(
autosave
&&
record
.
changed_for_autosave?
)
if
association
.
updated?
association_id
=
record
.
send
(
reflection
.
options
[
:primary_key
]
||
:id
)
self
[
reflection
.
foreign_key
]
=
association_id
association
.
loaded!
end
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
#
# In addition, it will destroy the association if it was marked for destruction.
def
save_belongs_to_association
(
reflection
)
association
=
association_instance_get
(
reflection
.
name
)
record
=
association
&&
association
.
load_target
if
record
&&
!
record
.
destroyed?
autosave
=
reflection
.
options
[
:autosave
]
if
autosave
&&
record
.
marked_for_destruction?
self
[
reflection
.
foreign_key
]
=
nil
record
.
destroy
elsif
autosave
!=
false
saved
=
record
.
save
(
:validate
=>
!
autosave
)
if
record
.
new_record?
||
(
autosave
&&
record
.
changed_for_autosave?
)
if
association
.
updated?
association_id
=
record
.
send
(
reflection
.
options
[
:primary_key
]
||
:id
)
self
[
reflection
.
foreign_key
]
=
association_id
association
.
loaded!
end
saved
if
autosave
saved
if
autosave
end
end
end
end
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录