2015-10-26 54 views
0

我在有必須一組由表中指定的術語相匹配的字符串字段Rails的幾個表,CvTerm(簡稱controlled_vocabulary)。 CvTerm作爲一個特定於表和字段的白名單;例如,表Foo可能有一個字段Bar,其中唯一允許的條目是Baz,BaxQuux,對於該字段,將爲每個允許的條目創建CvTerms。DRY的方式來糾正相同的驗證領域

我寫了一個自定義驗證,以確保用戶分配給這些字段的值相匹配的爲表設置的一個;這個驗證器可以在所有模型中用作單線程,validates :field, is_controlled: true

class IsControlledValidator < ActiveModel::EachValidator 
    def validate_each(record, attribute, value) 
     if options[:has_context] 
      allowed_terms = CvTerm.where({ 
       :related_table => record.class.to_s, 
       :related_field => attribute.to_s, 
       :context_table => record.related_type 
      }).map(&:term) 
     else 
      allowed_terms = CvTerm.where(:related_table => record.class.to_s, :related_field => attribute.to_s).map(&:term) 
     end 
     unless allowed_terms.include?(value) 
      record.errors[attribute] << "must be included in the allowed terms:\n#{allowed_terms.join("\n")}" 
     end 
    end 
end 

這是在我的模型,以實現方便,如預期運作近,但它是區分大小寫的:這將是很煩人的強制用戶手動確保的情況是完全一樣的初始輸入允許術語。

除了把這種情況下,修正的驗證,我的理解是不可取的,是有辦法做到這一點並不需要我單獨情況下,正確的每一個控制領域?

回答

0

我會做兩件事情。

  1. 使用pluck代替映射,它在sql上更快,而且您不必循環以獲取該術語。

  2. 而不是做直哪裏相似或ILIKE(MySQL的Postgres的VS),以去除大小寫

  3. (也許)移動搜索成一個查詢對象。

+0

這些都是很好的性能指針,雖然受控詞彙表通常足夠小,以至於任何性能命中都可以忽略不計。我更關心的是數據一致性 - 我怎樣才能讓我的用戶以均勻的長期風,而不必以確保每一個最後的大寫字母被妥善安置? – Vardarac

+0

聽起來好像你需要在保存前在後端進行這種轉換。這是您確保它採用特定格式的唯一方法。你也可以用postgres中的ilike做一個不區分大小寫的搜索。 – Austio