我正在使用Ruby on Rails v3.2.2,我想“保护”一个类/实例属性,以便数据库表列值只能以一种方式更新。也就是说,例如,假设我有两个数据库表:
table1
- full_name_column
table2
- name_column
- surname_column
我管理table1
以便通过使用相关full_name_column
类/模型中声明的回调更新table2
,我想确保可以仅通过该回调更新full_name_column
值 。
换句话说,我应该确保 table2.full_name_column
值总是
"#{table1.name_column} #{table1.surname_column}"
并且它不能是另一个值。因此,例如,如果我尝试“直接”更新table1.full_name_column
,它应该引发类似错误的事情。当然,这个值必须是可读的。
有可能吗?您对处理这种情况有什么建议?
这种做法的原因......
我想使用这种方法,因为我计划在table1
列上执行数据库搜索,其中table1
包含与“profile”/“person”对象相关的其他值...否则,可能,我必须做一些黑客攻击(可能是一个复杂的黑客攻击)来将这些搜索引导到table2
,以便查找"#{table1.name_column} #{table1.surname_column}"
个字符串。
所以,我认为一种简单的方式是 denormalize 数据,如上所述,但它需要实现一种“不常见”的方式来处理这些数据。
BTW :答案应该是“解决”相关流程或找到更好的方法来更好地处理搜索功能。
答案 0 :(得分:2)
这是在数据库级别维护数据的两种方法......
观看次数和具体化表格。
如果可能,table1可以是VIEW或例如MATERIALIZED QUERY TABLE(MQT)。术语可能略有不同,具体取决于使用的RDMS,我认为Oracle具有MATERIALIZED VIEW,而DB2具有MATERIALIZED QUERY TABLEs。
VIEW只是对物理上在不同表中的数据的访问。其中MATERIALIZED VIEW / QUERY TABLE是数据的物理副本,因此例如不与实时源数据同步。
反正。这些方法将提供对table2所拥有但可由table1访问的数据的只读访问权限。
非常简单的视图示例:
CREATE VIEW table1 AS
SELECT surname||', '||name AS full_name
FROM table2;
<强>触发器强>
有时候视图不方便,因为您可能真的希望在table1中拥有一些其他地方无法获得的数据。在这些情况下,您可以考虑使用数据库触发器。即创建触发器,当table2更新时,table1也会在同一个数据库事务中更新。
使用触发器可能会出现问题,那么您必须为客户端授予更新table1的权限。某些RDMS可能提供一些方法来调整触发器的访问控制,即TRIGGER执行的操作将使用启动TRIGGER的操作的不同权限执行。
在这种情况下,TRIGGER看起来像这样:
CREATE TRIGGER UPDATE_NAME
AFTER UPDATE OF NAME, SURNAME ON TABLE2
REFERENCING NEW AS NEWNAME
FOR EACH ROW
BEGIN ATOMIC
UPDATE TABLE1 SET FULL_NAME = NEWNAME.SURNAME||', '||NEWNAME.NAME
WHERE SOME_KEY = NEWNAME.SOME_KEY
END;
答案 1 :(得分:1)
通过将table2中的数据复制到table1中,您已经对它进行了非规范化。与任何非规范化一样,您必须遵守维护同步的规定。这意味着不要更新你不应该做的事情。
尽管你可以使用attr_accessible
来阻止意外分配,但Ruby的工作方式意味着无法保证永远不会修改该值。如果某人有足够的决心,他们会找到一种方法。这就是纪律的来源。
最好的方法是记录不应该直接修改列,使用attr_accessible
阻止批量分配,并将其留在那里。实际上,据我所知,没有写保护属性的概念。