Lindsey B
Lindsey B

Reputation: 556

friendly_id and acts_as_paranoid creating duplicate slugs

I'm current using acts_as_paranoid and friendly_id (5.0.1) on a model and when I destroy a model and try to create a new one that will generate the same slug I get:

ERROR:  duplicate key value violates unique constraint "index_papers_on_slug"

I need to somehow get the code that checks if a slug already exists check within the scope of all of the objects not just the non-deleted ones.

How can I get friendly_id to use with_deleted when checking if a slug already exists. I should note that I am also using slug history which may be complicating things further.

Upon digging deeper I realized that since I am using history the slug is being fully deleted while the object is just being soft deleted:

DELETE FROM "friendly_id_slugs" WHERE "friendly_id_slugs"."id" = $1  [["id", 9423]]

So, I just need to figure out how to prevent this and I should be okay since it looks like the friendly_id code itself is already using unscoped when trying to find a valid slug.

Upvotes: 5

Views: 1307

Answers (3)

I just came across this issue too and I figured two different ways to address it.

Solution 1:

Use dependent: false.

friendly_id :title, dependent: false

Solution: 2

Overcoming this problem without overriding the dependent destroy for anyone that wants to avoid that.

The friendly_id gem uses a method called scope_for_slug_generator to set the model scope. That means we could override this method by adding the following to app/config/initializers/friendly_id.rb.

module FriendlyId
  def scope_for_slug_generator
    scope = if self.class.base_class.include?(Paranoia)
      self.class.base_class.unscoped.with_deleted
    else
      self.class.base_class.unscoped
    end
 
    scope = self.class.base_class.unscoped
    scope = scope.friendly unless scope.respond_to?(:exists_by_friendly_id?)
    primary_key_name = self.class.primary_key
      
    scope.where(self.class.base_class.arel_table[primary_key_name].not_eq(send(primary_key_name)))
  end
end

Upvotes: 0

Lindsey B
Lindsey B

Reputation: 556

Adding the following to the model allowed me to overrride the dependent destroy on the slugs

def has_many_dependent_for_slugs; end

The solution comes from a comment on this github issue.

Upvotes: 3

bredikhin
bredikhin

Reputation: 9045

Friendly_id has a module called scoped which allows you to generate unique slugs within a scope. So, probably

class Paper < ActiveRecord::Base
  extend FriendlyId
  friendly_id :title, :use => :scoped, :scope => :unscoped
end

will resolve the problem.

Upvotes: 2

Related Questions