【问题标题】:ActiveRecord: Can I copy associations?ActiveRecord:我可以复制关联吗?
【发布时间】:2009-03-27 16:13:35
【问题描述】:

有没有办法将一个模型的关联复制到另一个模型...

template_model = MyModel.find(id)
new_model = template_model.clone
new_model.children << template_model.children # I want to *copy* children

...这样我就可以将子模板从模板复制到新模型? (事实上​​,这段代码将子模板从模板移动到新模型)。

我知道我可以手动循环,但是有更简洁的方法吗?

谢谢

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    问题是您正在克隆模板,但没有克隆它的子模板。尝试类似:

    template_model = MyModel.find(id)
    new_model = template_model.clone
    new_model.children << template_model.children.collect { |child| child.clone }
    

    【讨论】:

      【解决方案2】:

      在 /lib 下的某个位置添加它。例如 clone_deep.rb。

      module CloneDeep
        def clone_deep
          kopy = clone
          self.class.reflect_on_all_associations.each do |association|
            next if association.macro == :belongs_to
            cloned_object = case association.macro
                              when :has_many
                                self.send(association.name).collect { |item| item.clone_deep }
                              when :has_one
                                self.send(association.name) && self.send(association.name).clone_deep
                              else
                                clone
                            end
            kopy.send("#{association.name}=", cloned_object)
          end
          return kopy
        end
      end
      

      在 config/initializers/ 文件夹下创建新的初始化程序。在这个文件里面粘贴

      ActiveRecord::Base.send(:include, CloneDeep)
      

      现在您可以克隆具有所有 has_one 和 hos_many 关联的模型。

      cloned_person = person.clone_deep
      cloned_person.save
      

      【讨论】:

      • 只有这个简单的解决方案对我有用.. amoeba 和 deep_cloneable gems 默认调用 dup 而不是复制关联.. deep_cloneable gem failed on 有很多 through..rails 4.1 谢谢
      【解决方案3】:

      应该使用#dup 而不是#clone,因为在后者的情况下不会复制属性。

      module Promotion
        class Banner
          has_many :localizations
          has_many :images
      
          def deep_dup!
            duplicate = dup
            duplicate.save
      
            duplicate.localizations = localizations.collect { |localization| localization.dup }
            duplicate.images = images.collect { |image| image.dup }
      
            duplicate
          end
        end
      end
      

      http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-i-clone http://api.rubyonrails.org/classes/ActiveRecord/Core.html#method-i-dup

      【讨论】:

        【解决方案4】:

        嗯,这不是真正的副本。

        但你可以这样做

        new_model.child_ids = template_model.child_ids
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-01
          • 1970-01-01
          相关资源
          最近更新 更多