Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent change of one field in Rails model

Tags:

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.

like image 519
pjmorse Avatar asked Feb 08 '13 19:02

pjmorse


2 Answers

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

like image 129
Deradon Avatar answered Oct 06 '22 00:10

Deradon


With validates inclusion:

  validates :activity_id,             inclusion: { in: ->(i) { [i.activity_id_was] } },             on: :update 

No need for additional method.

like image 26
Artem P Avatar answered Oct 06 '22 01:10

Artem P