好的,我有一个名为Tire的模型,我无法更新某些保留名称上的名称字段
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
我需要不允许用户更新任何字段,当前名称是保留字...这适用于除用户更新名称之外的所有字段。
例如,用户更新为“Michelinnnn”然后它允许更新,因为self.name是“Michelinnnn”而不是“米其林”,它保存在数据库中。关于如何解决这个问题的任何想法
答案 0 :(得分:3)
如果您的意思是如果保留更改名称之前您不想允许任何更改,那么您可以访问旧名称 name_was
答案 1 :(得分:1)
所以问题是与保留名称相似但不相同的字符串?使用正则表达式而不是精确的字符串匹配来捕获“michelinnnn”示例:
RESERVED_TIRES = [/michelin/i, /good\s*year/i, /firestone/i]
...
if RESERVED_TIRES.find{|r| self.name =~ r}
内置的Rails函数是validates_exclusion_of,但我不知道它是否可以处理正则表达式的数组。
然而,这只会捕获某些类似的名字。 There are more general ways to calculate string similarity,但对于这类问题没有防水解决方案。
答案 2 :(得分:1)
首先,您可能希望使用验证而不是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
:unless => :new_record?
会跳过新记录的验证,因此您可以创建它们,但会阻止更改。
然后添加另一个验证以捕获他们尝试更改名称:
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
答案 3 :(得分:1)
应该这样做:
name_allowed = RESERVED_TIRES.inject(true) { |is_allowed, tire_name|
is_allowed &&= !self.name.include?(tire_name)
}
unless name_allowed
# add error
end