2012-04-15 26 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

相關問題