ruby on rails - query - ¿Cuál es la forma más fácil de duplicar un registro de registro de activación?
rails find (10)
A continuación, se muestra un ejemplo de anulación del método #dup
ActiveRecord para personalizar la duplicación de instancias e incluir también la duplicación de relaciones:
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
Nota: este método no requiere ninguna gema externa, pero requiere una versión más reciente de ActiveRecord con el método #dup
implementado
Quiero hacer una copia de un registro de registro de activación, cambiando un solo campo en el proceso (además de la identificación ). ¿Cuál es la forma más sencilla de lograr esto?
Me doy cuenta de que podría crear un nuevo registro y luego iterar sobre cada uno de los campos copiando los datos campo por campo, pero pensé que debía haber una manera más fácil de hacer esto ...
como:
@newrecord=Record.copy(:id) *perhaps?*
Como podría haber más lógica, al duplicar un modelo, sugeriría crear una nueva clase, en la que manejará toda la lógica necesaria. Para facilitar eso, hay una gema que puede ayudar: clowne
Según sus ejemplos de documentación, para un modelo de usuario:
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
Usted crea su clase cloner:
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
y luego usarlo:
user = User.last
#=> <#User(login: ''clown'', email: ''[email protected]'')>
cloned = UserCloner.call(user, email: ''[email protected]'')
cloned.persisted?
# => false
cloned.save!
cloned.login
# => nil
cloned.email
# => "[email protected]"
# associations:
cloned.posts.count == user.posts.count
# => true
cloned.profile.name
# => nil
Ejemplo copiado del proyecto, pero le dará una visión clara de lo que puede lograr.
Para un registro rápido y sencillo me gustaría ir con:
Model.new(Model.last.attributes.reject {|k,_v| k.to_s == ''id''}
Dependiendo de sus necesidades y estilo de programación, también puede usar una combinación del nuevo método de la clase y fusionar. A falta de un ejemplo más simple , suponga que tiene una tarea programada para una fecha determinada y desea duplicarla en otra fecha. Los atributos reales de la tarea no son importantes, por lo que:
old_task = Task.find(task_id) new_task = Task.new(old_task.attributes.merge({:scheduled_on => some_new_date}))
creará una nueva tarea con :id => nil
:scheduled_on => some_new_date
, y todos los demás atributos lo mismo que la tarea original. Usando Task.new, tendrá que llamar explícitamente a guardar, por lo que si desea que se guarde automáticamente, cambie Task.new a Task.create.
Paz.
La forma fácil es:
#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
O
# if your rails < 3.1
o = Model.find(id)
(1..109).each do |item|
new_record = o.clone
new_record.save
end
Para obtener una copia, use el método de clonación (o duplicación de rieles 3.1):
# rails < 3.1
new_record = old_record.clone
#rails >= 3.1
new_record = old_record.dup
Entonces puedes cambiar los campos que quieras.
ActiveRecord anula el clon de Object # incorporado para darle un nuevo registro (no guardado en la base de datos) con una ID sin asignar.
Tenga en cuenta que no copia asociaciones, por lo que tendrá que hacerlo manualmente si lo necesita.
Rails 3.1 clone es una copia superficial, use dup en su lugar ...
Si necesitas una copia profunda con asociaciones, te recomiendo la gema deep_cloneable .
También puedes consultar la acts_as_inheritable gema.
"Actúa como hereditaria es una gema de Ruby escrita específicamente para los modelos Rails / ActiveRecord. Está diseñada para ser utilizada con la Asociación autorreferencial , o con un modelo que tenga un padre que comparta los atributos heredables. Esto le permitirá heredar cualquier atributo o relación desde el modelo padre ".
Al agregar acts_as_inheritable
a sus modelos, tendrá acceso a estos métodos:
atributos heredados
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
relaciones hereditarias
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">
Espero que esto le pueda ayudar.
También te puede gustar la gema Amoeba para ActiveRecord 3.2.
En su caso, probablemente desee hacer uso de las opciones de regex
, regex
o prefix
disponibles en la configuración DSL.
Admite la duplicación recursiva fácil y automática de las has_many
has_one
, has_many
y has_and_belongs_to_many
, preprocesamiento de campos y una DSL de configuración altamente flexible y potente que se puede aplicar tanto al modelo como sobre la marcha.
Asegúrese de revisar la documentación de la ameba, pero su uso es bastante fácil ...
sólo
gem install amoeba
o agregar
gem ''amoeba''
a tu Gemfile
A continuación, agregue el bloque de ameba a su modelo y ejecute el método dup
como de costumbre.
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
También puede controlar qué campos se copian de varias maneras, pero por ejemplo, si desea evitar que se dupliquen los comentarios pero desea mantener las mismas etiquetas, puede hacer algo como esto:
class Post < ActiveRecord::Base
has_many :comments
has_and_belongs_to_many :tags
amoeba do
exclude_field :comments
end
end
También puede preprocesar los campos para ayudar a indicar la singularidad con prefijos y sufijos, así como expresiones regulares. Además, también hay numerosas opciones para que pueda escribir en el estilo más legible para su propósito:
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
La copia recursiva de asociaciones es fácil, solo habilite ameba en modelos infantiles también
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
La configuración DSL tiene aún más opciones, así que asegúrese de revisar la documentación.
¡Disfrutar! :)
Use ActiveRecord::Base#dup si no desea copiar el ID
Usualmente solo copio los atributos, cambiando lo que necesito cambiar:
new_user = User.new(old_user.attributes.merge(:login => "newlogin"))