Matt Elhotiby
Matt Elhotiby

Reputation: 44066

How do I grab the saved value in rails?

Ok i have a model named Tire and I cant update the name field on some reserved names

class Tire < ActiveRecord::Base

  RESERVED_TIRES = ['Michelin', 'Good Year', 'Firestone']

  before_update :reserved_tires

  def reserved_tires
    if RESERVED_TIRES.include?(self.name)
      self.errors.add(:base, "Cant be changed")
      false
    end
  end
end

And i need to not allow the user to update any field is the current name is in the reserved words...this works for all fields other then when the user updates name.

For example is the user updates to "Michelinnnn" then it allows the update because self.name is "Michelinnnn" rather then 'Michelin' which is saved in the DB. Any ideas on how to address this

Upvotes: 0

Views: 90

Answers (4)

rcrogers
rcrogers

Reputation: 2331

So the problem is strings that are similar, but not identical, to the reserved names? The "michelinnnn" example would be caught by using regular expressions instead of exact string matches:

RESERVED_TIRES = [/michelin/i, /good\s*year/i, /firestone/i]
...
if RESERVED_TIRES.find{|r| self.name =~ r}

The built-in Rails function is validates_exclusion_of, but I don't know if that can handle (arrays of) regular expressions.

However, that will only catch certain types of similar names. There are more general ways to calculate string similarity, but there is no watertight solution for this kind of problem.

Upvotes: 1

Leventix
Leventix

Reputation: 3859

If you mean you don't want to allow any change if the name before the change was reserved, then you can access the old name as name_was.

Upvotes: 3

emrass
emrass

Reputation: 6444

THis should do the trick:

name_allowed = RESERVED_TIRES.inject(true) { |is_allowed, tire_name|
  is_allowed &&= !self.name.include?(tire_name)
}
unless name_allowed
  # add error
end

Upvotes: 1

mu is too short
mu is too short

Reputation: 434685

First of all, you probably want to use a validation instead of your before_update:

class Tire < ActiveRecord::Base
  RESERVED_TIRES = ['Michelin', 'Good Year', 'Firestone']
  validate :reserved_tires, :unless => :new_record?

private

  def reserved_tires
    if RESERVED_TIRES.include?(self.name)
      self.errors.add(:base, "Cant be changed")
    end
  end
end

The :unless => :new_record? skips the validation for new records so you will be able to create them but changes will be prevented.

Then add another validation to catch them trying to change the name:

validate :cant_change_reserved_name, :if => :name_changed?
#...
def cant_change_reserved_name
  if RESERVED_TIRES.include?(self.name_was)
    self.errors.add(:name, "You cannot change a reserved name.")
  end
end

Upvotes: 1

Related Questions