Search code examples
ruby-on-railsrubydatabaseruby-on-rails-3.2denormalization

How to make sure that it is possible to update a database table column only in one way?


I am using Ruby on Rails v3.2.2 and I would like to "protect" a class/instance attribute so that a database table column value can be updated only one way. That is, for example, given I have two database tables:

table1
- full_name_column

table2
- name_column
- surname_column

and I manage the table1 so that the full_name_column is updated by using a callback stated in the related table2 class/model, I would like to make sure that it is possible to update the full_name_column value only through that callback.

In other words, I should ensure that the table2.full_name_column value is always

"#{table1.name_column} #{table1.surname_column}"

and that it can't be another value. So, for example, if I try to "directly" update the table1.full_name_column, it should raise something like an error. Of course, that value must be readable.

Is it possible? What do you advice on handling this situation?


Reasons to this approach...

I want to use that approach because I am planning to perform database searches on table1 columns where the table1 contains other values related to a "profile"/"person" object... otherwise, probably, I must make some hack (maybe a complex hack) to direct those searches to the table2 so to look for "#{table1.name_column} #{table1.surname_column}" strings.

So, I think that a simple way is to denormalize data as explained above, but it requires to implement an "uncommon" way to handling that data.

BTW: An answer should be intend to "solve" related processes or to find a better approach to handle search functionalities in a better way.


Solution

  • By replicating the data from table2 into table1 you've already de-normalized it. As with any de-normalization, you must be disciplined about maintaining sync. This means not updating things you're not supposed to.

    Although you can wall off things with attr_accessible to prevent accidental assignment, the way Ruby works means there's no way to guarantee that value will never be modified. If someone's determined enough, they will find a way. This is where the discipline comes in.

    The best approach is to document that the column should not be modified directly, block mass-assignment with attr_accessible, and leave it at that. There's no concept of a write-protected attribute, really, as far as I know.