Last active
May 10, 2023 10:05
-
-
Save pietromoro/6cfbd500b8cec4b79e1383f6ebccba32 to your computer and use it in GitHub Desktop.
Sluggable rails concern: use slugs instead of ids in the url!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module Sluggable | |
| extend ActiveSupport::Concern | |
| cattr_reader :slugging | |
| included do | |
| before_save :generate_slug | |
| def self.sluggable | |
| all.extending(Sluggable::Finder) | |
| end | |
| def self.slugging attribute | |
| @@slugging = attribute.to_sym | |
| end | |
| end | |
| def to_param? | |
| return nil unless persisted? | |
| slug | |
| end | |
| module Finder | |
| def find(*args) | |
| id = args.first | |
| return super if args.count != 1 | |
| resource = resource_by_slug(id) | |
| resource ||= super | |
| raise ActiveRecord::RecordNotFound unless resource | |
| resource | |
| end | |
| private | |
| def resource_by_slug(id) | |
| find_by(slug: id) | |
| end | |
| end | |
| private | |
| def generate_slug | |
| return unless send("#{slugging}_changed?".to_sym) | |
| self.slug = send(slugging).parameterize | |
| end | |
| end |
Author
Hey! yes, you are right, I came across the same problem long time ago and always forgot to fix it in this gist. Did it now! Thanks for the heads up!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I ran into some issues implementing this. The @@slugging is a class variable shared throughout the classes that includes the Slug concern. This becomes an issue if I want to use the concern on more than one class, for example:
When rails loads my classes, the
sluggingmethod sets the @@slugging == :name at first and then sets @@slugging == :alias, making it only work when I am dealing with Company objects. If I want to update the slug of a Person, I get aundefined method 'alias_changed?'error for a Person.I think that the best approach would be defining the class variable for each class using the concern with an
cattr_accessor.