Каков самый простой способ дублирования записи activerecord?

Я хочу сделать копию записи activerecord, изменив одно поле в этом процессе (в дополнение к id). Каков самый простой способ сделать это?

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

например:

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

Ответ 1

Чтобы получить копию, используйте метод клонирования (или dup для rails 3.1):

# rails < 3.1
new_record = old_record.clone

#rails >= 3.1
new_record = old_record.dup

Затем вы можете изменить любые поля, которые вы хотите.

ActiveRecord переопределяет встроенный клоун Object #, чтобы дать вам новую запись (не сохраненную в БД) с неназначенным идентификатором. < ш > Обратите внимание, что он не копирует ассоциации, поэтому вам нужно будет сделать это вручную, если вам нужно.

Квест Rails 3.1 - это мелкая копия, вместо этого используйте dup...

Ответ 2

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

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

создаст новую задачу с :id => nil, :scheduled_on => some_new_date и всеми другими атрибутами, такими же, как и исходная задача. Используя Task.new, вам нужно будет явно вызвать save, поэтому, если вы хотите, чтобы он был сохранен автоматически, измените Task.new на Task.create.

Мир.

Ответ 3

Вам также может понравиться Amoeba gem для ActiveRecord 3.2.

В вашем случае вы, вероятно, захотите использовать опции nullify, regex или prefix, доступные в конфигурации DSL.

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

не забудьте проверить Amoeba Documentation, но использование довольно просто...

только

gem install amoeba

или добавить

gem 'amoeba'

в ваш Gemfile

затем добавьте блок амебы к вашей модели и запустите метод 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

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

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

  amoeba do
    exclude_field :comments
  end
end

Вы также можете создавать поля предварительной обработки, чтобы указать уникальность как с префиксами, так и с суффиксами, а также с регулярными выражениями. Кроме того, есть также множество опций, чтобы вы могли писать в наиболее читаемом стиле для своей цели:

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

Рекурсивное копирование ассоциаций легко, просто включите амебу на дочерние модели, а

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

Конфигурация DSL имеет еще множество опций, поэтому не забудьте ознакомиться с документацией.

Наслаждайтесь!:)

Ответ 5

Обычно я просто копирую атрибуты, меняя все, что мне нужно, меняя:

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

Ответ 6

Если вам нужна глубокая копия с ассоциациями, я рекомендую deep_cloneable gem.

Ответ 7

Легко:

#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

Или

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

Ответ 8

Вы также можете проверить драгоценный камень acts_as_inheritable.

"Acts As Inheritable - это Ruby Gem, специально написанный для моделей Rails/ActiveRecord. Он предназначен для использования с Ассоциацией самореференций, или с моделью, имеющей родителя, который разделяет наследуемые атрибуты. Это позволит вам наследовать любой атрибут или отношение из родительской модели."

Добавив acts_as_inheritable к вашим моделям, вы получите доступ к этим методам:

inherit_attributes

class Person < ActiveRecord::Base

  acts_as_inheritable attributes: %w(favorite_color last_name soccer_team)

  # Associations
  belongs_to  :parent, class_name: 'Person'
  has_many    :children, class_name: 'Person', foreign_key: :parent_id
end

parent = Person.create(last_name: 'Arango', soccer_team: 'Verdolaga', favorite_color:'Green')

son = Person.create(parent: parent)
son.inherit_attributes
son.last_name # => Arango
son.soccer_team # => Verdolaga
son.favorite_color # => Green

inherit_relations

class Person < ActiveRecord::Base

  acts_as_inheritable associations: %w(pet)

  # Associations
  has_one     :pet
end

parent = Person.create(last_name: 'Arango')
parent_pet = Pet.create(person: parent, name: 'Mango', breed:'Golden Retriver')
parent_pet.inspect #=> #<Pet id: 1, person_id: 1, name: "Mango", breed: "Golden Retriver">

son = Person.create(parent: parent)
son.inherit_relations
son.pet.inspect # => #<Pet id: 2, person_id: 2, name: "Mango", breed: "Golden Retriver">

Надеюсь, это поможет вам.