Coder Social home page Coder Social logo

sluggi's Introduction

Sluggi

Gem Version Build Status

Sluggi is a simple friendly_id-inspired slugging library for ActiveRecord models. It is faster than friendly_id (see below for benchmarks).

It provides basic slugs, slug history, and the ability to define multiple slug candidates.

Sluggi 1.x works with Rails 5.1+. Sluggi 0.5.x works with Rails 4.0-5.0.x. Make sure to view the 0.5-stable branch's Readme for those versions.

Install

Add this line to your Gemfile:

gem 'sluggi'

Add a string column named slug to any models you want to slug. You can generate a migration like so:

rails generate migration AddSlugToCats slug:string:uniq:index
rake db:migrate

To track slug history for any model, you must generate a migration to add the slugs table:

rails generate sluggi
rake db:migrate

Usage

Sluggi is Magic Free(tm). Each slugged model must:

  • Have a column named slug (see above).
  • Include the Sluggi::Slugged module
  • Override the slug_value method or the slug_candidates method.

Simple Slugged Model

Specify the slug value by defining #slug_value and #slug_value_changed?.

class Cat < ActiveRecord::Base
  include Sluggi::Slugged

  def slug_value
    name
  end

  def slug_value_changed?
    name_changed?
  end
end
cat = Cat.create(name: 'Tuxedo Stan')
cat.slug
=> 'tuxedo-stan'

cat.to_param
=> 'tuxedo-stan'

cat_path
=> 'cats/tuxedo-stan'

Cat.find_by_slug('tuxedo-stan')
=> cat

Model with Slugged History

To save slug history, include Sluggi::History. You get a slugs association. You can search for any slug in the history using .find_slug!.

You must also implement #saved_change_to_slug_value?.

class Cat < ActiveRecord::Base
  include Sluggi::Slugged
  include Sluggi::History

  def slug_value
    name
  end

  def slug_value_changed?
    name_changed?
  end

  def saved_change_to_slug_value?
    saved_change_to_name?
  end
end
cat = Cat.create(name: 'Tuxedo Stan')
cat.slug
=> 'tuxedo-stan'

cat.name = 'Tuxedo Bob'
cat.save
cat.slug
=> 'tuxedo-bob'

# use .find_slug! to search slug history:

Cat.find_slug!('tuxedo-bob')
=> cat
Cat.find_slug!('tuxedo-stan')
=> cat

# plain finders will not search history:

Cat.find_by_slug('tuxedo-bob')
=> cat

Cat.find_by_slug('tuxedo-stan')
=> RecordNotFound

Model with Slug Candidates

Override #slug_candidates to define cascading candidate values for slugs. This is useful to avoid uniqueness conflicts. Do not override #slug_value - the default implementation in Model will call #slug_candidates and works with or without History.

class Cat < ActiveRecord::Base
  include Sluggi::Slugged

  # The first unused value in the list is used.
  # Each item may be a value or a lambda.
  # Use a lambda to defer expensive unique value calculations.
  def slug_candidates
    [
      name,
      -> { "#{name}-#{Cat.count}" }
    ]
  end

  def slug_value_changed?
    name_changed?
  end
end
cat = Cat.create(name: 'Tuxedo Stan')
cat.slug
=> 'tuxedo-stan'

cat_2 = Cat.create(name: 'Tuxedo Stan')
cat_2.slug
=> 'tuxedo-stan-456'

Performance

Run the benchmark script: ruby bench.rb. This script is based on the benchmark script from friendly_id.

Here are some anecdotal results using ruby 2.5.3:

                                                  SLUGGI      FRIENDLY_ID
1) find (id) - direct ActiveRecord                0.092318    0.093049
2) find (in-table slug)                           0.102773    0.259542
3) find (in-table slug; using finders module)     0.098183    0.108248
4) find (external slug)                           0.670229    0.832791
5) insert (plain AR / no slug)                    0.345077    0.345105
6) insert (in-table-slug)                         0.666451    0.815505
7) insert (in-table-slug; using finders module)   0.668737    0.744433
8) insert (external slug)                         2.480790    2.849761

Notes:

Sluggi is at least 10% faster in every benchmark.

  1. Baseline (does not use either gem)
  2. 0.44x
  3. 0.90x
  4. 0.80x
  5. Baseline (does not use either gem)
  6. 0.82x
  7. 0.90x
  8. 0.87x

Alternatives

sluggi's People

Contributors

teeparham avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

sluggi's Issues

Break validations into separate modules

There are times when the validations in Slugged aren't exactly what you want. For example you might want the uniqueness validation to be scoped. One way to make it more flexible would be to put the validations in separate modules:

ValidatesSlugPresence
ValidatesSlugUniqueness

etc.

We could move the methods from Slugged to SluggedLite.

Then Slugged could just include the validation modules and the SluggedLite module.

Users can include Slugged in their models to get the current behavior, or just include SluggedLite and pick and choose the validation modules they want.

Possible to customize slug creation logic?

Thanks for the great gem!

I'm just exploring the API and looking for ways to customize slug generation/creation algorithm.

I already have an app with slugs and I'd like to switch it to sluggi.

I'd like all the old slugs to stay the same.

Where should I look or what's the easiest way to change how slugs are being created?

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.