Forum: Ruby on Rails How do I stop a column being updated by model.save?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
690247bbedee9ee592827abfbc23f715?d=identicon&s=25 David Fitzgibbon (davyfitz)
on 2007-05-21 10:19
One of my models has a column that is updated very frequently from a
separate process, so it is important that when a record is saved in
rails, this column should be left alone. In the update method of the
controller I have:

@record = MyModel.find(params[:id])
@record.update_attributes(params[:my_model])

params[:my_model] doesn't have a reference to the column I'm talking
about, however, the UPDATE statement produced by update_attributes will
still assign a value to this column.

Even though its unlikely, if the separate process updates the record in
the time betweent the find, and the update, then the new value will be
lost. Is there a way to prevent this from happening?

p.s. attr_protected doesn't help me
5233478c51a92b6a1a5c970cbf3a42f3?d=identicon&s=25 Isak Hansen (Guest)
on 2007-05-21 10:42
(Received via mailing list)
On 5/21/07, David Fitzgibbon <rails-mailing-list@andreas-s.net> wrote:
> about, however, the UPDATE statement produced by update_attributes will
> still assign a value to this column.
>
> Even though its unlikely, if the separate process updates the record in
> the time betweent the find, and the update, then the new value will be
> lost. Is there a way to prevent this from happening?
>

One option, not very clean and elegant, and probably prone to
deadlocks if you update several rows during a transaction, is locking
the row & reading its' current value from a before_save callback.

E.g.:

  def before_save
    unless self.new_record?
      current = self.class.find(self.id, :lock => true) # "select for
update", locking row
      write_attribute(:some_attribute, current.some_attribute)
    end
  end


Isak
7223c62b7310e164eb79c740188abbda?d=identicon&s=25 Xavier Noria (Guest)
on 2007-05-21 10:51
(Received via mailing list)
On May 21, 2007, at 10:19 AM, David Fitzgibbon wrote:

> about, however, the UPDATE statement produced by update_attributes
> will
> still assign a value to this column.
>
> Even though its unlikely, if the separate process updates the
> record in
> the time betweent the find, and the update, then the new value will be
> lost. Is there a way to prevent this from happening?
>
> p.s. attr_protected doesn't help me

The invocation is

   attr_readonly :foo

but according to

   http://dev.rubyonrails.org/ticket/6896

is scheduled for 1.2.4.

-- fxn
690247bbedee9ee592827abfbc23f715?d=identicon&s=25 David Fitzgibbon (davyfitz)
on 2007-05-21 11:19
>   def before_save
>     unless self.new_record?
>       current = self.class.find(self.id, :lock => true) # "select for
> update", locking row
>       write_attribute(:some_attribute, current.some_attribute)
>     end
>   end
>
>
> Isak

Its nasty, but it might work. Thanks!
F15cd004b8f180465f9f2d856336ade9?d=identicon&s=25 inung (Guest)
on 2007-05-21 12:28
(Received via mailing list)
hi david,

have you ever try this:
@record = MyModel.find(params[:id])
@record.update_attribute("your_column", params[:value])

for updating several column, you could use this instead:
@record.update_attribute("your_column1", params[:value1],
"your_column2",
params[:value2])

afaik, if you do somethink like this:
@record.update_attributes(params[:value])

then all your column will be updated using apt column-name with array of
:value, so that you previous value of column will be lost regardles.

regard,

~inung;


On 21/05/07, David Fitzgibbon <rails-mailing-list@andreas-s.net> wrote:
> >
> > Isak
>
> Its nasty, but it might work. Thanks!
>
> --
> Posted via http://www.ruby-forum.com/.
>
> >
>


--
in03ng a.k.a inung a.k.a nursamsi a.k.a nur syamsi
Y! in03ng
690247bbedee9ee592827abfbc23f715?d=identicon&s=25 David Fitzgibbon (davyfitz)
on 2007-05-21 12:38
> @record.update_attribute("your_column", params[:value])

This has the same problem, both "update_attribute" and
"update_attributes" call the "save" method, which in turn, calls the
"update" method. This is whats setting the values of all the columns in
the table.
F15cd004b8f180465f9f2d856336ade9?d=identicon&s=25 inung (Guest)
on 2007-05-21 12:59
(Received via mailing list)
sorry david, i'm wrong getting your first message. anyway, have u ever
try
using attr_accessible? n00b here, just trying to help...:D

regards,

~inung;


On 21/05/07, David Fitzgibbon <rails-mailing-list@andreas-s.net> wrote:
> Posted via http://www.ruby-forum.com/.
>
> >
>


--
in03ng a.k.a inung a.k.a nursamsi a.k.a nur syamsi
Y! in03ng
690247bbedee9ee592827abfbc23f715?d=identicon&s=25 David Fitzgibbon (davyfitz)
on 2007-05-21 13:04
Yes, both attr_protected and attr_accessible only allow/prevent values
being assigned at the Rails level, the underlying SQL UPDATE that is
executed is still updating the values of all the columns.

Thanks anyway for trying!
89441a6c74647d292f5cc951eae24cfa?d=identicon&s=25 Jack Christensen (Guest)
on 2007-05-21 15:15
(Received via mailing list)
David Fitzgibbon wrote:
> still assign a value to this column.
>
> Even though its unlikely, if the separate process updates the record in
> the time betweent the find, and the update, then the new value will be
> lost. Is there a way to prevent this from happening?
>
> p.s. attr_protected doesn't help me
>
>
Check out optimistic locking.

--
Jack Christensen
jackc@hylesanderson.edu
This topic is locked and can not be replied to.