Rails dup 和 clone 方法有什么区别?
What's the difference between Rails dup and clone methods?
我需要知道 Rails dup 和 clone 方法的区别,因为 dup 复制了 id 属性而 clone 没有:
juan:~/alhambra$ rails c
Loading development environment (Rails 3.0.1)
1.9.3-p551 :001 > @user=User.last
=> #<User id: 2, email: "ferbad12@hotmail.com", encrypted_password: "a$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "a$/Fsz8DZ9PQbReTU1.wyxS.", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-05-06 23:34:20", last_sign_in_at: "2015-05-06 23:34:20", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-05-06 23:33:37", updated_at: "2015-05-06 23:34:20">
1.9.3-p551 :002 > @user.clone
=> #<User id: nil, email: "ferbad12@hotmail.com", encrypted_password: "a$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "a$/Fsz8DZ9PQbReTU1.wyxS.", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-05-06 23:34:20", last_sign_in_at: "2015-05-06 23:34:20", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-05-06 23:33:37", updated_at: "2015-05-06 23:34:20">
1.9.3-p551 :003 > @user.dup
=> #<User id: 2, email: "ferbad12@hotmail.com", encrypted_password: "a$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "a$/Fsz8DZ9PQbReTU1.wyxS.", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-05-06 23:34:20", last_sign_in_at: "2015-05-06 23:34:20", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-05-06 23:33:37", updated_at: "2015-05-06 23:34:20">
在 rails 3.0 中,dup
和 clone
所扮演的角色与现在的角色完全相反。来自 ActiveRecord::Base:
Cloned objects have no id assigned and are treated as new records. Note that this is a "shallow" clone as it copies the object's attributes only, not its associations. The extent of a "deep" clone is application specific and is therefore left to the application to implement according to its need.
While it can be seen in the same file 即dup
简单复制了记录及其属性:
def dup
obj = super
obj.instance_variable_set('@attributes', @attributes.dup)
obj
end
这与当前的 rails 4 不同,后者定义 dup
和 clone
以更多地遵循 ruby docs, noted in a similar question not specific to rails.
中的注释
In general, clone and dup may have different semantics in descendent classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendent object to create the new instance.
从the more current ActiveRecord source可以看出:
##
# :method: clone
# Identical to Ruby's clone method. This is a "shallow" copy. Be
# warned that your attributes are not copied. That means that modifying
# attributes of the clone will modify the original, since they will both
# point to the same attributes hash. If you need a copy of your attributes
# hash, please use the #dup method.
#
# user = User.first
# new_user = user.clone
# user.name # => "Bob"
# new_user.name = "Joe"
# user.name # => "Joe"
#
# user.object_id == new_user.object_id # => false
# user.name.object_id == new_user.name.object_id # => true
#
# user.name.object_id == user.dup.name.object_id # => false
##
# :method: dup
# Duped objects have no id assigned and are treated as new records. Note
# that this is a "shallow" copy as it copies the object's attributes
# only, not its associations. The extent of a "deep" copy is application
# specific and is therefore left to the application to implement according
# to its need.
# The dup method does not preserve the timestamps (created|updated)_(at|on).
教程对此进行了解释,与我的控制台显示的相反
p1 = Post.create(title: 'Post 1', message: 'Amazing message')
p3 = p1.clone
p3.title = "This is now p3"
p1 #=> #<Post id: 1, title: "Post 1", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">
p3 #=> #<Post id: nil, title: "This is now P3", message: "Amazing message", created_at: nil, updated_at: nil>
我需要知道 Rails dup 和 clone 方法的区别,因为 dup 复制了 id 属性而 clone 没有:
juan:~/alhambra$ rails c
Loading development environment (Rails 3.0.1)
1.9.3-p551 :001 > @user=User.last
=> #<User id: 2, email: "ferbad12@hotmail.com", encrypted_password: "a$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "a$/Fsz8DZ9PQbReTU1.wyxS.", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-05-06 23:34:20", last_sign_in_at: "2015-05-06 23:34:20", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-05-06 23:33:37", updated_at: "2015-05-06 23:34:20">
1.9.3-p551 :002 > @user.clone
=> #<User id: nil, email: "ferbad12@hotmail.com", encrypted_password: "a$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "a$/Fsz8DZ9PQbReTU1.wyxS.", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-05-06 23:34:20", last_sign_in_at: "2015-05-06 23:34:20", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-05-06 23:33:37", updated_at: "2015-05-06 23:34:20">
1.9.3-p551 :003 > @user.dup
=> #<User id: 2, email: "ferbad12@hotmail.com", encrypted_password: "a$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "a$/Fsz8DZ9PQbReTU1.wyxS.", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 1, current_sign_in_at: "2015-05-06 23:34:20", last_sign_in_at: "2015-05-06 23:34:20", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "127.0.0.1", created_at: "2015-05-06 23:33:37", updated_at: "2015-05-06 23:34:20">
在 rails 3.0 中,dup
和 clone
所扮演的角色与现在的角色完全相反。来自 ActiveRecord::Base:
Cloned objects have no id assigned and are treated as new records. Note that this is a "shallow" clone as it copies the object's attributes only, not its associations. The extent of a "deep" clone is application specific and is therefore left to the application to implement according to its need.
While it can be seen in the same file 即dup
简单复制了记录及其属性:
def dup
obj = super
obj.instance_variable_set('@attributes', @attributes.dup)
obj
end
这与当前的 rails 4 不同,后者定义 dup
和 clone
以更多地遵循 ruby docs, noted in a similar question not specific to rails.
In general, clone and dup may have different semantics in descendent classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendent object to create the new instance.
从the more current ActiveRecord source可以看出:
##
# :method: clone
# Identical to Ruby's clone method. This is a "shallow" copy. Be
# warned that your attributes are not copied. That means that modifying
# attributes of the clone will modify the original, since they will both
# point to the same attributes hash. If you need a copy of your attributes
# hash, please use the #dup method.
#
# user = User.first
# new_user = user.clone
# user.name # => "Bob"
# new_user.name = "Joe"
# user.name # => "Joe"
#
# user.object_id == new_user.object_id # => false
# user.name.object_id == new_user.name.object_id # => true
#
# user.name.object_id == user.dup.name.object_id # => false
##
# :method: dup
# Duped objects have no id assigned and are treated as new records. Note
# that this is a "shallow" copy as it copies the object's attributes
# only, not its associations. The extent of a "deep" copy is application
# specific and is therefore left to the application to implement according
# to its need.
# The dup method does not preserve the timestamps (created|updated)_(at|on).
教程对此进行了解释,与我的控制台显示的相反
p1 = Post.create(title: 'Post 1', message: 'Amazing message')
p3 = p1.clone
p3.title = "This is now p3"
p1 #=> #<Post id: 1, title: "Post 1", message: "Amazing message", created_at: "2014-07-01 19:45:44", updated_at: "2014-07-01 19:45:44">
p3 #=> #<Post id: nil, title: "This is now P3", message: "Amazing message", created_at: nil, updated_at: nil>