【问题标题】:What's the difference between Rails dup and clone methods? [duplicate]Rails dup 和 clone 方法有什么区别? [复制]
【发布时间】:2015-07-17 09:11:45
【问题描述】:

我需要知道 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: "$2a$10$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "$2a$10$/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: "$2a$10$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "$2a$10$/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: "$2a$10$/Fsz8DZ9PQbReTU1.wyxS.m3IOxZSV3siKDrrtUJdupz...", password_salt: "$2a$10$/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"> 

【问题讨论】:

  • 关于它的好博文:jvanbaarsen.com/blog/2014/07/01/ruby-on-rails-dup-vs-clone; tl;dr:clone 将创建一个 ActiveRecord 对象,其更改会影响原始对象; dup 创建一个新的 ActiveRecord 对象(没有 id)。
  • @numbers1311407: The answer by jvalanen 是该线程中唯一相关的,因为大多数其他答案以及问题都是关于 Ruby,而不是 Rails/AR。
  • 我的控制台正在发生的事情。 Dup 正在复制 id,而 clone 正在复制 id
  • 正如@Amadan 所指出的,这不是重复的,但它也不仅仅是dupclone 的Rails 实现特有的问题。它询问为什么 dupclone 没有给出预期的结果,结果证明在 Rails 3 和 4 之间方法角色完全颠倒了。如果措辞稍有不同,这可能是一个足够常见的混淆原因,可以证明问题的存在。

标签: ruby-on-rails ruby ruby-on-rails-3


【解决方案1】:

在 rails 3.0 中,dupclone 所扮演的角色与他们现在所做的基本相反。来自ActiveRecord::Base

克隆的对象没有分配 id 并被视为新记录。请注意,这是一个“浅”克隆,因为它仅复制对象的属性,而不是其关联。 “深度”克隆的范围是特定于应用程序的,因此留给应用程序根据需要实现。

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 不同,后者定义了 dupclone 以更多地遵循 ruby docs 中的注释,在 similar question not specific to rails 中注明。

一般来说,clone 和 dup 在后代类中可能有不同的语义。虽然 clone 用于复制对象,包括其内部状态,但 dup 通常使用后代对象的类来创建新实例。

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).

【讨论】:

  • numbers1311407 因为 dup 在我的代码中保留了 id?
  • 1.9.3-p551 :001 > @user=User.last => # @user .dup => #
  • 更新了答案。回去看了下3.0的源码,果然,当时dupclone的角色互换了。我记得曾经有过这种情况,如果我不查一下也不会相信。
  • 谢谢 numbers1311407 我有这个疑问
【解决方案2】:

本教程解释了这一点,一切与我的控制台显示的相反

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>

【讨论】:

    猜你喜欢
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2022-07-22
    • 2021-08-17
    • 1970-01-01
    • 2011-11-10
    • 2011-05-07
    • 2018-08-16
    相关资源
    最近更新 更多