How to hide a database column from ActiveRecord?

David Scheffel wrote:

I've added an array column to one of my tables for providing a faster search. This column is populated by a trigger-function from a detail-table. However this data is being overwritten with blank values by ActiveRecord when performing an insert or update.

Can I tell ActiveRecord to ignore this column and not to add it to the Attributes array?

Add an SQL View object and point the ActiveRecord at that.

(Hypothesis: ActiveRecord might not support your feature because it knows you can do the View trick.)

Or maybe not. :wink:

David Scheffel wrote:

> Add an SQL View object and point the ActiveRecord at that.

But could I still use that "hidden" column in a call to find_by_sql? I mean since it is not part of the underlying (the view) anymore?

Sure - just write a table join between the original table and its own view.

You could even add the original table as another Model object, then put a has_one between the two models.

Hi David,

I ran into a similar problem when working on BetterNestedSet-- I had columns I wanted AR to read, but never write to.

My solution is a bit heavy-handed, but seems to work well. I overrode the update method of Activerecord in the relevant model, so that it won't write that column to the database:

        private           # call 'special_attributes_with_quotes' method instead of attributes_with_quotes           def update #:nodoc:             connection.update(               "UPDATE #{self.class.table_name} " +               "SET #{quoted_comma_pair_list(connection, special_attributes_with_quotes(false))} " +               "WHERE #{self.class.primary_key} = #{quote_value(id)}",               "#{self.class.name} Update"             )           end

          # exclude the columns from update statements           def special_attributes_with_quotes(include_primary_key = true) #:nodoc:             attributes.inject({}) do |quoted, (name, value)|               if column = column_for_attribute(name)                 quoted[name] = quote_value(value, column) unless (!include_primary_key && column.primary) || [your_col_name, your_other_col_name].include?(column.name)               end               quoted             end           end

          # i couldn't figure out how to call attributes_with_quotes without cutting and pasting this private method in. :frowning:           # Quote strings appropriately for SQL statements.           def quote_value(value, column = nil) #:nodoc:             self.class.connection.quote(value, column)           end

If you come up with a better solution please let me know!

Krishna

FYI, I just found out that my solution breaks the before_update callback (and probably others).

Krishna