How to hide a database column from ActiveRecord?

Hi there!

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?

Thanks…
David

David S. 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:


Phlip
Redirecting... ← NOT a blog!!!

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:

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?

Thanks
David

Chris G. wrote:

I believe attr_protected would be a more straightforward way to
accomplish this:

Peak Obsession

“Attributes named in this macro are protected from mass-assignment, such
as new(attributes) and attributes=(attributes). Their assignment will
simply be ignored. Instead, you can use the direct writer methods to do
assignment.”

Almost. It protects the value from being changed, but it is still
included in the sql that is generated by ActiveRecord. Since the
particular column is an integer[], but ActiveRecord tries to handle it
as integer instead, it fails because of a wrong type assignment.

Maybe a better database driver would do. I’m currently using the dbi
driver on Windows. I know there is a native one as well, but this one
seems to be a bit tricky to install.

Looking for your suggestions
David

I believe attr_protected would be a more straightforward way to
accomplish this:

http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M000873

“Attributes named in this macro are protected from mass-assignment, such
as new(attributes) and attributes=(attributes). Their assignment will
simply be ignored. Instead, you can use the direct writer methods to do
assignment.”

Phlip wrote:

David S. 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.

As I’ve found out ActiveRecord can’t even handle views - at least not
the postgres-rb driver! It tries to retrieve the structure for the view
which obviously fails.

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

On Dec 28, 12:41 pm, David S. [email protected]

David S. 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.


Phlip
http://c2.com/cgi/wiki?ZeekLand ← NOT a blog!!

k Thanks! You’ve made my day:-)))

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

I will. If I would I’ll post it here.

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

Krishna

On Dec 28 2006, 4:58 pm, David S.

David S. wrote:

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

I submitted a patch at http://dev.rubyonrails.org/ticket/6896 which
adds an attr_readonly method to ActiveRecord::Base to ignore attributes
in update queries. It also fixes a bug with counter_cache. Hopefully
it receives enough support and provides enough value to be applied, but
if not I can make it into a plugin.

Dan M.

Dan M. wrote:

I submitted a patch at http://dev.rubyonrails.org/ticket/6896 which
adds an attr_readonly method to ActiveRecord::Base to ignore attributes
in update queries.

k Thanks!!

I’m really looking forward to it. How could I get notice about the next
Rails release including this patch?

Regards
//David

David S. wrote:

I’m really looking forward to it. How could I get notice about the next
Rails release including this patch?

You can subscribe to the RSS feed for the patch here:
http://dev.rubyonrails.org/ticket/6896?format=rss

You may also want to leave a comment on the patch stating that you
would like to see the patch applied. If you have time, try checking
out Rails trunk, applying the patch, and leaving a comment confirming
that the patch works.

Dan M.

Dan M. wrote:

I submitted a patch at http://dev.rubyonrails.org/ticket/6896 which
adds an attr_readonly method to ActiveRecord::Base to ignore attributes
in update queries. It also fixes a bug with counter_cache. Hopefully
it receives enough support and provides enough value to be applied, but
if not I can make it into a plugin.

I think attr_readonly is a good solution if a different solution that
tracks and only updates changed attributes is not going to be
implemented.

Something’s really needed to prevent a save writing to attributes that
are also being updated through direct database update calls (used to
most easily and properly handle concurrency).


We develop, watch us RoR, in numbers too big to ignore.

You may also want to leave a comment on the patch stating that you
would like to see the patch applied.

I did.

If you have time, try checking
out Rails trunk, applying the patch, and leaving a comment confirming
that the patch works.

How could I apply this path? I assume that it has been commited to a
branch in svn?

Which command line would I need to call?

Thanks…
David