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