How to avoid FriendlyId creating a different slug if current already exists - ruby-on-rails

I'm using FriendlyId gem on Ruby on Rails 5.
Is there any way to stop FriendlyId to create a different slug if the current one has already been taken? I'd like the user to have full control over the slug.

Add this method to your Model.
def should_generate_new_friendly_id?
new_record?
end
or modify the content of the method to match your needs.

Related

Rails Friendly_ID Multiple model creation with slug on same field failing

I am running a Rails 5 application which has 2 models - a User and a Provider. I am using multiple table inheritance to show that each Provider "is a" User (via the active_record-acts_as gem). So, in effect, creating a Provider with the related fields would create a User at the same time.
I wanted to implement slugging for these models, so I integrated the friendly_id gem for that purpose.
Both models are slugged via a field called username. The code in question being:
class User
extend FriendlyId
friendly_id :username, use: :slugged
# ...
end
for the User model and
class Provider
extend FriendlyId
friendly_id username, use: :slugged
def username
acting_as.username # this fetches the parent model (User)'s username field.
end
# ...
end
for the Provider model.
When I attempt to create a Provider via a controller action (providers#create), it fails, with the error being:
TypeError at /providers
nil is not a symbol nor a string
The stack trace identifies the problem to be at lib/friendly_id/slugged.rb:299, which is the body of the should_generate_new_friendly_id? method. This method was called by the set_slug method in the same file, slugged.rb.
I have created an issue on the GitHub page of friendly_id, where you can find the request parameters and full stack trace.
Edit: added friendly_id_config for both: https://gist.github.com/mindseyeblind/9b78c588f5008a494f7157e72da1de6e

rails friendly_id bad request

I'm new to rails and currently involved in an internship and I was assigned to use the friendly_id gem for my tournament class, this is part of the code in it:
class Tournament < ApplicationRecord
extend FriendlyId
friendly_id :url_id
...
end
I don't use a slug since I have a url_id attribute that stores my desired url and when I try with the old .../tournaments/1 everything's all good but with .../tournaments/example I get "example is not a valid value for id" with code 103, status 400. Any ideas what the problem might be?
You have to update your controller for Tournaments so that it uses friendly.find method instead of the find.
# Change this:
Tournament.find(params[:id])
# to
Tournament.friendly.find(params[:id])

Generate slug when using ancestry gem

I'd like to create a slug based on the ancestors of the record. If I already have a slug created. The best solution I have come up with is:
def pretty_url
path.select(:slug).map(&:slug).join("-")
end
Is there a more precise way to do this using the ancestry gem?
Also, I am using friendly id to generate the slug, so maybe there is a better way using friendly id?
This is what I figured out, using friendly id and ancestry gem together.
friendly_id :slug_candidates, use: :slugged
def slug_candidates
[
[parent.try(:slug), :title]
]
end

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

how to display path with FriendlyId, rails

My task is to be able to see the path of the current category or product in browsing bar.
At this moment I just can see current category like this
localhost:3000/categories/smalcinataji
but I want like this
localhost:3000/categories/atkritumu-parstrades-tehnika/smalcinataji
To create pretty urls I am using gem called FriendlyId from this example http://railscasts.com/episodes/314-pretty-urls-with-friendlyid?view=asciicast
Thanks!
FriendlyId can take a method to construct the slug.
class Person < ActiveRecord::Base
friendly_id :category_and_subcategory
def category_and_subcategory
"#{my_category_method}/#{my_subcategory_method}"
end
end
Note that there might be an issue with routing due to the additional slash, but there's certainly a fix for this, too, if nescessary.

Resources