复制 ActiveRecord 记录的最简单方法是什么?
我想制作 ActiveRecord 对象的副本,更改进程中的单个字段(除了 id 之外)。 实现这一目标的最简单方法是什么?
我意识到我可以创建一条新记录,然后迭代每个字段,逐个字段复制数据 - 但我认为必须有一种更简单的方法来做到这一点。
也许是这样的:
new_record = Record.copy(:id)
I want to make a copy of an ActiveRecord object, changing a single field in the process (in addition to the id). What is the simplest way to accomplish this?
I realize I could create a new record, and then iterate over each of the fields copying the data field-by-field - but I figured there must be an easier way to do this.
Perhaps something like this:
new_record = Record.copy(:id)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
您可能还喜欢 ActiveRecord 3.2 的 Amoeba gem。
对于您的情况,您可能希望使用配置 DSL 中提供的
nullify
、regex
或prefix
选项。它支持
has_one
、has_many
和has_and_belongs_to_many
关联的简单自动递归复制、字段预处理以及可应用的高度灵活且强大的配置DSL无论是对于模型还是在飞行中。请务必查看 Amoeba 文档,但使用非常简单......
只需
或添加
到您的 然后, Gemfile
将阿米巴块添加到模型中,并照常运行 dup 方法。
您还可以通过多种方式控制复制哪些字段,但例如,如果您想防止注释重复,但您想要维护相同的标签,您可以执行以下操作:
您还可以预处理字段以帮助指示前缀和后缀以及正则表达式的唯一性。 此外,还有许多选项,因此您可以根据自己的目的以最易读的方式进行编写:
关联的递归复制很容易,只需在子模型上启用amoeba
配置 DSL 还有更多选项,因此请务必查看文档。
享受! :)
You may also like the Amoeba gem for ActiveRecord 3.2.
In your case, you probably want to make use of the
nullify
,regex
orprefix
options available in the configuration DSL.It supports easy and automatic recursive duplication of
has_one
,has_many
andhas_and_belongs_to_many
associations, field preprocessing and a highly flexible and powerful configuration DSL that can be applied both to the model and on the fly.be sure to check out the Amoeba Documentation but usage is pretty easy...
just
or add
to your Gemfile
then add the amoeba block to your model and run the
dup
method as usualYou can also control which fields get copied in numerous ways, but for example, if you wanted to prevent comments from being duplicated but you wanted to maintain the same tags, you could do something like this:
You can also preprocess fields to help indicate uniqueness with both prefixes and suffixes as well as regexes. In addition, there are also numerous options so you can write in the most readable style for your purpose:
Recursive copying of associations is easy, just enable amoeba on child models as well
The configuration DSL has yet more options, so be sure to check out the documentation.
Enjoy! :)
如果您不这样做,请使用 ActiveRecord::Base#dup不想复制id
Use ActiveRecord::Base#dup if you don't want to copy the id
我通常只是复制属性,更改我需要更改的内容:
I usually just copy the attributes, changing whatever I need changing:
如果您需要具有关联的深层副本,我推荐 deep_cloneable gem。
If you need a deep copy with associations, I recommend the deep_cloneable gem.
要获取副本,请使用 dup (或克隆for
然后您可以更改您想要的任何字段。
ActiveRecord 覆盖内置 Object#clone 为您提供一个新的 (未保存到数据库)具有未分配 ID 的记录。
请注意,它不会复制关联,因此如果需要,您必须手动执行此操作。
Rails 3.1 克隆是浅拷贝,请使用 dup 代替...
To get a copy, use the dup (or clone for < rails 3.1+) method:
Then you can change whichever fields you want.
ActiveRecord overrides the built-in Object#clone to give you a new (not saved to the DB) record with an unassigned ID.
Note that it does not copy associations, so you'll have to do this manually if you need to.
Rails 3.1 clone is a shallow copy, use dup instead...
您还可以检查 acts_as_inheritable gem。
“Acts As Inheritable 是专门为 Rails/ActiveRecord 模型编写的 Ruby Gem。它旨在与 自引用关联,或者与具有共享可继承属性的父模型的模型。这将允许您从父模型继承任何属性或关系。”
通过将
acts_as_inheritable
添加到您的模型中,您将可以访问以下方法:inherit_attributes
inherit_relations
希望这可以帮助您。
You can also check the acts_as_inheritable gem.
"Acts As Inheritable is a Ruby Gem specifically written for Rails/ActiveRecord models. It is meant to be used with the Self-Referential Association, or with a model having a parent that share the inheritable attributes. This will let you inherit any attribute or relation from the parent model."
By adding
acts_as_inheritable
to your models you will have access to these methods:inherit_attributes
inherit_relations
Hope this can help you.
由于可能有更多逻辑,因此在复制模型时,我建议创建一个新类,在其中处理所有需要的逻辑。
为了缓解这个问题,有一个 gem 可以提供帮助:clowne
根据他们的文档示例,对于用户模型:
您创建克隆器类:
然后使用它:
从项目复制的示例,但它将给出您可以实现的目标的清晰愿景。
为了快速简单的记录,我会选择:
Model.new(Model.last.attributes.reject {|k,_v| k.to_s == 'id'}
Since there could be more logic, when duplicating a model, I would suggest to create a new class, where you handle all the needed logic.
To ease that, there's a gem that can help: clowne
As per their documentation examples, for a User model:
You create your cloner class:
and then use it:
Example copied from the project, but it will give a clear vision of what you can achieve.
For a quick and simple record I would go with:
Model.new(Model.last.attributes.reject {|k,_v| k.to_s == 'id'}
尝试 Rails 的 dup 方法:
Try rails's
dup
method:最简单的方法是:
或者
The easily way is:
Or
根据您的需要和编程风格,您还可以使用类的新方法和合并的组合。 由于缺乏更好的简单示例,假设您在某个日期安排了一项任务,并且希望将其复制到另一个日期。 任务的实际属性并不重要,因此:
将使用
:id => 创建一个新任务; nil
,:scheduled_on =>; some_new_date
,所有其他属性与原始任务相同。 使用Task.new,您必须显式调用save,因此如果您希望自动保存它,请将Task.new 更改为Task.create。和平。
Depending on your needs and programming style, you can also use a combination of the new method of the class and merge. For lack of a better simple example, suppose you have a task scheduled for a certain date and you want to duplicate it to another date. The actual attributes of the task aren't important, so:
will create a new task with
:id => nil
,:scheduled_on => some_new_date
, and all other attributes the same as the original task. Using Task.new, you will have to explicitly call save, so if you want it saved automatically, change Task.new to Task.create.Peace.
以下是重写 ActiveRecord
#dup
方法的示例,用于自定义实例复制并包含关系复制:注意:此方法不需要任何外部 gem,但需要带有
# 的较新 ActiveRecord 版本dup
方法已实现Here is a sample of overriding ActiveRecord
#dup
method to customize instance duplication and include relation duplication as well:Note: this method doesn't require any external gem but it requires newer ActiveRecord version with
#dup
method implemented在 Rails 5 中,您可以像这样简单地创建重复对象或记录。
In Rails 5 you can simply create duplicate object or record like this.