2012-04-15 42 views
0

好的我有一个名为轮胎模型,我不能对一些保留名称如何在轨中获取保存的值?

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 

更新名称字段,我需要不允许用户更新任何字段是当前的名字是保留字.. 。当用户更新名称时,此功能适用于其他所有字段。

例如,用户更新为“Michelinnn”,则允许更新,因为self.name是“Michelinnnn”,而不是“Michelin”,保存在DB中。关于如何解决这个问题的任何想法

+0

我怎么会在这种情况下添加约束 – Trace 2012-04-15 17:50:04

+0

你能不能使用回调中的id读取现有的数据库记录并进行比较?或者,正如Leventix所建议的那样使用name_was。 – 2012-04-15 17:53:57

回答

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,但这种问题没有防水解决方案。

3

如果你的意思是你不想让任何变化,如果变化是保留名称之前,那么你可以为name_was访问旧名。

+0

我会像self.name_was – Trace 2012-04-15 17:53:46

+0

一样使用它,因为你已经在对象的上下文中,只需要'name_was',所以你不需要'self.'。您也可以从'错误'之前删除它。当使用像self.name =“something”这样的setter时,你会需要它,否则Ruby会设置局部变量名称,而不是在对象上调用方法'name =(value)'。 – Leventix 2012-04-15 17:57:13

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 
1

这应该做的伎俩:

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

你能解释一下吗? – Trace 2012-04-15 18:42:02

+0

当然,只要看一下http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject就可以更好地理解注入。基本上,它循环遍历RESERVED_TIRES中的所有值,并将当前记录值放入块的第二个参数(tire_name)中。第一个参数是本例中的布尔值,是注入方法返回的值。它用true来初始化。 is_allowed && = ...与is_allowed = is_allowed && ...相同,一旦第二个验证(轮胎名称的验证)在前一个循环实例中返回false,它将始终返回false – emrass 2012-04-15 18:50:23

+0

这是否适合您? – emrass 2012-04-20 09:16:03

相关问题