Answer a question

I am trying to figure out a graceful way to handle a ActiveRecord::RecordNotUnique exception globally for all my ActiveRecord code. I know about the validates_uniqueness_of validation but I want to rescue the exception directly as I have a constraint on the database in order to avoid bad data due to race conditions. I also don't want to create a bunch of custom methods that directly handle the exception every time I want to save or update an object where this constraint can be violated.

I would prefer not to monkey patch ActiveRecord methods like save() but I am beginning to think that achieving graceful exception handling for all ActiveRecord objects in my code might require that. Below is some code that demonstrates what a solution would look like:

class Photo < ActiveRecord::Base

  belongs_to :post

  def save(*args)
    super
  rescue ActiveRecord::RecordNotUnique => error
    errors[:base] << error.message
    false
  end

end

While this works if I call save directly on a Photo object it won't work if I save the object through another model using accepts_nested_attributes_for with validates_associated.

Any help would be greatly apprecaited.

Thanks

Update The desired outcome is to handle the exception and just add a key/value pair to the object's errors hash and then display form errors back to the user telling them that the email has been taken.

Answers

What I was looking for was the inverse_of option when defining the association on each of the models. What inverse_of does is it causes rails to use the in memory instance of the associated object as opposed to going to the db to fetch the record. I created a save method in the Photo model that looks like this:

  def save(*args)
    super
  rescue ActiveRecord::RecordNotUnique => error
    post.errors[:base] << "You can only have one photo be your header photo"
    false
  end

In the rescue block, when I call post.errors I am getting the unsaved, associated post object rather than rails looking for one in the db based on photo.post_id which at this point is nil because the photo object is invalid which caused the post not to be persisted to the db.

Here are the docs for inverse_of

http://guides.rubyonrails.org/association_basics.html#bi-directional-associations

Logo

PostgreSQL社区为您提供最前沿的新闻资讯和知识内容

更多推荐