Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
30a23280
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,发现更多精彩内容 >>
提交
30a23280
编写于
1月 31, 2012
作者:
J
Jon Leighton
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4727 from railsaholic/dependent_restrict_should_add_error
has_many/has_one, :dependent => :restrict, deprecation added
上级
9a172407
23074c81
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
157 addition
and
35 deletion
+157
-35
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+19
-0
activerecord/lib/active_record/associations.rb
activerecord/lib/active_record/associations.rb
+4
-4
activerecord/lib/active_record/associations/builder/association.rb
...ord/lib/active_record/associations/builder/association.rb
+30
-1
activerecord/lib/active_record/associations/builder/has_many.rb
...record/lib/active_record/associations/builder/has_many.rb
+1
-7
activerecord/lib/active_record/associations/builder/has_one.rb
...erecord/lib/active_record/associations/builder/has_one.rb
+3
-9
activerecord/lib/active_record/core.rb
activerecord/lib/active_record/core.rb
+10
-0
activerecord/lib/active_record/locale/en.yml
activerecord/lib/active_record/locale/en.yml
+1
-0
activerecord/test/cases/associations/has_many_associations_test.rb
...ord/test/cases/associations/has_many_associations_test.rb
+44
-12
activerecord/test/cases/associations/has_one_associations_test.rb
...cord/test/cases/associations/has_one_associations_test.rb
+35
-2
railties/lib/rails/generators/rails/app/templates/config/application.rb
...ails/generators/rails/app/templates/config/application.rb
+5
-0
railties/test/generators/app_generator_test.rb
railties/test/generators/app_generator_test.rb
+5
-0
未找到文件。
activerecord/CHANGELOG.md
浏览文件 @
30a23280
## Rails 4.0.0 (unreleased) ##
*
Added deprecation for the
`:dependent => :restrict`
association option.
Please note:
* Up until now `has_many` and `has_one`, `:dependent => :restrict`
option raised a `DeleteRestrictionError` at the time of destroying
the object. Instead, it will add an error on the model.
* To fix this warning, make sure your code isn't relying on a
`DeleteRestrictionError` and then add
`config.active_record.dependent_restrict_raises = false` to your
application config.
* New rails application would be generated with the
`config.active_record.dependent_restrict_raises = false` in the
application config.
*Manoj Kumar*
*
Added
`create_join_table`
migration helper to create HABTM join tables
create_join_table :products, :categories
...
...
activerecord/lib/active_record/associations.rb
浏览文件 @
30a23280
...
...
@@ -1097,8 +1097,8 @@ module ClassMethods
# alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated
# objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
# objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to
# <tt>:restrict</tt>
this object raises an <tt>ActiveRecord::DeleteRestrictionError</tt> exception and
#
cannot be deleted if it has any associated objects
.
# <tt>:restrict</tt>
an error will be added to the object, preventing its deletion, if any associated
#
objects are present
.
#
# If using with the <tt>:through</tt> option, the association on the join model must be
# a +belongs_to+, and the records which get deleted are the join records, rather than
...
...
@@ -1251,8 +1251,8 @@ def has_many(name, options = {}, &extension)
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
# If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+.
#
Also, association is assigned. If set to <tt>:restrict</tt> this object raises
an
#
<tt>ActiveRecord::DeleteRestrictionError</tt> exception and cannot be deleted if it has any associated objec
t.
#
If set to <tt>:restrict</tt>, an error will be added to the object, preventing its deletion, if
an
#
associated object is presen
t.
# [:foreign_key]
# Specify the foreign key used for the association. By default this is guessed to be the name
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
...
...
activerecord/lib/active_record/associations/builder/association.rb
浏览文件 @
30a23280
...
...
@@ -51,5 +51,34 @@ def define_writers
association
(
name
).
writer
(
value
)
end
end
end
def
dependent_restrict_raises?
ActiveRecord
::
Base
.
dependent_restrict_raises
==
true
end
def
dependent_restrict_deprecation_warning
if
dependent_restrict_raises?
msg
=
"In the next release, `:dependent => :restrict` will not raise a `DeleteRestrictionError`."
\
"Instead, it will add an error on the model. To fix this warning, make sure your code"
\
"isn't relying on a `DeleteRestrictionError` and then add"
\
"`config.active_record.dependent_restrict_raises = false` to your application config."
ActiveSupport
::
Deprecation
.
warn
msg
end
end
def
define_restrict_dependency_method
name
=
self
.
name
mixin
.
redefine_method
(
dependency_method_name
)
do
# has_many or has_one associations
if
send
(
name
).
respond_to?
(
:exists?
)
?
send
(
name
).
exists?
:
!
send
(
name
).
nil?
if
dependent_restrict_raises?
raise
ActiveRecord
::
DeleteRestrictionError
.
new
(
name
)
else
errors
.
add
(
:base
,
:restrict_dependent_destroy
,
:model
=>
name
.
to_s
.
singularize
)
return
false
end
end
end
end
end
end
activerecord/lib/active_record/associations/builder/has_many.rb
浏览文件 @
30a23280
...
...
@@ -21,6 +21,7 @@ def configure_dependency
":nullify or :restrict (
#{
options
[
:dependent
].
inspect
}
)"
end
dependent_restrict_deprecation_warning
if
options
[
:dependent
]
==
:restrict
send
(
"define_
#{
options
[
:dependent
]
}
_dependency_method"
)
model
.
before_destroy
dependency_method_name
end
...
...
@@ -52,13 +53,6 @@ def define_nullify_dependency_method
end
end
def
define_restrict_dependency_method
name
=
self
.
name
mixin
.
redefine_method
(
dependency_method_name
)
do
raise
ActiveRecord
::
DeleteRestrictionError
.
new
(
name
)
unless
send
(
name
).
empty?
end
end
def
dependency_method_name
"has_many_dependent_for_
#{
name
}
"
end
...
...
activerecord/lib/active_record/associations/builder/has_one.rb
浏览文件 @
30a23280
...
...
@@ -34,15 +34,12 @@ def configure_dependency
":nullify or :restrict (
#{
options
[
:dependent
].
inspect
}
)"
end
dependent_restrict_deprecation_warning
if
options
[
:dependent
]
==
:restrict
send
(
"define_
#{
options
[
:dependent
]
}
_dependency_method"
)
model
.
before_destroy
dependency_method_name
end
end
def
dependency_method_name
"has_one_dependent_
#{
options
[
:dependent
]
}
_for_
#{
name
}
"
end
def
define_destroy_dependency_method
name
=
self
.
name
mixin
.
redefine_method
(
dependency_method_name
)
do
...
...
@@ -52,11 +49,8 @@ def define_destroy_dependency_method
alias
:define_delete_dependency_method
:define_destroy_dependency_method
alias
:define_nullify_dependency_method
:define_destroy_dependency_method
def
define_restrict_dependency_method
name
=
self
.
name
mixin
.
redefine_method
(
dependency_method_name
)
do
raise
ActiveRecord
::
DeleteRestrictionError
.
new
(
name
)
unless
send
(
name
).
nil?
end
def
dependency_method_name
"has_one_dependent_
#{
options
[
:dependent
]
}
_for_
#{
name
}
"
end
end
end
activerecord/lib/active_record/core.rb
浏览文件 @
30a23280
...
...
@@ -72,6 +72,16 @@ module Core
# The connection handler
config_attribute
:connection_handler
self
.
connection_handler
=
ConnectionAdapters
::
ConnectionHandler
.
new
##
# :singleton-method:
# Specifies wether or not has_many or has_one association option
# :dependent => :restrict raises an exception. If set to true, the
# ActiveRecord::DeleteRestrictionError exception will be raised
# along with a DEPRECATION WARNING. If set to false, an error would
# be added to the model instead.
config_attribute
:dependent_restrict_raises
,
:global
=>
true
self
.
dependent_restrict_raises
=
true
end
module
ClassMethods
...
...
activerecord/lib/active_record/locale/en.yml
浏览文件 @
30a23280
...
...
@@ -10,6 +10,7 @@ en:
messages
:
taken
:
"
has
already
been
taken"
record_invalid
:
"
Validation
failed:
%{errors}"
restrict_dependent_destroy
:
"
Cannot
delete
record
because
dependent
%{model}
exists"
# Append your own errors here or at the model/attributes scope.
# You can define own errors for models or model attributes.
...
...
activerecord/test/cases/associations/has_many_associations_test.rb
浏览文件 @
30a23280
...
...
@@ -1140,16 +1140,41 @@ def test_depends_and_nullify
assert_nil
companies
(
:leetsoft
).
reload
.
client_of
assert_nil
companies
(
:jadedpixel
).
reload
.
client_of
assert_equal
num_accounts
,
Account
.
count
end
def
test_restrict
firm
=
RestrictedFirm
.
new
(
:name
=>
'restrict'
)
firm
.
save!
# ActiveRecord::Base.dependent_restrict_raises = true, by default
firm
=
RestrictedFirm
.
create!
(
:name
=>
'restrict'
)
firm
.
companies
.
create
(
:name
=>
'child'
)
assert
!
firm
.
companies
.
empty?
assert_raise
(
ActiveRecord
::
DeleteRestrictionError
)
{
firm
.
destroy
}
assert
RestrictedFirm
.
exists?
(
:name
=>
'restrict'
)
assert
firm
.
companies
.
exists?
(
:name
=>
'child'
)
end
def
test_restrict_when_dependent_restrict_raises_config_set_to_false
# ActiveRecord::Base.dependent_restrict_raises = true, by default
ActiveRecord
::
Base
.
dependent_restrict_raises
=
false
# add an error on the model instead of raising ActiveRecord::DeleteRestrictionError
firm
=
RestrictedFirm
.
create!
(
:name
=>
'restrict'
)
firm
.
companies
.
create
(
:name
=>
'child'
)
assert
!
firm
.
companies
.
empty?
firm
.
destroy
assert
!
firm
.
errors
.
empty?
assert_equal
"Cannot delete record because dependent company exists"
,
firm
.
errors
[
:base
].
first
assert
RestrictedFirm
.
exists?
(
:name
=>
'restrict'
)
assert
firm
.
companies
.
exists?
(
:name
=>
'child'
)
ensure
ActiveRecord
::
Base
.
dependent_restrict_raises
=
true
end
def
test_included_in_collection
...
...
@@ -1401,29 +1426,29 @@ def test_calling_first_or_last_on_new_record_should_not_run_queries
firm
.
clients
.
last
end
end
def
test_custom_primary_key_on_new_record_should_fetch_with_query
author
=
Author
.
new
(
:name
=>
"David"
)
assert
!
author
.
essays
.
loaded?
assert_queries
1
do
assert_queries
1
do
assert_equal
1
,
author
.
essays
.
size
end
assert_equal
author
.
essays
,
Essay
.
find_all_by_writer_id
(
"David"
)
end
def
test_has_many_custom_primary_key
david
=
authors
(
:david
)
assert_equal
david
.
essays
,
Essay
.
find_all_by_writer_id
(
"David"
)
end
def
test_blank_custom_primary_key_on_new_record_should_not_run_queries
author
=
Author
.
new
assert
!
author
.
essays
.
loaded?
assert_queries
0
do
assert_queries
0
do
assert_equal
0
,
author
.
essays
.
size
end
end
...
...
@@ -1649,4 +1674,11 @@ def test_replace
assert_equal
[
bulb2
],
car
.
bulbs
assert_equal
[
bulb2
],
car
.
reload
.
bulbs
end
def
test_building_has_many_association_with_restrict_dependency
klass
=
Class
.
new
(
ActiveRecord
::
Base
)
assert_deprecated
{
klass
.
has_many
:companies
,
:dependent
=>
:restrict
}
assert_not_deprecated
{
klass
.
has_many
:companies
}
end
end
activerecord/test/cases/associations/has_one_associations_test.rb
浏览文件 @
30a23280
...
...
@@ -157,11 +157,37 @@ def test_dependence_with_nil_associate
end
def
test_dependence_with_restrict
firm
=
RestrictedFirm
.
new
(
:name
=>
'restrict'
)
firm
.
save!
# ActiveRecord::Base.dependent_restrict_raises = true, by default
firm
=
RestrictedFirm
.
create!
(
:name
=>
'restrict'
)
firm
.
create_account
(
:credit_limit
=>
10
)
assert_not_nil
firm
.
account
assert_raise
(
ActiveRecord
::
DeleteRestrictionError
)
{
firm
.
destroy
}
assert
RestrictedFirm
.
exists?
(
:name
=>
'restrict'
)
assert
firm
.
account
.
present?
end
def
test_dependence_with_restrict_with_dependent_restrict_raises_config_set_to_false
# ActiveRecord::Base.dependent_restrict_raises = true, by default
ActiveRecord
::
Base
.
dependent_restrict_raises
=
false
# adds an error on the model instead of raising ActiveRecord::DeleteRestrictionError
firm
=
RestrictedFirm
.
create!
(
:name
=>
'restrict'
)
firm
.
create_account
(
:credit_limit
=>
10
)
assert_not_nil
firm
.
account
firm
.
destroy
assert
!
firm
.
errors
.
empty?
assert_equal
"Cannot delete record because dependent account exists"
,
firm
.
errors
[
:base
].
first
assert
RestrictedFirm
.
exists?
(
:name
=>
'restrict'
)
assert
firm
.
account
.
present?
ensure
ActiveRecord
::
Base
.
dependent_restrict_raises
=
true
end
def
test_successful_build_association
...
...
@@ -456,4 +482,11 @@ def test_association_attributes_are_available_to_after_initialize
assert_equal
car
.
id
,
bulb
.
attributes_after_initialize
[
'car_id'
]
end
def
test_building_has_one_association_with_dependent_restrict
klass
=
Class
.
new
(
ActiveRecord
::
Base
)
assert_deprecated
{
klass
.
has_one
:account
,
:dependent
=>
:restrict
}
assert_not_deprecated
{
klass
.
has_one
:account
}
end
end
railties/lib/rails/generators/rails/app/templates/config/application.rb
浏览文件 @
30a23280
...
...
@@ -56,6 +56,11 @@ class Application < Rails::Application
# parameters by using an attr_accessible or attr_protected declaration.
# config.active_record.whitelist_attributes = true
# Specifies wether or not has_many or has_one association option :dependent => :restrict raises
# an exception. If set to true, then an ActiveRecord::DeleteRestrictionError exception would be
# raised. If set to false, then an error will be added on the model instead.
config
.
active_record
.
dependent_restrict_raises
=
false
<
% unless
options
.
skip_sprockets?
-
%>
# Enable the asset pipeline.
config.assets.enabled = true
...
...
railties/test/generators/app_generator_test.rb
浏览文件 @
30a23280
...
...
@@ -349,6 +349,11 @@ def test_generated_environments_file_for_auto_explain
end
end
def
test_active_record_dependent_restrict_raises_is_present_application_config
run_generator
assert_file
"config/application.rb"
,
/config\.active_record\.dependent_restrict_raises = false/
end
protected
def
action
(
*
args
,
&
block
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录