Slugable
- adds support for creating seo friendly url to your active record models and simplifies generating url
- gem is tests against rails 3.2, 4.0, 4.1, 4.2 and ruby 1.9.3. and 2.2.2
# model
class Article < ActiveRecord::Base
# has columns: id, name, slug
has_slug
end
# creating new
item = Article.create!(name: 'First article')
item.slug # => 'first-article'
item.to_slug # => 'first-article'
# routes to the article
get "articles/:slug" => "articles#show", as: :article
# view
link_to 'My first article', article_path(item.to_slug) # => '/articles/first-article'
Installation
Add this line to your application's Gemfile:
gem 'slugable'
And then execute:
$ bundle
Or install it yourself as:
$ gem install slugable
Usage
- default configuration converts name column to slug column and formatted by parameterize method from active support
- it internally use callbacks to do the job
- it also adds several convenient methods for generating url parts
to_slug
,to_slug_was
,to_slug_will
class Item < ActiveRecord::Base
# columns :name, :slug
has_slug # default from: :name, to: :slug
end
# then in code
item = Item.create!(name: "my name is")
item.slug # => "my-name-is"
item.to_slug # => "my-name-is"
item.slug = "new-slug"
item.to_slug_was # => "my-name-is"
item.to_slug_will # => "new-slug"
item.to_slug # => "new-slug"
you can override defaults by passing hash
class Page < ActiveRecord::Base
# has columns: :id, :title, :seo_url
has_slug from: :title, to: :seo_url, formatter: lambda { |string| string.downcase }
end
# then in code
page = Page.create!(title: "NAME")
page.seo_url # => "name"
page.to_seo_url # => "name"
if model is a tree structure and you use ancestry gem, tree like structure will be generated
class Category < ActiveRecord::Base
# has columns: :id, :name, :slug
has_ancestry
has_slug
end
# then in code
root = Category.create!(name: "root", slug: "root")
root.slug # => "root"
root.to_slug # => ["root"]
child = Category.new(name: "child", slug: "child")
child.parent = root
child.save!
child.slug # => "child"
child.to_slug # => ["root", "child"]
branch = Category.create!(name: "branch", slug: "branch")
child.parent = branch
child.slug = "renamed"
child.to_slug_was # => ["root", "child"]
child.to_slug_will # => ["branch", "renamed"]
child.to_slug # => ["root", "child"]
child.save!
child.to_slug # => ["branch", "renamed"]
- You can cache slug for tree structure if you want to optimize performance, all you need is to pass cache storage object
class Category < ActiveRecord::Base
# has columns: :id, :name, :slug
has_ancestry
has_slug tree_cache_storage: Rails.cache
end
Configuration
You can set up default formatter and default tree_cache_storage in you initializer.
class MyFormatter
def self.call(string)
string.my_own_parameterize
end
end
Slugable.configure do |config|
config.formatter = MyFormatter
config.tree_cache_storage = Rails.cache
end
to_slug
, to_slug_was
and to_slug_will
methods are implemented by to_slug_builder. You can implement you own one and pass as configuration
# you own to slug builder
class StupidToSlug
def to_slug(record)
"to_slug_#{record.id}"
end
def to_slug_was(record)
"to_slug_was_#{record.id}"
end
def to_slug_will(record)
"to_slug_will_#{record.id}"
end
end
# model
class News < ActiveRecord::Base
# columns: :id, :name, :slug
has_slug to_slug_builder: StupidToSlug.new
end
# code
news = News.create!(name: 'whatever')
news.to_slug # => "to_slug_#{news.id}"
news.to_slug_was # => "to_slug_was_#{news.id}"
news.to_slug_will # => "to_slug_will_#{news.id}"
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request