如何捕获/解决保存构建的关联时引发的 ActiveRecord:RecordInvalid 异常

发布于 2024-10-26 10:34:16 字数 1641 浏览 7 评论 0原文

我希望得到一些帮助来解决一个问题,我相信很多人在睡梦中都可以避免这个问题。

我有两个处于正常关系中的模特。一个包可以有多个位置,一个位置可以有多个包。如果我的位置模型验证失败(例如,由于位置地址为空),我会收到 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

` 预先感谢您的帮助!

I am hoping to get some help solving a problem that I'm sure many of you could avoid in your sleep.

I have two models in a habtm relationship. A package can have many locations, and a location can have many packages. If my location model fails validation (due to an empty location address, for example), I get anActiveRecord:RecordInvalid exception. I understand that I'm getting this error because when I call package.save, rails automatically calls save! on the location association.

I'm not sure how to avoid the error or at least rescue the error. Do any of you have any good advice, both on how to solve the problem and on Rails best practices?

Here is the code:

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

`
Thanks in advance for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

少女净妖师 2024-11-02 10:34:16

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

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

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

The selected answer is not accurate. According to documentation here there's a simple way to catch rescue this exception:

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

You can access the messages instance variable of errors and get the field and error message associated.

鹿港小镇 2024-11-02 10:34:16

我突然想到了几个想法:

使用 @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_linked 在您的包模型中,并且仅在有效时保存:

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 工作...

希望有帮助!

A couple ideas off the top of my head:

Use @package.save! and a rescue block:

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

Use validates_associated in your Package model, and only save if it's valid:

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

And I'm sure there are a couple more ways, too, as you're working in Ruby...

Hope that helps!

驱逐舰岛风号 2024-11-02 10:34:16

这是我用来解决问题的代码,同时向用户提供关于保存失败原因的良好反馈。请原谅我不优雅的红宝石代码。

仍然存在一个小问题。 。 。如果包和位置均未通过验证,则重新加载时仅显示位置错误消息。如果用户随后更正了位置错误但未更正包错误,则会向他显示包错误消息。我正在研究如何在第一次重新加载时显示所有错误

  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

Here's the code that I used to solve the problem while giving the user good feedback on the why the save failed. Please forgive my inelegant ruby code.

One small problem remains . . . if the package and the location both fail validation, only the location error message is displayed on reload. If the user then corrects the location error but not the package error, he is shown the package error message. I'm working on how to show all of the errors on the first reload

  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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文