Frage

Ich möchte eine Kopie eines Active Datensatz machen, ein einzelnes Feld in dem Verfahren (neben dem id ) zu verändern. Was ist der einfachste Weg, dies zu erreichen?

Ich weiß, ich könnte einen neuen Datensatz erstellen, und dann jedes der Felder iterieren Kopieren des Datenfeld-für-Feld - aber ich dachte, es muss ein einfacher Weg, dies zu tun ...

wie:

 @newrecord=Record.copy(:id)  *perhaps?*
War es hilfreich?

Lösung

Um eine Kopie zu erhalten, verwenden Sie den Klon (oder dup für Schienen 3.1) Methode:

# rails < 3.1
new_record = old_record.clone

#rails >= 3.1
new_record = old_record.dup

Dann können Sie ändern, je nachdem, welche Felder Sie wollen.

Activeüberschreibt die sich im internen Objekt # Klon zu geben ein neuer Datensatz mit einer nicht belegten ID (nicht auf die DB gespeichert).
Beachten Sie, dass es keine Zuordnungen kopiert, so dass Sie müssen dies manuell tun, wenn Sie müssen.

Rails 3.1 Klon ist eine flache Kopie, verwendet dup statt ...

Andere Tipps

Je nach Bedarf und Programmierstil, Sie können auch eine Kombination der neuen Methode der Klasse und verschmelzen verwenden. In Ermangelung eines besseren einfach Beispiel an, dass Sie eine Aufgabe für einen bestimmten Zeitpunkt geplant haben, und Sie wollen, dass es auf einen anderen Termin duplizieren. Die tatsächlichen Eigenschaften der Aufgabe sind nicht wichtig, so:

old_task = Task.find(task_id)
new_task = Task.new(old_task.attributes.merge({:scheduled_on => some_new_date}))

wird eine neue Aufgabe mit :id => nil, :scheduled_on => some_new_date erstellen und alle anderen Attribute der gleiche wie der ursprüngliche Aufgabe. Mit Task.new, werden Sie ausdrücklich haben speichern anrufen, wenn Sie also automatisch gespeichert werden soll, ändern Task.new zu Task.create.

Frieden.

Sie können auch wie die Amoeba gem für Active 3.2.

In Ihrem Fall möchten Sie wahrscheinlich die Verwendung der nullify, regex oder prefix Optionen, die in der Konfiguration DSL machen.

Es unterstützt die einfache und automatische rekursive Doppel has_one, has_many und has_and_belongs_to_many Verbände, Feld Vorverarbeitung und eine hochflexible und leistungsstarke Konfiguration DSL, die sowohl auf das Modell und im laufenden Betrieb eingesetzt werden kann.

müssen Sie die Amoeba Dokumentation aber Nutzung ist recht einfach ...

nur

gem install amoeba

oder fügen

gem 'amoeba'

Ihr Gemfile

Sie dann die Amöbe Block zu Ihrem Modell hinzufügen und die dup Methode wie gewohnt ausgeführt

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

Sie können auch die Kontrollfelder in vielfältiger Weise kopiert werden, sondern zum Beispiel, wenn Sie vor einer dupliziert verhindern Kommentare wollten, aber Sie wollten die gleichen Tags erhalten, können Sie etwas tun könnten:

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

  amoeba do
    exclude_field :comments
  end
end

Sie können auch Vorprozess Felder zeigen mit beiden Präfixe Einzigartigkeit zu helfen und sowie reguläre Ausdrücke Suffixe. Darüber hinaus gibt es auch zahlreiche Möglichkeiten, so dass Sie in den meisten lesbaren Stil für Ihren Zweck schreiben:

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

  amoeba do
    include_field :tags
    prepend :title => "Copy of "
    append :contents => " (copied version)"
    regex :contents => {:replace => /dog/, :with => "cat"}
  end
end

rekursive Kopieren von Verbänden ist einfach, nur ermöglichen Amöbe auf Kindermodelle und

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

Die Konfiguration DSL hat noch mehr Möglichkeiten, so sollten Sie die Dokumentation überprüfen.

Viel Spaß! :)

Verwenden Sie Activerecord :: Base # dup wenn Sie wollen nicht die id

kopieren

ich in der Regel nur die Attribute kopieren, zu ändern, was ich brauche zu ändern:

new_user = User.new(old_user.attributes.merge(:login => "newlogin"))

Wenn Sie eine tiefe Kopie mit Verbänden benötigen, empfehle ich die deep_cloneable gem.

Die leicht Weg ist:

#your rails >= 3.1 (i was done it with Rails 5.0.0.1)
  o = Model.find(id)
 # (Range).each do |item|
 (1..109).each do |item|
   new_record = o.dup
   new_record.save
 end

oder

# if your rails < 3.1
 o = Model.find(id)
 (1..109).each do |item|
   new_record = o.clone
   new_record.save
 end     

In Rails 5 können Sie einfach erstellen doppeltes Objekt oder Datensatz wie folgt.

new_user = old_user.dup

Da es könnte mehr Logik sein, wenn ein Modell duplizieren, würde ich vorschlagen, eine neue Klasse zu erstellen, in dem Sie alle benötigten Logik behandeln. Zur Erleichterung, dass es ein Juwel, die helfen können: Clowne

Wie pro ihre Dokumentation Beispiele für ein User-Modell:

class User < ActiveRecord::Base
  # create_table :users do |t|
  #  t.string :login
  #  t.string :email
  #  t.timestamps null: false
  # end

  has_one :profile
  has_many :posts
end

Sie erstellen Ihre cloner Klasse:

class UserCloner < Clowne::Cloner
  adapter :active_record

  include_association :profile, clone_with: SpecialProfileCloner
  include_association :posts

  nullify :login

  # params here is an arbitrary Hash passed into cloner
  finalize do |_source, record, params|
    record.email = params[:email]
  end
end

class SpecialProfileCloner < Clowne::Cloner
  adapter :active_record

  nullify :name
end

und dann verwenden:

user = User.last
#=> <#User(login: 'clown', email: 'clown@circus.example.com')>

cloned = UserCloner.call(user, email: 'fake@example.com')
cloned.persisted?
# => false

cloned.save!
cloned.login
# => nil
cloned.email
# => "fake@example.com"

# associations:
cloned.posts.count == user.posts.count
# => true
cloned.profile.name
# => nil

Beispiel aus dem Projekt kopiert, aber es wird eine klare Vorstellung von dem, was man erreichen kann.

Für eine schnelle und einfache Aufzeichnung mit mir gehen würde:

Model.new(Model.last.attributes.reject {|k,_v| k.to_s == 'id'}

Hier ist ein Beispiel Active #dup Methode des überwiegenden Beispiel Doppelarbeit gestalten Beziehung Vervielfältigung umfasst auch:

class Offer < ApplicationRecord
  has_many :offer_items

  def dup
    super.tap do |new_offer|

      # change title of the new instance
      new_offer.title = "Copy of #{@offer.title}"

      # duplicate offer_items as well
      self.offer_items.each { |offer_item| new_offer.offer_items << offer_item.dup }
    end
  end
end

Hinweis: Diese Methode erfordert kein externes Juwel, aber es erfordert neuere Version Active mit #dup Methode implementiert

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top