调用ActiveRecord的#relationship_ids = 会立即保存。 有任何变通方法吗?

我在ActiveRecord的#relationship_ids方法中遇到了一个奇怪的问题(当你声明’has_many’时会自动添加),这会立即为现有记录保存,这会引起一些问题,我想知道是否有人有任何有用的建议。

我正在运行Rails 2.3.5。

考虑这个简单的场景,其中有一篇文章has_many标签,比如说:

a = Article.first a.name = "New Name" # No save yet a.author_id = 1 # No save yet a.tag_ids = [1,2,3] # These changes are saved to the database # immediately, even if I don't subsequently # call 'a.save' 

这对我来说似乎很令人惊讶。 它在尝试构建预览工具时特别引起问题 – 我想更新一堆属性然后预览文章而不保存它 – 但在这种情况下,标签更改会保存,即使没有其他字段也可以。

(可能相关的是,如果’a’是一篇新文章而不是现有文章,那么事情就像我期望的那样 – 在我称之为’a.save’之前,没有任何东西得到保存)

我有一个相当讨厌的解决方法 – 我可以覆盖模型中的tag_ids =方法来填充实例变量,并实际将相关模型保存在before_save回调中。

但我想知道一种比我更简单的方法,我必须为每个具有has_many关系的模型做这个,我想创建一个预览工具。

有没有人有任何修复/解决方法/一般建议? 谢谢!

事情是这样的。 它被称为外键。 在具有许多关系的情况下,链接到具有许多模型的模型的信息作为外键存储在该模型之外。

与文章一样,有很多标签。 将标记链接到文章的信息存储在标记表或连接表中。 当您在文章上调用保存时,您只保存文章。

活动记录会立即修改其他记录。 除非您正在处理尚未保存的新文章。 如果Rails不知道要在外键中放置哪个id,Rails将延迟创建/更新相关记录。

但是,如果您要修改现有记录,那么您决定使用的解决方案就是您可以做的所有事情。 使用accepts_nested_attributes_for有一个更丑陋的黑客,但它确实不值得努力。

如果您希望将此行为添加到许多模型而不是所有模型,您可能需要考虑编写一个简单的插件来重新定义所需方法的分配,并在单个类方法调用中添加回调。 看看acts_as_audited之类的来源,看看它是如何完成的。

如果您希望将此行为添加到所有模型,您可以编写has_many的包装器来执行此操作。