Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I disallow updates except for on one field?

I've been preventing updates to certain models by using this in the model:

def update
  self.errors.add_to_base( "Cannot update a #{ self.to_s }" )
end

I'm now writing a plugin that delivers some extra functionality to the model, and I need to update one field in the model. If I weren't using a plugin I would do this directly in the model...

def update
  if self.changed == ['my_field']
    super
  else
    self.errors.add_to_base( "Cannot update a #{ self.to_s }" )       
  end
end

I can't do the same from my plugin since I don't know if the update behaviour is the ActiveRecord default, or has been overridden to prevent updates. Is there another way to prevent record updates while allowing me to override for a specific field (and only in the instance where my plugin is applied to this model).

like image 342
Nick Avatar asked Nov 16 '10 07:11

Nick


2 Answers

First, you should be using a before_update callback for that sort of thing rather than overriding update. Second, you can store the updatable attributes on the model, and then update them with the plugin. I just wrote this in the browser, so it could be wrong.

  attr_accessor :updatable_attributes
  before_update :prevent_update

  private
  def prevent_update
    return true if self.changed == self.updatable_attributes
    self.errors.add_to_base "Cannot update a #{ self.to_s }"
    false
  end
end
like image 82
zaius Avatar answered Nov 02 '22 19:11

zaius


Late to the game here, but for people viewing this question, you can use attr_readonly to allow writing to a field on create, but not allowing updates.

See http://api.rubyonrails.org/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html

I think it has been available since Rails 2.0

The tricky part is, if you have any attributes that are attr_accessible you have to list your read only attributes there also (or you get a mass assignment error on create):

class Post < ActiveRecord::Base
  attr_readonly :original_title
  attr_accessible :latest_title, :original_title
end
like image 42
marksiemers Avatar answered Nov 02 '22 17:11

marksiemers