5

我希望能得到一些帮助来解决一个我相信你们中的许多人可以在睡眠中避免的问题。

我有两个处于 habtm 关系的模型。一个包可以有多个位置,一个位置可以有多个包。如果我的位置模型验证失败(例如,由于位置地址为空),我会收到 ActiveRecord:RecordInvalid 异常。我知道我收到此错误是因为当我调用 package.save 时,rails 会自动调用 save!关于位置关联。

我不确定如何避免错误或至少挽救错误。关于如何解决问题和 Rails 最佳实践,你们有什么好的建议吗?

这是代码:

def create
    @package = 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

` 提前感谢您的帮助!

4

3 回答 3

24

选择的答案不准确。根据此处的文档,有一种简单的方法可以解决此异常:

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

您可以访问错误的消息实例变量并获取相关的字段和错误消息。

于 2014-10-12T05:37:07.810 回答
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

在您的 Package 模型中使用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...

希望有帮助!

于 2011-03-24T23:28:26.310 回答
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
于 2011-03-26T21:59:23.397 回答