1

我希望能夠幫助解決一個問題,我相信你們中的許多人可以在你的睡眠中避免這個問題。如何捕捉/解決ActiveRecord:當我保存一個內置的關聯時導致的RecordInvalid異常

我有兩個模型在habtm關係。一個包可以有很多位置,一個位置可以有很多包。如果我的位置模型驗證失敗(例如由於空位置地址),我得到一個活動記錄:RecordInvalid異常。我知道我得到這個錯誤,因爲當我打電話給package.save時,rails會自動調用save!關於位置關聯。

我不知道如何避免錯誤或至少挽救錯誤。你們有沒有什麼好的建議,包括如何解決問題和Rails最佳實踐?

下面是代碼:」在您的幫助

def create 
    @pacakge = current_user.package.build(params[:package]) 
    package_location 
    if @package.save 
     flash[:success] = "Package created!" 
     redirect_to root_path 
    else   
     render 'pages/home' 
    end 
    end 

    def package_location 
    gps_processing if !session[:gps_aware] 
    @package.locations.build(:address => session[:address]) 
    end 

    def gps_processing 
    session[:address] = [params[:story][:street_address], params[:story][:city], params[:story][:state], params[:story][:country]].compact.join(', ') 
    end 

class Package< ActiveRecord::Base 

    belongs_to :user 
    has_and_belongs_to_many :locations 

    validates   :content, :presence => true, 
        :length  => {:maximum => 140} 
    validates  :user_id, :presence => true 

    default_scope :order => 'package.created_at DESC' 

end 

class Location < ActiveRecord::Base 

    attr_accessible :lng, :lat, :address 

    validates  :lng,  :presence => true 
    validates  :lat,  :presence => true 
    validates  :address, :presence => true 

    geocoded_by :full_street_address, :latitude => :lat, :longitude => :lng 

    before_validation :geocode 

    has_and_belongs_to_many :packages 

    def full_street_address 
    address 
    end 
end 

` 謝謝!

回答

0

下面是我用來解決問題的代碼,同時向用戶提供關於保存失敗原因的良好反饋。請原諒我不雅的紅寶石代碼。

一個小問題依然存在。 。 。如果軟件包和位置均未通過驗證,則僅在重新加載時顯示位置錯誤消息。如果用戶然後更正了位置錯誤而不是包錯誤,則會顯示包錯誤消息。我正在努力如何在第一次加載時顯示所有錯誤

def create 
    @package= current_user.package.build(params[:package]) 
    if package_location && @package.save 
     flash[:success] = "Package created!" 
     redirect_to root_path 
     else 
     render 'pages/home' 
    end 
    end 

def package_location 
    gps_processing if !session[:gps_aware] 
    location = @package.locations.build(:address => session[:address]) 
    if !location.valid? 
    @package.errors.add(:address, "You have entered an invalid address") 
    return false 
    else 
     return true 
    end 
end 

def gps_processing 
    session[:address] = [params[:story][:street_address], params[:story][:city], 
      params[:story][:state], params[:story][:country]].compact.join(', ') 
end 
2

一對夫婦的想法從我的頭頂:

使用@package.save!和救援塊:

def create 
    @package = current_user.package.build(params[:package]) 
    package_location 
    @package.save! 
    flash[:success] = "Package created!" 
    redirect_to root_path 
rescue  
    render 'pages/home' 
end 

使用validates_associated在你的套餐模式,且僅當它是有效的節省:

def create 
    @package = current_user.package.build(params[:package]) 
    package_location 

    # You might be able to just use if(@package.save), but I'm not positive. 
    if(@package.valid?) 
    @package.save! 
    flash[:success] = "Package created!" 
    redirect_to root_path 
    else  
    render 'pages/home' 
    end 
end 

我相信還有更多的方法,因爲你在Ruby中工作...

希望有幫助!

+0

謝謝,澤維爾。救援區塊的作用是捕捉異常情況,但它不會向用戶提供有關問題的反饋。我修改了驗證方法以提供所需的反饋。請參閱下面的代碼。 – 2011-03-26 21:50:16

5

所選答案並不準確。根據文檔here有一個簡單的方法來拯救趕上這個異常:

begin 
    complex_operation_that_calls_save!_internally 
rescue ActiveRecord::RecordInvalid => invalid 
    puts invalid.record.errors 
end 

您可以訪問錯誤的消息實例變量,並得到相關的領域和錯誤消息。