Con*_*ion 5 ruby db2 activerecord view
我正在寻找以下问题的解决方案:我有一个ActiveRecord实体,由可更新的数据库视图支持(在DB2中通过activerecord-jdbc-adapter gem).此视图包含一个从其他列计算的列,并且是"只读":您无法以任何有效方式设置该列.当这个实体创建一个新的纪录,那场应该不会设置.但是,默认情况下,ActiveRecord会使用"default"(NULL)对其进行设置,该值将被数据库拒绝.
attr_readonly不是解决方案,因为它只从更新中排除列,而不是从创建中排除.
attr_ignore,例如由'lincoln'gem实现的,也不是解决方案,因为那时该字段被完全忽略.但是,该列仍需要读取并可访问.它实际上甚至被用作关系的一部分.
有一些方法可以阻止您设置ActiveRecord实体的某个属性,但这通常不会阻止该属性包含在create或update语句中
有没有人知道ActiveRecord中是否有办法将列指定为"从不设置此字段"?
更新,响应Arsen7:我试图使用after_initialize挂钩从新创建的实体中删除属性,因此它不包含在构建的SQL中.这样做的问题在于该属性被完全删除并且根本不再可用,与上面描述的'igonre_attr'情况几乎完全相同.由于缓存,这并非易事,并且需要额外的逻辑来强制重新加载这些特定表的实体.create除了使用after_initialize之外,可以通过覆盖添加'reload'来实现.
(正如Arsen7指出的那样,我忘了提到我在ActiveRecord 3.0.9)
我的解决方案
由于我的实体已经从子类继承ActiveRecord::Base,我选择添加before_create和after_create挂钩.在before_create钩子中,我从@attributes实例中删除了"计算"列.在after_create钩子中,我再次添加它们并从数据库中读取"计算"列的值,以将它们设置为它们收到的值.
添加这样的钩子几乎与覆盖创建相同,所以我认为Arsen7的答案是正确的.
恐怕 ActiveRecord 还没有为您需要的用例做好准备。(顺便问一下:您使用的是哪个版本的 AR?)
但我相信您可以应用两种可能的解决方法。
第一种是覆盖模型的“创建”方法,执行一些其他 SQL,在最坏的情况下手动准备。我认为需要覆盖的真正函数不是“创建”本身,而是查看源代码,您可以找到该函数。
另一种解决方案(我相信也是一种更优雅的解决方案)是在数据库中创建触发器。我更多地在 PostgreSQL 世界中,在那里我会使用 触发器'CREATE RULE',但是查看 DB2 文档,我发现在 DB2 中有'INSTEAD OF' 触发器。我希望这会有所帮助。