Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
7e6530b1
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,发现更多精彩内容 >>
提交
7e6530b1
编写于
1月 09, 2010
作者:
J
José Valim
浏览文件
操作
浏览文件
下载
差异文件
Merge remote branch 'eloy/master'
上级
017f5d53
7f775ef1
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
125 addition
and
31 deletion
+125
-31
activerecord/lib/active_record/associations.rb
activerecord/lib/active_record/associations.rb
+3
-3
activerecord/lib/active_record/autosave_association.rb
activerecord/lib/active_record/autosave_association.rb
+14
-8
activerecord/lib/active_record/nested_attributes.rb
activerecord/lib/active_record/nested_attributes.rb
+1
-1
activerecord/lib/active_record/reflection.rb
activerecord/lib/active_record/reflection.rb
+5
-5
activerecord/test/cases/autosave_association_test.rb
activerecord/test/cases/autosave_association_test.rb
+57
-10
activerecord/test/cases/reflection_test.rb
activerecord/test/cases/reflection_test.rb
+4
-4
activerecord/test/models/bird.rb
activerecord/test/models/bird.rb
+6
-0
activerecord/test/models/invoice.rb
activerecord/test/models/invoice.rb
+4
-0
activerecord/test/models/line_item.rb
activerecord/test/models/line_item.rb
+3
-0
activerecord/test/models/parrot.rb
activerecord/test/models/parrot.rb
+6
-0
activerecord/test/models/pirate.rb
activerecord/test/models/pirate.rb
+6
-0
activerecord/test/models/ship.rb
activerecord/test/models/ship.rb
+6
-0
activerecord/test/schema/schema.rb
activerecord/test/schema/schema.rb
+10
-0
未找到文件。
activerecord/lib/active_record/associations.rb
浏览文件 @
7e6530b1
...
...
@@ -1770,7 +1770,7 @@ def construct_finder_sql_for_association_limiting(options, join_dependency)
end
def
using_limitable_reflections?
(
reflections
)
reflections
.
collect
(
&
:collection
_association
?
).
length
.
zero?
reflections
.
collect
(
&
:collection?
).
length
.
zero?
end
def
column_aliases
(
join_dependency
)
...
...
@@ -1843,7 +1843,7 @@ def remove_duplicate_results!(base, records, associations)
case
associations
when
Symbol
,
String
reflection
=
base
.
reflections
[
associations
]
if
reflection
&&
reflection
.
collection
_association
?
if
reflection
&&
reflection
.
collection?
records
.
each
{
|
record
|
record
.
send
(
reflection
.
name
).
target
.
uniq!
}
end
when
Array
...
...
@@ -1857,7 +1857,7 @@ def remove_duplicate_results!(base, records, associations)
parent_records
=
[]
records
.
each
do
|
record
|
if
descendant
=
record
.
send
(
reflection
.
name
)
if
reflection
.
collection
_association
?
if
reflection
.
collection?
parent_records
.
concat
descendant
.
target
.
uniq
else
parent_records
<<
descendant
...
...
activerecord/lib/active_record/autosave_association.rb
浏览文件 @
7e6530b1
...
...
@@ -166,7 +166,7 @@ def #{type}(name, options = {})
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
_association
?
collection
=
reflection
.
collection?
unless
method_defined?
(
save_method
)
if
collection
...
...
@@ -224,10 +224,10 @@ def marked_for_destruction?
def
associated_records_to_validate_or_save
(
association
,
new_record
,
autosave
)
if
new_record
association
elsif
a
ssociation
.
loaded?
a
utosave
?
association
:
association
.
find_all
{
|
record
|
record
.
new_record
?
}
elsif
a
utosave
a
ssociation
.
target
.
find_all
{
|
record
|
record
.
new_record?
||
record
.
changed?
||
record
.
marked_for_destruction
?
}
else
a
utosave
?
association
.
target
:
a
ssociation
.
target
.
find_all
{
|
record
|
record
.
new_record?
}
association
.
target
.
find_all
{
|
record
|
record
.
new_record?
}
end
end
...
...
@@ -296,13 +296,15 @@ def save_collection_association(reflection)
association
.
destroy
(
record
)
elsif
autosave
!=
false
&&
(
@new_record_before_save
||
record
.
new_record?
)
if
autosave
association
.
send
(
:insert_record
,
record
,
false
,
false
)
saved
=
association
.
send
(
:insert_record
,
record
,
false
,
false
)
else
association
.
send
(
:insert_record
,
record
)
end
elsif
autosave
record
.
save
(
false
)
saved
=
record
.
save
(
false
)
end
raise
ActiveRecord
::
Rollback
if
saved
==
false
end
end
...
...
@@ -329,7 +331,9 @@ def save_has_one_association(reflection)
key
=
reflection
.
options
[
:primary_key
]
?
send
(
reflection
.
options
[
:primary_key
])
:
id
if
autosave
!=
false
&&
(
new_record?
||
association
.
new_record?
||
association
[
reflection
.
primary_key_name
]
!=
key
||
autosave
)
association
[
reflection
.
primary_key_name
]
=
key
association
.
save
(
!
autosave
)
saved
=
association
.
save
(
!
autosave
)
raise
ActiveRecord
::
Rollback
if
!
saved
&&
autosave
saved
end
end
end
...
...
@@ -350,7 +354,7 @@ def save_belongs_to_association(reflection)
if
autosave
&&
association
.
marked_for_destruction?
association
.
destroy
elsif
autosave
!=
false
association
.
save
(
!
autosave
)
if
association
.
new_record?
||
autosave
saved
=
association
.
save
(
!
autosave
)
if
association
.
new_record?
||
autosave
if
association
.
updated?
association_id
=
association
.
send
(
reflection
.
options
[
:primary_key
]
||
:id
)
...
...
@@ -360,6 +364,8 @@ def save_belongs_to_association(reflection)
self
[
reflection
.
options
[
:foreign_type
]]
=
association
.
class
.
base_class
.
name
.
to_s
end
end
saved
if
autosave
end
end
end
...
...
activerecord/lib/active_record/nested_attributes.rb
浏览文件 @
7e6530b1
...
...
@@ -238,7 +238,7 @@ def accepts_nested_attributes_for(*attr_names)
reflection
.
options
[
:autosave
]
=
true
add_autosave_association_callbacks
(
reflection
)
nested_attributes_options
[
association_name
.
to_sym
]
=
options
type
=
(
reflection
.
collection
_association
?
?
:collection
:
:one_to_one
)
type
=
(
reflection
.
collection?
?
:collection
:
:one_to_one
)
# def pirate_attributes=(attributes)
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes)
...
...
activerecord/lib/active_record/reflection.rb
浏览文件 @
7e6530b1
...
...
@@ -255,11 +255,11 @@ def polymorphic_inverse_of(associated_class)
# Returns whether or not this association reflection is for a collection
# association. Returns +true+ if the +macro+ is one of +has_many+ or
# +has_and_belongs_to_many+, +false+ otherwise.
def
collection
_association
?
if
@collection
_association
.
nil?
@collection
_association
=
[
:has_many
,
:has_and_belongs_to_many
].
include?
(
macro
)
def
collection?
if
@collection
.
nil?
@collection
=
[
:has_many
,
:has_and_belongs_to_many
].
include?
(
macro
)
end
@collection
_association
@collection
end
# Returns whether or not the association should be validated as part of
...
...
@@ -278,7 +278,7 @@ def validate?
private
def
derive_class_name
class_name
=
name
.
to_s
.
camelize
class_name
=
class_name
.
singularize
if
collection
_association
?
class_name
=
class_name
.
singularize
if
collection?
class_name
end
...
...
activerecord/test/cases/autosave_association_test.rb
浏览文件 @
7e6530b1
...
...
@@ -3,6 +3,8 @@
require
'models/company'
require
'models/customer'
require
'models/developer'
require
'models/invoice'
require
'models/line_item'
require
'models/order'
require
'models/parrot'
require
'models/person'
...
...
@@ -699,23 +701,18 @@ def save(*args)
define_method
(
"test_should_rollback_destructions_if_an_exception_occurred_while_saving_
#{
association_name
}
"
)
do
2
.
times
{
|
i
|
@pirate
.
send
(
association_name
).
create!
(
:name
=>
"
#{
association_name
}
_
#{
i
}
"
)
}
before
=
@pirate
.
send
(
association_name
).
map
{
|
c
|
c
}
before
=
@pirate
.
send
(
association_name
).
map
{
|
c
|
c
.
mark_for_destruction
;
c
}
# Stub the save method of the first child to destroy and the second to raise an exception
class
<<
before
.
first
def
save
(
*
args
)
super
destroy
end
end
# Stub the destroy method of the the second child to raise an exception
class
<<
before
.
last
def
save
(
*
args
)
def
destroy
(
*
args
)
super
raise
'Oh noes!'
end
end
assert_raise
(
RuntimeError
)
{
assert
!
@pirate
.
save
}
assert
before
.
first
.
frozen?
# the first child was indeed destroyed
assert_equal
before
,
@pirate
.
reload
.
send
(
association_name
)
end
...
...
@@ -833,6 +830,18 @@ def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_t
end
end
def
test_should_not_save_and_return_false_if_a_callback_cancelled_saving
pirate
=
Pirate
.
new
(
:catchphrase
=>
'Arr'
)
ship
=
pirate
.
build_ship
(
:name
=>
'The Vile Insanity'
)
ship
.
cancel_save_from_callback
=
true
assert_no_difference
'Pirate.count'
do
assert_no_difference
'Ship.count'
do
assert
!
pirate
.
save
end
end
end
def
test_should_rollback_any_changes_if_an_exception_occurred_while_saving
before
=
[
@pirate
.
catchphrase
,
@pirate
.
ship
.
name
]
...
...
@@ -916,6 +925,18 @@ def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_t
end
end
def
test_should_not_save_and_return_false_if_a_callback_cancelled_saving
ship
=
Ship
.
new
(
:name
=>
'The Vile Insanity'
)
pirate
=
ship
.
build_pirate
(
:catchphrase
=>
'Arr'
)
pirate
.
cancel_save_from_callback
=
true
assert_no_difference
'Ship.count'
do
assert_no_difference
'Pirate.count'
do
assert
!
ship
.
save
end
end
end
def
test_should_rollback_any_changes_if_an_exception_occurred_while_saving
before
=
[
@ship
.
pirate
.
catchphrase
,
@ship
.
name
]
...
...
@@ -931,7 +952,6 @@ def save(*args)
end
assert_raise
(
RuntimeError
)
{
assert
!
@ship
.
save
}
# TODO: Why does using reload on @ship looses the associated pirate?
assert_equal
before
,
[
@ship
.
pirate
.
reload
.
catchphrase
,
@ship
.
reload
.
name
]
end
...
...
@@ -1032,6 +1052,26 @@ def test_should_allow_to_bypass_validations_on_the_associated_models_on_create
end
end
def
test_should_not_save_and_return_false_if_a_callback_cancelled_saving_in_either_create_or_update
@pirate
.
catchphrase
=
'Changed'
@child_1
.
name
=
'Changed'
@child_1
.
cancel_save_from_callback
=
true
assert
!
@pirate
.
save
assert_equal
"Don' botharrr talkin' like one, savvy?"
,
@pirate
.
reload
.
catchphrase
assert_equal
"Posideons Killer"
,
@child_1
.
reload
.
name
new_pirate
=
Pirate
.
new
(
:catchphrase
=>
'Arr'
)
new_child
=
new_pirate
.
send
(
@association_name
).
build
(
:name
=>
'Grace OMalley'
)
new_child
.
cancel_save_from_callback
=
true
assert_no_difference
'Pirate.count'
do
assert_no_difference
"
#{
new_child
.
class
.
name
}
.count"
do
assert
!
new_pirate
.
save
end
end
end
def
test_should_rollback_any_changes_if_an_exception_occurred_while_saving
before
=
[
@pirate
.
catchphrase
,
*
@pirate
.
send
(
@association_name
).
map
(
&
:name
)]
new_names
=
[
'Grace OMalley'
,
'Privateers Greed'
]
...
...
@@ -1215,3 +1255,10 @@ def setup
assert
!
@pirate
.
respond_to?
(
:validate_associated_records_for_non_validated_parrots
)
end
end
class
TestAutosaveAssociationWithTouch
<
ActiveRecord
::
TestCase
def
test_autosave_with_touch_should_not_raise_system_stack_error
invoice
=
Invoice
.
create
assert_nothing_raised
{
invoice
.
line_items
.
create
(
:amount
=>
10
)
}
end
end
activerecord/test/cases/reflection_test.rb
浏览文件 @
7e6530b1
...
...
@@ -198,11 +198,11 @@ def test_has_many_through_reflection
end
def
test_collection_association
assert
Pirate
.
reflect_on_association
(
:birds
).
collection
_association
?
assert
Pirate
.
reflect_on_association
(
:parrots
).
collection
_association
?
assert
Pirate
.
reflect_on_association
(
:birds
).
collection?
assert
Pirate
.
reflect_on_association
(
:parrots
).
collection?
assert
!
Pirate
.
reflect_on_association
(
:ship
).
collection
_association
?
assert
!
Ship
.
reflect_on_association
(
:pirate
).
collection
_association
?
assert
!
Pirate
.
reflect_on_association
(
:ship
).
collection?
assert
!
Ship
.
reflect_on_association
(
:pirate
).
collection?
end
def
test_default_association_validation
...
...
activerecord/test/models/bird.rb
浏览文件 @
7e6530b1
class
Bird
<
ActiveRecord
::
Base
validates_presence_of
:name
attr_accessor
:cancel_save_from_callback
before_save
:cancel_save_callback_method
,
:if
=>
:cancel_save_from_callback
def
cancel_save_callback_method
false
end
end
\ No newline at end of file
activerecord/test/models/invoice.rb
0 → 100644
浏览文件 @
7e6530b1
class
Invoice
<
ActiveRecord
::
Base
has_many
:line_items
,
:autosave
=>
true
before_save
{
|
record
|
record
.
balance
=
record
.
line_items
.
map
(
&
:amount
).
sum
}
end
activerecord/test/models/line_item.rb
0 → 100644
浏览文件 @
7e6530b1
class
LineItem
<
ActiveRecord
::
Base
belongs_to
:invoice
,
:touch
=>
true
end
activerecord/test/models/parrot.rb
浏览文件 @
7e6530b1
...
...
@@ -6,6 +6,12 @@ class Parrot < ActiveRecord::Base
alias_attribute
:title
,
:name
validates_presence_of
:name
attr_accessor
:cancel_save_from_callback
before_save
:cancel_save_callback_method
,
:if
=>
:cancel_save_from_callback
def
cancel_save_callback_method
false
end
end
class
LiveParrot
<
Parrot
...
...
activerecord/test/models/pirate.rb
浏览文件 @
7e6530b1
...
...
@@ -51,6 +51,12 @@ def reject_empty_ships_on_create(attributes)
attributes
.
delete
(
'_reject_me_if_new'
).
present?
&&
new_record?
end
attr_accessor
:cancel_save_from_callback
before_save
:cancel_save_callback_method
,
:if
=>
:cancel_save_from_callback
def
cancel_save_callback_method
false
end
private
def
log_before_add
(
record
)
log
(
record
,
"before_adding_method"
)
...
...
activerecord/test/models/ship.rb
浏览文件 @
7e6530b1
...
...
@@ -9,4 +9,10 @@ class Ship < ActiveRecord::Base
accepts_nested_attributes_for
:update_only_pirate
,
:update_only
=>
true
validates_presence_of
:name
attr_accessor
:cancel_save_from_callback
before_save
:cancel_save_callback_method
,
:if
=>
:cancel_save_from_callback
def
cancel_save_callback_method
false
end
end
activerecord/test/schema/schema.rb
浏览文件 @
7e6530b1
...
...
@@ -191,6 +191,11 @@ def create_table(*args, &block)
t
.
string
:info
end
create_table
:invoices
,
:force
=>
true
do
|
t
|
t
.
integer
:balance
t
.
datetime
:updated_at
end
create_table
:items
,
:force
=>
true
do
|
t
|
t
.
column
:name
,
:integer
end
...
...
@@ -216,6 +221,11 @@ def create_table(*args, &block)
t
.
integer
:version
,
:null
=>
false
,
:default
=>
0
end
create_table
:line_items
,
:force
=>
true
do
|
t
|
t
.
integer
:invoice_id
t
.
integer
:amount
end
create_table
:lock_without_defaults
,
:force
=>
true
do
|
t
|
t
.
column
:lock_version
,
:integer
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录