Hi List, I have a table that contains several fields that must be initialized when first created, but may not be altered afterwards (when updating the other fields) because they can be changed by external processes. I noticed that the ActiveRecord update commands (even update_attribute) only seem to work by loading the complete record, changing fields that need to be changed and doing a full update of all (even unchanged) fields. I know it is only a matter of milliseconds between read/update, but I don''t like to take any unneeded risks. I found a workaround by overriding update_attributes in my model as follows: def update_attributes(attributes) @attributes.delete(''fieldthatshouldnotbechanged1'') @attributes.delete(''fieldthatshouldnotbechanged2'') @attributes.delete(''fieldthatshouldnotbechanged3'') super(attributes) end I''m wondering though if there isn''t a better way to accomplish this and I also got a gut-feeling the above will somehow screw up something else but I can''t put a finger on it (and am probably overlooking the obvious). Any bright ideas/suggestions ? Thanks in advance! Piet. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060621/da4af44e/attachment-0001.html
On 6/21/06, Piet Hadermann <piet.hadermann@seagha.com> wrote:> I have a table that contains several fields that must be initialized when > first created, but may not be altered afterwards (when updating the other > fields) because they can be changed by external processes. > > I noticed that the ActiveRecord update commands (even update_attribute) only > seem to work by loading the complete record, changing fields that need to be > changed and doing a full update of all (even unchanged) fields. I know it is > only a matter of milliseconds between read/update, but I don''t like to take > any unneeded risks. > > I found a workaround by overriding update_attributes in my model as follows: > > def update_attributes(attributes) > @attributes.delete(''fieldthatshouldnotbechanged1'') > > @attributes.delete(''fieldthatshouldnotbechanged2'') > > @attributes.delete(''fieldthatshouldnotbechanged3'') > super(attributes) > end > > I''m wondering though if there isn''t a better way to accomplish this and I > also got a gut-feeling the above will somehow screw up something else but I > can''t put a finger on it (and am probably overlooking the obvious). > > Any bright ideas/suggestions ?attr_protected: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M000873
-----Original Message----- From: rails-bounces@lists.rubyonrails.org [mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of Jeremy Evans> > On 6/21/06, Piet Hadermann <piet.hadermann@seagha.com> wrote: > > I have a table that contains several fields that must be initializedwhen> > first created, but may not be altered afterwards (when updating theother> > fields) because they can be changed by external processes. > > > > I noticed that the ActiveRecord update commands (evenupdate_attribute) only> > seem to work by loading the complete record, changing fields thatneed to be> > changed and doing a full update of all (even unchanged) fields. Iknow it is> > only a matter of milliseconds between read/update, but I don''t liketo take> > any unneeded risks. > > > > I found a workaround by overriding update_attributes in my model asfollows:> > > > def update_attributes(attributes) > > @attributes.delete(''fieldthatshouldnotbechanged1'') > > > > @attributes.delete(''fieldthatshouldnotbechanged2'') > > > > @attributes.delete(''fieldthatshouldnotbechanged3'') > > super(attributes) > > end > > > > I''m wondering though if there isn''t a better way to accomplish thisand I> > also got a gut-feeling the above will somehow screw up somethingelse but I> > can''t put a finger on it (and am probably overlooking the obvious). > > > > Any bright ideas/suggestions ? > > attr_protected: > http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M000873Jeremy, this only protects the attributes from being ''mass-assigned''. I just tried it (to make sure), and the fields/atributes that should not be changed/updated are still in the sql update statement being issued. But thanks for the suggestion!
Currently, AR always resaves the entire record, not just the changed portions. I think there are a couple of tickets around that may be looking to change that... -Jonathan. On 6/22/06, Piet Hadermann <piet.hadermann@seagha.com> wrote:> > Jeremy, this only protects the attributes from being ''mass-assigned''. > I just tried it (to make sure), and the fields/atributes that should not > be changed/updated are still in the sql update statement being issued. > > But thanks for the suggestion!
On 6/22/06, Piet Hadermann <piet.hadermann@seagha.com> wrote:> > attr_protected: > > http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M000873 > > Jeremy, this only protects the attributes from being ''mass-assigned''. > I just tried it (to make sure), and the fields/atributes that should not > be changed/updated are still in the sql update statement being issued.It does pretty much the same thing as your modification to update_attributes, except it uses the Rails API specifically designed to protect attributes. To get what you want, you are going to need to patch Rails to not update all fields on save (a worthy patch, IMO, but unlikely to be accepted due to validation issues), or bite the bullet and use optimistic locking [1]. The former is my preference, but it forces you to put your validations in the database (where they belong, IMO), which goes against Rails philosophy. Jeremy [1] http://api.rubyonrails.org/classes/ActiveRecord/Locking.html
A ''rails-y'' approach to this might be to place these in a separate table and use a relationship users id name email hashed_password other_data_id other_data id field_that_must_not_be_changed_1 field_that_must_not_be_changed_2 field_that_must_not_be_changed_3 Or you could play around with before_update and see if you can''t intercept the data there. Just a thought... this problem intrigues me. On 6/22/06, Jeremy Evans <jeremyevans0@gmail.com> wrote:> > On 6/22/06, Piet Hadermann <piet.hadermann@seagha.com> wrote: > > > attr_protected: > > > http://api.rubyonrails.org/classes/ActiveRecord/Base.html#M000873 > > > > Jeremy, this only protects the attributes from being ''mass-assigned''. > > I just tried it (to make sure), and the fields/atributes that should not > > be changed/updated are still in the sql update statement being issued. > > It does pretty much the same thing as your modification to > update_attributes, except it uses the Rails API specifically designed > to protect attributes. To get what you want, you are going to need to > patch Rails to not update all fields on save (a worthy patch, IMO, but > unlikely to be accepted due to validation issues), or bite the bullet > and use optimistic locking [1]. The former is my preference, but it > forces you to put your validations in the database (where they belong, > IMO), which goes against Rails philosophy. > > Jeremy > > [1] http://api.rubyonrails.org/classes/ActiveRecord/Locking.html > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060622/6da873d4/attachment.html