Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
031588eb
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,发现更多精彩内容 >>
提交
031588eb
编写于
6月 26, 2014
作者:
R
Rafael Mendonça França
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #15754 from sgrif/sg-deprecate-hmt-counter-cache
Deprecate automatic counter caches on has_many :through
上级
e8003c72
d730e374
变更
16
显示空白变更内容
内联
并排
Showing
16 changed file
with
93 addition
and
36 deletion
+93
-36
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+5
-0
activerecord/lib/active_record/associations/has_many_association.rb
...rd/lib/active_record/associations/has_many_association.rb
+9
-1
activerecord/lib/active_record/associations/has_many_through_association.rb
...ctive_record/associations/has_many_through_association.rb
+14
-0
activerecord/test/cases/associations/belongs_to_associations_test.rb
...d/test/cases/associations/belongs_to_associations_test.rb
+2
-2
activerecord/test/cases/associations/cascaded_eager_loading_test.rb
...rd/test/cases/associations/cascaded_eager_loading_test.rb
+2
-2
activerecord/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb
...ions/deprecated_counter_cache_on_has_many_through_test.rb
+26
-0
activerecord/test/cases/associations/has_many_associations_test.rb
...ord/test/cases/associations/has_many_associations_test.rb
+4
-4
activerecord/test/cases/associations/has_many_through_associations_test.rb
.../cases/associations/has_many_through_associations_test.rb
+5
-5
activerecord/test/cases/associations/join_model_test.rb
activerecord/test/cases/associations/join_model_test.rb
+13
-12
activerecord/test/cases/connection_adapters/schema_cache_test.rb
...ecord/test/cases/connection_adapters/schema_cache_test.rb
+2
-2
activerecord/test/cases/finder_test.rb
activerecord/test/cases/finder_test.rb
+2
-2
activerecord/test/fixtures/posts.yml
activerecord/test/fixtures/posts.yml
+0
-2
activerecord/test/models/post.rb
activerecord/test/models/post.rb
+1
-1
activerecord/test/models/tagging.rb
activerecord/test/models/tagging.rb
+1
-1
activerecord/test/schema/schema.rb
activerecord/test/schema/schema.rb
+1
-2
guides/source/4_2_release_notes.md
guides/source/4_2_release_notes.md
+6
-0
未找到文件。
activerecord/CHANGELOG.md
浏览文件 @
031588eb
*
Deprecate automatic counter caches on
`has_many :through`
. The behavior was
broken and inconsistent.
*Sean Griffin*
*
`preload`
preserves readonly flag for associations.
See #15853.
...
...
activerecord/lib/active_record/associations/has_many_association.rb
浏览文件 @
031588eb
...
...
@@ -80,10 +80,14 @@ def cached_counter_attribute_name(reflection = reflection())
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
has_cached_counter?
(
reflection
)
counter
=
cached_counter_attribute_name
(
reflection
)
owner
.
class
.
update_counters
(
owner
.
id
,
counter
=>
difference
)
update_counter_in_memory
(
difference
,
reflection
)
end
end
...
...
@@ -107,6 +111,10 @@ def update_counter_in_memory(difference, reflection = reflection())
# Hence this method.
def
inverse_updates_counter_cache?
(
reflection
=
reflection
())
counter_name
=
cached_counter_attribute_name
(
reflection
)
inverse_updates_counter_named?
(
counter_name
,
reflection
)
end
def
inverse_updates_counter_named?
(
counter_name
,
reflection
=
reflection
())
reflection
.
klass
.
_reflections
.
values
.
any?
{
|
inverse_reflection
|
:belongs_to
==
inverse_reflection
.
macro
&&
inverse_reflection
.
counter_cache_column
==
counter_name
...
...
activerecord/lib/active_record/associations/has_many_through_association.rb
浏览文件 @
031588eb
...
...
@@ -63,6 +63,15 @@ def insert_record(record, validate = true, raise = false)
end
save_through_record
(
record
)
if
has_cached_counter?
&&
!
through_reflection_updates_counter_cache?
ActiveSupport
::
Deprecation
.
warn
(
<<-
MESSAGE
.
strip_heredoc
)
Automatic updating of counter caches on through associations has been
deprecated, and will be removed in Rails 5.0. Instead, please set the
appropriate counter_cache options on the has_many and belongs_to for
your associations to
#{
through_reflection
.
name
}
.
MESSAGE
update_counter_in_database
(
1
)
end
record
end
...
...
@@ -217,6 +226,11 @@ def find_target
def
invertible_for?
(
record
)
false
end
def
through_reflection_updates_counter_cache?
counter_name
=
cached_counter_attribute_name
inverse_updates_counter_named?
(
counter_name
,
through_reflection
)
end
end
end
end
activerecord/test/cases/associations/belongs_to_associations_test.rb
浏览文件 @
031588eb
...
...
@@ -787,8 +787,8 @@ def test_polymorphic_counter_cache
post
=
posts
(
:welcome
)
comment
=
comments
(
:greetings
)
assert_difference
lambda
{
post
.
reload
.
tag
ging
s_count
},
-
1
do
assert_difference
'comment.reload.tag
ging
s_count'
,
+
1
do
assert_difference
lambda
{
post
.
reload
.
tags_count
},
-
1
do
assert_difference
'comment.reload.tags_count'
,
+
1
do
tagging
.
taggable
=
comment
end
end
...
...
activerecord/test/cases/associations/cascaded_eager_loading_test.rb
浏览文件 @
031588eb
...
...
@@ -35,9 +35,9 @@ def test_eager_association_loading_with_cascaded_two_levels_and_one_level
def
test_eager_association_loading_with_hmt_does_not_table_name_collide_when_joining_associations
assert_nothing_raised
do
Author
.
joins
(
:posts
).
eager_load
(
:comments
).
where
(
:posts
=>
{
:tag
ging
s_count
=>
1
}).
to_a
Author
.
joins
(
:posts
).
eager_load
(
:comments
).
where
(
:posts
=>
{
:tags_count
=>
1
}).
to_a
end
authors
=
Author
.
joins
(
:posts
).
eager_load
(
:comments
).
where
(
:posts
=>
{
:tag
ging
s_count
=>
1
}).
to_a
authors
=
Author
.
joins
(
:posts
).
eager_load
(
:comments
).
where
(
:posts
=>
{
:tags_count
=>
1
}).
to_a
assert_equal
1
,
assert_no_queries
{
authors
.
size
}
assert_equal
10
,
assert_no_queries
{
authors
[
0
].
comments
.
size
}
end
...
...
activerecord/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb
0 → 100644
浏览文件 @
031588eb
require
"cases/helper"
class
DeprecatedCounterCacheOnHasManyThroughTest
<
ActiveRecord
::
TestCase
class
Post
<
ActiveRecord
::
Base
has_many
:taggings
,
as: :taggable
has_many
:tags
,
through: :taggings
end
class
Tagging
<
ActiveRecord
::
Base
belongs_to
:taggable
,
polymorphic:
true
belongs_to
:tag
end
class
Tag
<
ActiveRecord
::
Base
end
test
"counter caches are updated in the database if the belongs_to association doesn't specify a counter cache"
do
post
=
Post
.
create!
(
title:
'Hello'
,
body:
'World!'
)
assert_deprecated
{
post
.
tags
<<
Tag
.
create!
(
name:
'whatever'
)
}
assert_equal
1
,
post
.
tags
.
size
assert_equal
1
,
post
.
tags_count
assert_equal
1
,
post
.
reload
.
tags
.
size
assert_equal
1
,
post
.
reload
.
tags_count
end
end
activerecord/test/cases/associations/has_many_associations_test.rb
浏览文件 @
031588eb
...
...
@@ -36,7 +36,7 @@ def test_should_generate_valid_sql
author
=
authors
(
:david
)
# this can fail on adapters which require ORDER BY expressions to be included in the SELECT expression
# if the reorder clauses are not correctly handled
assert
author
.
posts_with_comments_sorted_by_comment_id
.
where
(
'comments.id > 0'
).
reorder
(
'posts.comments_count DESC'
,
'posts.tag
ging
s_count DESC'
).
last
assert
author
.
posts_with_comments_sorted_by_comment_id
.
where
(
'comments.id > 0'
).
reorder
(
'posts.comments_count DESC'
,
'posts.tags_count DESC'
).
last
end
end
...
...
@@ -814,14 +814,14 @@ def test_pushing_association_updates_counter_cache
def
test_deleting_updates_counter_cache_without_dependent_option
post
=
posts
(
:welcome
)
assert_difference
"post.reload.tag
ging
s_count"
,
-
1
do
assert_difference
"post.reload.tags_count"
,
-
1
do
post
.
taggings
.
delete
(
post
.
taggings
.
first
)
end
end
def
test_deleting_updates_counter_cache_with_dependent_delete_all
post
=
posts
(
:welcome
)
post
.
update_columns
(
taggings_with_delete_all_count:
post
.
tag
ging
s_count
)
post
.
update_columns
(
taggings_with_delete_all_count:
post
.
tags_count
)
assert_difference
"post.reload.taggings_with_delete_all_count"
,
-
1
do
post
.
taggings_with_delete_all
.
delete
(
post
.
taggings_with_delete_all
.
first
)
...
...
@@ -830,7 +830,7 @@ def test_deleting_updates_counter_cache_with_dependent_delete_all
def
test_deleting_updates_counter_cache_with_dependent_destroy
post
=
posts
(
:welcome
)
post
.
update_columns
(
taggings_with_destroy_count:
post
.
tag
ging
s_count
)
post
.
update_columns
(
taggings_with_destroy_count:
post
.
tags_count
)
assert_difference
"post.reload.taggings_with_destroy_count"
,
-
1
do
post
.
taggings_with_destroy
.
delete
(
post
.
taggings_with_destroy
.
first
)
...
...
activerecord/test/cases/associations/has_many_through_associations_test.rb
浏览文件 @
031588eb
...
...
@@ -489,7 +489,7 @@ def test_update_counter_caches_on_delete
post
=
posts
(
:welcome
)
tag
=
post
.
tags
.
create!
(
:name
=>
'doomed'
)
assert_difference
[
'post.reload.tag
gings_count'
,
'post.reload.tag
s_count'
],
-
1
do
assert_difference
[
'post.reload.tags_count'
],
-
1
do
posts
(
:welcome
).
tags
.
delete
(
tag
)
end
end
...
...
@@ -499,7 +499,7 @@ def test_update_counter_caches_on_delete_with_dependent_destroy
tag
=
post
.
tags
.
create!
(
:name
=>
'doomed'
)
post
.
update_columns
(
tags_with_destroy_count:
post
.
tags
.
count
)
assert_difference
[
'post.reload.tag
gings_count'
,
'post.reload.tag
s_with_destroy_count'
],
-
1
do
assert_difference
[
'post.reload.tags_with_destroy_count'
],
-
1
do
posts
(
:welcome
).
tags_with_destroy
.
delete
(
tag
)
end
end
...
...
@@ -509,7 +509,7 @@ def test_update_counter_caches_on_delete_with_dependent_nullify
tag
=
post
.
tags
.
create!
(
:name
=>
'doomed'
)
post
.
update_columns
(
tags_with_nullify_count:
post
.
tags
.
count
)
assert_no_difference
'post.reload.tag
ging
s_count'
do
assert_no_difference
'post.reload.tags_count'
do
assert_difference
'post.reload.tags_with_nullify_count'
,
-
1
do
posts
(
:welcome
).
tags_with_nullify
.
delete
(
tag
)
end
...
...
@@ -524,14 +524,14 @@ def test_update_counter_caches_on_replace_association
tag
.
tagged_posts
=
[]
post
.
reload
assert_equal
(
post
.
taggings
.
count
,
post
.
tag
ging
s_count
)
assert_equal
(
post
.
taggings
.
count
,
post
.
tags_count
)
end
def
test_update_counter_caches_on_destroy
post
=
posts
(
:welcome
)
tag
=
post
.
tags
.
create!
(
name:
'doomed'
)
assert_difference
'post.reload.tag
ging
s_count'
,
-
1
do
assert_difference
'post.reload.tags_count'
,
-
1
do
tag
.
tagged_posts
.
destroy
(
post
)
end
end
...
...
activerecord/test/cases/associations/join_model_test.rb
浏览文件 @
031588eb
...
...
@@ -326,11 +326,11 @@ def test_has_many_through_with_custom_primary_key_on_has_many_source
end
def
test_belongs_to_polymorphic_with_counter_cache
assert_equal
1
,
posts
(
:welcome
)[
:tag
ging
s_count
]
assert_equal
1
,
posts
(
:welcome
)[
:tags_count
]
tagging
=
posts
(
:welcome
).
taggings
.
create
(
:tag
=>
tags
(
:general
))
assert_equal
2
,
posts
(
:welcome
,
:reload
)[
:tag
ging
s_count
]
assert_equal
2
,
posts
(
:welcome
,
:reload
)[
:tags_count
]
tagging
.
destroy
assert_equal
1
,
posts
(
:welcome
,
:reload
)[
:tag
ging
s_count
]
assert_equal
1
,
posts
(
:welcome
,
:reload
)[
:tags_count
]
end
def
test_unavailable_through_reflection
...
...
@@ -489,7 +489,7 @@ def test_create_associate_when_adding_to_has_many_through
message
=
"Expected a Tag in tags collection, got
#{
wrong
.
class
}
."
)
assert_nil
(
wrong
=
post_thinking
.
taggings
.
detect
{
|
t
|
t
.
class
!=
Tagging
},
message
=
"Expected a Tagging in taggings collection, got
#{
wrong
.
class
}
."
)
assert_equal
(
count
+
1
,
post_thinking
.
tags
.
size
)
assert_equal
(
count
+
1
,
post_thinking
.
reload
.
tags
.
size
)
assert_equal
(
count
+
1
,
post_thinking
.
tags
(
true
).
size
)
assert_kind_of
Tag
,
post_thinking
.
tags
.
create!
(
:name
=>
'foo'
)
...
...
@@ -497,7 +497,7 @@ def test_create_associate_when_adding_to_has_many_through
message
=
"Expected a Tag in tags collection, got
#{
wrong
.
class
}
."
)
assert_nil
(
wrong
=
post_thinking
.
taggings
.
detect
{
|
t
|
t
.
class
!=
Tagging
},
message
=
"Expected a Tagging in taggings collection, got
#{
wrong
.
class
}
."
)
assert_equal
(
count
+
2
,
post_thinking
.
tags
.
size
)
assert_equal
(
count
+
2
,
post_thinking
.
reload
.
tags
.
size
)
assert_equal
(
count
+
2
,
post_thinking
.
tags
(
true
).
size
)
assert_nothing_raised
{
post_thinking
.
tags
.
concat
(
Tag
.
create!
(
:name
=>
'abc'
),
Tag
.
create!
(
:name
=>
'def'
))
}
...
...
@@ -505,7 +505,7 @@ def test_create_associate_when_adding_to_has_many_through
message
=
"Expected a Tag in tags collection, got
#{
wrong
.
class
}
."
)
assert_nil
(
wrong
=
post_thinking
.
taggings
.
detect
{
|
t
|
t
.
class
!=
Tagging
},
message
=
"Expected a Tagging in taggings collection, got
#{
wrong
.
class
}
."
)
assert_equal
(
count
+
4
,
post_thinking
.
tags
.
size
)
assert_equal
(
count
+
4
,
post_thinking
.
reload
.
tags
.
size
)
assert_equal
(
count
+
4
,
post_thinking
.
tags
(
true
).
size
)
# Raises if the wrong reflection name is used to set the Edge belongs_to
...
...
@@ -554,34 +554,35 @@ def test_delete_associate_when_deleting_from_has_many_through_with_nonstandard_i
def
test_delete_associate_when_deleting_from_has_many_through
count
=
posts
(
:thinking
).
tags
.
count
tags_before
=
posts
(
:thinking
).
tags
tags_before
=
posts
(
:thinking
).
tags
.
sort
tag
=
Tag
.
create!
(
:name
=>
'doomed'
)
post_thinking
=
posts
(
:thinking
)
post_thinking
.
tags
<<
tag
assert_equal
(
count
+
1
,
post_thinking
.
taggings
(
true
).
size
)
assert_equal
(
count
+
1
,
post_thinking
.
tags
(
true
).
size
)
assert_equal
(
count
+
1
,
post_thinking
.
reload
.
tags
(
true
).
size
)
assert_not_equal
(
tags_before
,
post_thinking
.
tags
.
sort
)
assert_nothing_raised
{
post_thinking
.
tags
.
delete
(
tag
)
}
assert_equal
(
count
,
post_thinking
.
tags
.
size
)
assert_equal
(
count
,
post_thinking
.
tags
(
true
).
size
)
assert_equal
(
count
,
post_thinking
.
taggings
(
true
).
size
)
assert_equal
(
tags_before
.
sort
,
post_thinking
.
tags
.
sort
)
assert_equal
(
tags_before
,
post_thinking
.
tags
.
sort
)
end
def
test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
count
=
posts
(
:thinking
).
tags
.
count
tags_before
=
posts
(
:thinking
).
tags
tags_before
=
posts
(
:thinking
).
tags
.
sort
doomed
=
Tag
.
create!
(
:name
=>
'doomed'
)
doomed2
=
Tag
.
create!
(
:name
=>
'doomed2'
)
quaked
=
Tag
.
create!
(
:name
=>
'quaked'
)
post_thinking
=
posts
(
:thinking
)
post_thinking
.
tags
<<
doomed
<<
doomed2
assert_equal
(
count
+
2
,
post_thinking
.
tags
(
true
).
size
)
assert_equal
(
count
+
2
,
post_thinking
.
reload
.
tags
(
true
).
size
)
assert_nothing_raised
{
post_thinking
.
tags
.
delete
(
doomed
,
doomed2
,
quaked
)
}
assert_equal
(
count
,
post_thinking
.
tags
.
size
)
assert_equal
(
count
,
post_thinking
.
tags
(
true
).
size
)
assert_equal
(
tags_before
.
sort
,
post_thinking
.
tags
.
sort
)
assert_equal
(
tags_before
,
post_thinking
.
tags
.
sort
)
end
def
test_deleting_junk_from_has_many_through_should_raise_type_mismatch
...
...
activerecord/test/cases/connection_adapters/schema_cache_test.rb
浏览文件 @
031588eb
...
...
@@ -45,8 +45,8 @@ def test_dump_and_load
@cache
=
Marshal
.
load
(
Marshal
.
dump
(
@cache
))
assert_equal
1
2
,
@cache
.
columns
(
'posts'
).
size
assert_equal
1
2
,
@cache
.
columns_hash
(
'posts'
).
size
assert_equal
1
1
,
@cache
.
columns
(
'posts'
).
size
assert_equal
1
1
,
@cache
.
columns_hash
(
'posts'
).
size
assert
@cache
.
tables
(
'posts'
)
assert_equal
'id'
,
@cache
.
primary_keys
(
'posts'
)
end
...
...
activerecord/test/cases/finder_test.rb
浏览文件 @
031588eb
...
...
@@ -144,8 +144,8 @@ def test_exists_with_distinct_association_includes_and_limit
def
test_exists_with_distinct_association_includes_limit_and_order
author
=
Author
.
first
assert_equal
false
,
author
.
unique_categorized_posts
.
includes
(
:special_comments
).
order
(
'comments.tag
ging
s_count DESC'
).
limit
(
0
).
exists?
assert_equal
true
,
author
.
unique_categorized_posts
.
includes
(
:special_comments
).
order
(
'comments.tag
ging
s_count DESC'
).
limit
(
1
).
exists?
assert_equal
false
,
author
.
unique_categorized_posts
.
includes
(
:special_comments
).
order
(
'comments.tags_count DESC'
).
limit
(
0
).
exists?
assert_equal
true
,
author
.
unique_categorized_posts
.
includes
(
:special_comments
).
order
(
'comments.tags_count DESC'
).
limit
(
1
).
exists?
end
def
test_exists_with_empty_table_and_no_args_given
...
...
activerecord/test/fixtures/posts.yml
浏览文件 @
031588eb
...
...
@@ -4,7 +4,6 @@ welcome:
title
:
Welcome to the weblog
body
:
Such a lovely day
comments_count
:
2
taggings_count
:
1
tags_count
:
1
type
:
Post
...
...
@@ -14,7 +13,6 @@ thinking:
title
:
So I was thinking
body
:
Like I hopefully always am
comments_count
:
1
taggings_count
:
1
tags_count
:
1
type
:
SpecialPost
...
...
activerecord/test/models/post.rb
浏览文件 @
031588eb
...
...
@@ -88,7 +88,7 @@ def greeting
has_and_belongs_to_many
:categories
has_and_belongs_to_many
:special_categories
,
:join_table
=>
"categories_posts"
,
:association_foreign_key
=>
'category_id'
has_many
:taggings
,
:as
=>
:taggable
has_many
:taggings
,
:as
=>
:taggable
,
:counter_cache
=>
:tags_count
has_many
:tags
,
:through
=>
:taggings
do
def
add_joins_and_select
select
(
'tags.*, authors.id as author_id'
)
...
...
activerecord/test/models/tagging.rb
浏览文件 @
031588eb
...
...
@@ -8,6 +8,6 @@ class Tagging < ActiveRecord::Base
belongs_to
:invalid_tag
,
:class_name
=>
'Tag'
,
:foreign_key
=>
'tag_id'
belongs_to
:blue_tag
,
->
{
where
:tags
=>
{
:name
=>
'Blue'
}
},
:class_name
=>
'Tag'
,
:foreign_key
=>
:tag_id
belongs_to
:tag_with_primary_key
,
:class_name
=>
'Tag'
,
:foreign_key
=>
:tag_id
,
:primary_key
=>
:custom_primary_key
belongs_to
:taggable
,
:polymorphic
=>
true
,
:counter_cache
=>
true
belongs_to
:taggable
,
:polymorphic
=>
true
,
:counter_cache
=>
:tags_count
has_many
:things
,
:through
=>
:taggable
end
activerecord/test/schema/schema.rb
浏览文件 @
031588eb
...
...
@@ -190,7 +190,7 @@ def except(adapter_names_to_exclude)
t
.
text
:body
,
null:
false
end
t
.
string
:type
t
.
integer
:tag
ging
s_count
,
default:
0
t
.
integer
:tags_count
,
default:
0
t
.
integer
:children_count
,
default:
0
t
.
integer
:parent_id
t
.
references
:author
,
polymorphic:
true
...
...
@@ -569,7 +569,6 @@ def except(adapter_names_to_exclude)
end
t
.
string
:type
t
.
integer
:comments_count
,
default:
0
t
.
integer
:taggings_count
,
default:
0
t
.
integer
:taggings_with_delete_all_count
,
default:
0
t
.
integer
:taggings_with_destroy_count
,
default:
0
t
.
integer
:tags_count
,
default:
0
...
...
guides/source/4_2_release_notes.md
浏览文件 @
031588eb
...
...
@@ -201,6 +201,12 @@ for detailed changes.
(
[
Commit
](
https://github.com/rails/rails/commit/91949e48cf41af9f3e4ffba3e5eecf9b0a08bfc3
)
)
*
Deprecated broken support for automatic detection of counter caches on
`has_many :through`
associations. You should instead manually specify the
counter cache on the
`has_many`
and
`belongs_to`
associations for the through
records.
(
[
Pull Request
](
https://github.com/rails/rails/pull/15754
)
)
### Notable changes
*
Added support for
`#pretty_print`
in
`ActiveRecord::Base`
objects.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录