ruby-on-rails-3validationhobo

Prevent change of one field in Rails model


I have two related models - let's say Activity and Step. Activity has_many :steps and Step belongs_to :activity which means the table for steps has an activity_id column.

This is in Hobo 1.3, so Rails 3.0.

What I want is to ensure that after Step creation it is not possible to move a step to another Activity. We don't want the activity_id field to change.

I've removed the field from edit forms, but I'm looking for a stronger constraint. Essentially I want to validate on update (not on create) that the column isn't being touched. Hobo's documentation doesn't suggest anything of the sort inside Hobo, so I'm looking at Rails validations, but so far I haven't found the "only do this on update" constraint that I remember, nor a validation that something isn't changing.


Solution

  • You can declare an attribute as read_only with attr_readonly :your_field_name. But this won't create an error if you try to write this attribute, it will fail silently. (This attribute will be ignored for all SQL-Updates)

    Another option might be, to write a validation for this case, might look like this:

    class Step < ActiveRecord::Base
      validate :activity_id_not_changed
    
      private
    
      def activity_id_not_changed
        if activity_id_changed? && self.persisted?
          errors.add(:activity_id, "Change of activity_id not allowed!")
        end
      end
    end
    

    persisted? returns true, if this is not a new record and it is not destroyed.

    Links:

    http://api.rubyonrails.org/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html#method-i-readonly_attributes

    http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-persisted-3F