2010-07-27 43 views
9

我希望在rails中保存/更新模型時能夠用警告替換字段錯誤。基本上我想只寫周圍會產生錯誤的驗證方法的包裝,保存模型,也許在警告散列可(工作就像錯誤哈希):ActiveRecord - 用警告替換模型驗證錯誤

class Person < ActiveRecord::Base 
    # normal validation 
    validates_presence_of :name 

    # validation with warning 
    validates_numericality_of :age, 
          :only_integer => true, 
          :warning => true # <-- only warn 
end 

>>> p = Person.new(:name => 'john', :age => 2.2) 
>>> p.save 
=> true # <-- able to save to db 
>>> p.warnings.map { |field, message| "#{field} - #{message}" } 
["age - is not a number"] # <-- have access to warning content 

任何想法如何我可以實現這個?我能夠將:warning => false默認值添加到ActiveRecord::Validations::ClassMethods::DEFAULT_VALIDATION_OPTIONS 通過擴展模塊,但我正在尋找一些關於如何實現其餘部分的見解。謝謝。

回答

4

我不知道,如果它已經準備好爲Rails 3,但這個插件做了你在找什麼:

http://softvalidations.rubyforge.org/

編輯補充:

要更新的這個基本功能加載ActiveModel與我想出了以下內容:

#/config/initializer/soft_validate.rb: 
module ActiveRecord 
    class Base 
    def warnings 
     @warnings ||= ActiveModel::Errors.new(self) 
    end 
    def complete? 
     warnings.clear 
     valid? 
     warnings.empty? 
    end 
    end 
end 

#/lib/soft_validate_validator.rb 
class SoftValidateValidator < ActiveModel::EachValidator 
    def validate(record) 
    record.warnings.add_on_blank(attributes, options) 
    end 
end 

它增加了一個新的錯誤升ike對象警告和輔助方法完成?,你可以像這樣把它添加到模型:

class FollowupReport < ActiveRecord::Base 
    validates :suggestions, :soft_validate => true 
end 
4

validation_scopes gem使用了一些很好的元編程魔術給你所有的驗證的常用功能和ActiveRecord的::錯誤比object.errors其他上下文對象。

例如,你可以說:

validation_scope :warnings do |s| 
    s.validates_presence_of :some_attr 
end 

以上驗證將被觸發像往常一樣object.valid?,但不會阻止保存到數據庫object.save如果some_attr不存在。任何關聯的ActiveRecord :: Errors對象都將在object.warnings中找到。

以通常方式指定的沒有範圍的驗證仍將按預期運行,阻止數據庫保存並將錯誤對象分配給object.errors。

作者簡要介紹了寶石的發展on his blog

+0

非常酷,非常感謝! – sa125 2011-02-20 12:06:13

+0

寶石版本0.5.1與rails 3兼容,但對gemspec的簡單更改(請參閱https://github.com/ivalkeen/validation_scopes/commit/acc1545a028605997e87fd41efece0ddffd3b999)允許它在rails 4中使用。 – KenB 2014-07-30 21:42:14

1

我做我自己的寶石,以解決問題爲Rails 4.1+:https://github.com/s12chung/active_warnings

class BasicModel 
    include ActiveWarnings 

    attr_accessor :name 
    def initialize(name); @name = name; end 

    warnings do 
    validates :name, absence: true 
    end 
end 

model = BasicModel.new("some_name") 
model.safe? # .invalid? equivalent, but for warnings 
model.warnings # .errors equivalent