Каков самый простой способ дублирования записи 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 имеет еще множество опций, поэтому не забудьте ознакомиться с документацией.
Наслаждайтесь!:)
Ответ 4
Используйте ActiveRecord:: Base # dup, если вы не хотите копировать id
Ответ 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">
Надеюсь, это поможет вам.