0

我正在使用 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,它应该会引发类似错误的内容。当然,该值必须是可读的。

可能吗?你对处理这种情况有什么建议?


这种方法的原因...

我想使用这种方法,因为我计划对包含与“profile”/“person”对象相关table1的其他值的列执行数据库搜索table1......否则,我可能必须进行一些黑客攻击(也许是一个复杂的黑客攻击)将这些搜索定向到table2so 以查找"#{table1.name_column} #{table1.surname_column}"字符串。

因此,我认为一种简单的方法是如上所述对数据进行非规范化,但它需要实现一种“不常见”的方式来处理该数据。

顺便说一句:答案应该旨在“解决”相关流程或找到更好的方法来以更好的方式处理搜索功能。

4

2 回答 2

2

这是在数据库级别维护数据的两种方法...

视图和物化表。

如果可能,table1 可以是 VIEW 或例如 MATERIALIZED QUERY TABLE (MQT)。术语可能略有不同,具体取决于使用的 RDMS,我认为 Oracle 具有 MATERIALIZED VIEWs 而 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;
于 2012-04-27T15:53:09.153 回答
1

通过将 table2 中的数据复制到 table1 中,您已经对其进行了反规范化。与任何反规范化一样,您必须遵守保持同步的原则。这意味着不要更新你不应该更新的东西。

尽管您可以使用隔离墙attr_accessible来防止意外分配,但 Ruby 的工作方式意味着无法保证值永远不会被修改。如果有人有足够的决心,他们就会找到方法。这就是纪律的用武之地。

最好的方法是记录不应直接修改该列,用 阻止质量分配attr_accessible,然后将其保留。据我所知,真的没有写保护属性的概念。

于 2012-04-27T15:15:14.337 回答