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
Related
I have the friendly_id gem installed and it works great. My issue is I have comments that have polymorphic relations to several other things, like blogs. I set up the comments to be found by the id of both, for example blog id, then comment id. Like so in my comments controller:
def load_commentable
resource, id = request.path.split('/')[1,2]
#commentable = resource.singularize.classify.constantize.find(id)
end
My problem is now that I have friendly ids for everything, this is no longer working. It's pulling the friendly id, of course.
Couldn't find Blog with 'id'=cobra-kai-here-we-go-again
How can I fix this so it finds the resource the comment belongs to by the friendly id?
I would keep a separation between the id and the friendly_id so the id is not overwritten by default and can still be used in model relationship while the friendly_id from the controllers only by using the Model.friendly.find('id') syntax.
Check this change in friendly_id gem in version 5.0
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.
I have a Company Model, and i am using friendly_id like this
friendly_id :name, use: :slugged
But since there can be many Company with the same name (different branches). I am trying to handle that case by using city attribute from the address of the Company.
But the Company address is stored in a different table Address.
so company.address.city gives me the city of the company.
friendly_id :slug_candidates, use: :slugged
# Try building a slug based on the following fields in
# increasing order of specificity.
def slug_candidates
[
:name,
[:name, :city]
]
end
I'm aware i can do something like above. But since city is not an attribute of company how can i achieve this?
Update:
Possible solution for this is to create a helper method city which returns the company's city.
But the problem never was that.
The version of friendly_id i am using is 4.0.10.1
and the feature which enables the usage of slug_candidates are available in versions 5 and above.
I tried updating the gem. But it wont get updated as version 5 has dependency on activerecord 4.0 and rails has dependency on activerecord 3.2.13
It's kind of a deadlock. Don't know what to do
class Company < ActiveRecord::Base
.............................
def city
self.address.city
end
end
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
I want to be able in browsing bar see full path to some product. The path would look like this
www.mysite.com/categories/category_name/subcategory_name/product_name
At this moment I have just
www.mysite.com/categories/category_name
It just provides with one level path, that I don't need.
To build these friendly links I used friendly_id. And full categorization function I created using gem called Ancestry.
How can I modify friendly_id slug so that I can show the full path? I know how the friendly_id works, but I don't know how to change the way how slug is generated.
Some guys could just give me link or tip to search for. I can work it out, I just need idea.
I would be very greatfull :) :)
You can pass a method for the gem to use, as in:
extend FriendlyId
friendly_id :method_name, use: :slugged
def method_name
end
You're probably looking for nested resouces.
If both models (category, subcategory) have slugs, nesting them in your routes.rb file should do the trick:
resources :categories do
resources :subcategories
end