RoR: глубокий клон: как мне также клонировать модели, которые ссылаются на ту, которую я клонирую?- как в моделях клонов через отношение has_many - PullRequest
1 голос
/ 26 января 2012

Мой код:

  class  ActiveRecord::Base  
      def clone!(options = {})
        defaults = {:except => [:updated_at, :cerated_at, :id], :shallow => []}
        options = defaults.merge(options)

        skip_attributes = options[:except] or false #attributes not to clone at all
        shallow_attributes = options[:shallow] or false # non-recursivly cloned attributes
        options[:except] << self.class.to_s.foreign_key # add current class to exceptions to prevent infinite loop

        new_model = self.class.new

        self.attributes.each_pair do |attribute, value|
          skip_attribute = (skip_attributes ? skip_attributes.map{|a| a.to_s}.include?(attribute) : false)
          next if skip_attribute

          shallow_copy = (shallow_attributes ? shallow_attributes.map{|s| s.to_s}.include?(attribute) : false)

          if attribute =~ /_id\z/ and (not shallow_copy)
            # assume reference to a different object
            model_table_name = attribute.gsub(/_id\z/, "")
            model_name = model_table_name.camelize

            referenced_object = model_name.constantize.find(value).clone!(options)
            puts attribute.inspect
            puts referenced_object.inspect
            new_model.send("#{attribute}=", referenced_object[:id])
          else
            new_model.send("#{attribute}=", value) 
          end
        end

        new_model.save!
      end
    end

Итак, один из способов вызова метода заключается в следующем:

b = MyObject.find (432) .clone! ({: Shallow =><Другие объекты имеют внешний ключ к MyObject. </p>

Как узнать, какие имена моделей имеют эту связь?

Ответы [ 2 ]

2 голосов
/ 14 апреля 2012

Я не уверен, что это полностью применимо, потому что я не уверен, что точно понимаю, что вы хотите скопировать, а что нет, но ...

Вы можете получить хорошее использование от Amoeba gem для ActiveRecord 3.2.

Он поддерживает простое и автоматическое рекурсивное дублирование ассоциаций has_one, has_many и has_and_belongs_to_many, предварительную обработку поля и очень гибкий и мощный конфигурационный DSL, который может применяться как к модели, так и на лету.

Обязательно ознакомьтесь с Документацией Amoeba , но использовать ее довольно просто ...

только

gem install amoeba

или добавить

gem 'amoeba'

в ваш Gemfile

затем добавьте блок amoeba в вашу модель и запустите метод dup как обычно

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    enable
  end
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :posts
end

class PostsController < ActionController
  def some_method
    my_post = Post.find(params[:id])
    new_post = my_post.dup
    new_post.save
  end
end

Ваше новое сообщение должно иметь все теги, которые были изначально связаны с ним, и все комментарии также должны дублироваться. Вы можете отключить дублирование различных записей через DSL, о котором вы можете прочитать в документации, но, например, если вы хотите сохранить теги, но не комментарии, вы можете сделать что-то вроде этого:

class Post < ActiveRecord::Base
  has_many :comments
  has_and_belongs_to_many :tags

  amoeba do
    include_field :comments
  end
end

это должно привести к повторной привязке нового сообщения с теми же тегами, что и к старому сообщению, но без дублирования комментариев.

Amoeba также автоматически вернется к дочерним записям, если вы включите их

class Post < ActiveRecord::Base
  has_many :comments

  amoeba do
    enable
  end
end

class Comment < ActiveRecord::Base
  belongs_to :post
  has_many :ratings

  amoeba do
    enable
  end
end

class Rating < ActiveRecord::Base
  belongs_to :comment
end

Надеюсь, это поможет:)

0 голосов
/ 15 февраля 2012

Этот самоцвет делает свое дело:

https://github.com/DerNalia/deep_cloning

в настоящее время обладает большинством возможностей любого из драгоценных камней deep_cloning.

Протестировано на 1.8.7 с Rails 2.3.8

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...