ruby - 在 Ruby ActiveRecord 中创建和更新时忽略 'read-only' 列

标签 ruby activerecord view db2

我正在寻找以下问题的解决方案:我有一个由可更新数据库 View 支持的 ActiveRecord 实体(在 DB2 中通过 activerecord-jdbc-adapter gem)。此 View 包含一列,该列是根据其他列计算得出的,并且是“只读”的:您不能以任何有效方式设置该列。当为该实体创建新记录时,该字段应该被设置。然而,默认情况下,ActiveRecord 确实将其设置为“默认值”(NULL),这被数据库拒绝了。

attr_readonly 不是解决方案,因为它只会从更新中排除列,而不是从创建中排除列。

attr_ignore,例如由 'lincoln' gem 实现的,也不是解决方案,因为那样该字段将被完全忽略。但是,该专栏仍然需要阅读和访问。它实际上什至被用作关系的一部分。

有一些方法可以阻止您设置 ActiveRecord 实体的某个属性,但这通常不会阻止该属性被包含在创建或更新语句中

有谁知道 ActiveRecord 中是否有一种方法可以将列指定为“从不设置此字段”?

更新,回应 Arsen7: 我试图使用 after_initialize Hook 从新创建的实体中删除该属性,因此它不包含在构建的 SQL 中。这样做的问题是该属性已完全删除并且根本不再可用,与上述“igonre_attr”情况几乎相同。由于缓存的存在,这并非易事,并且需要额外的逻辑来强制重新加载这些特定表的实体。除了使用 after_initialize 之外,这可能可以通过重写 create 来添加“重新加载”来实现。

(正如 Arsen7 所指出的,我忘了说我在 ActiveRecord 3.0.9)

我的解决方案

因为我的实体已经继承自 ActiveRecord::Base 的子类,所以我选择添加 before_createafter_create Hook 。在 before_create Hook 中,我从实例的 @attributes 中删除了“已计算”列。在 after_create Hook 中,我再次添加它们并从数据库中读取“计算”列的值以将它们设置为它们收到的值。

添加这样的钩子(Hook)几乎与覆盖创建相同,所以我认为 Arsen7 的答案是正确的。

最佳答案

恐怕 ActiveRecord 没有为您需要的用例准备好。 (顺便问一下:您使用的是哪个版本的 AR?)

但我相信您可以应用两种可能的解决方法。

首先,是覆盖模型的“创建”方法,执行一些其他 SQL,在最坏的情况下手动准备。我认为需要覆盖的真正函数不是“创建”本身,而是查看源代码您可以找到它。

另一种解决方案,我认为是一种更优雅的解决方案,是在数据库中创建触发器。我更喜欢 PostgreSQL 世界,在那里我会使用 'CREATE RULE',但是查看 DB2 文档我发现在 DB2 中有 'INSTEAD OF' triggers .我希望这可能有所帮助。

关于ruby - 在 Ruby ActiveRecord 中创建和更新时忽略 'read-only' 列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6667758/

相关文章:

javascript - 使用相同 View 的 React-Native 2 按钮

ruby - 在 Ruby 中显式返回是好的风格吗?

ruby-on-rails - Jobs with Resque gives "Don' t know how to build task 'jobs:work' "on Heroku

ruby-on-rails - 在 rails ActiveRecord 中别名 find_by 方法

php - Yii 中使用 updateAll() 递增字段

objective-c - 无法在 View 中设置标签

ruby-on-rails - 将 json 字符串转换为 URL 编码字符串 (Rails)

javascript - 如何在rails中使用jquery删除特定项目?

ruby-on-rails - 核心中的 find_by() 和 FinderMethods 中的 find_by() 有什么区别?

database - 没有数据库的django模型