Skip to content

Commit

Permalink
added ability to not regenerate slugs on save, using :assign_slug? me…
Browse files Browse the repository at this point in the history
…thod on Mongoid object. See specs.
  • Loading branch information
fxposter committed May 8, 2012
1 parent a6bcebd commit 85b9a7d
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 32 deletions.
68 changes: 36 additions & 32 deletions lib/mongoid/slugify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,9 @@ module Slugify
included do
field :slug
index :slug, :unique => true
before_save :assign_slug
before_save :assign_slug, :if => :assign_slug?
end

def to_param
slug || super
end

private
def generate_slug
raise NotImplementedError
end

def generate_unique_slug
current_slug = generate_slug
pattern = /^#{Regexp.escape(current_slug)}(?:-(\d+))?$/

appropriate_class = self.class
while (appropriate_class.superclass.include?(Mongoid::Document))
appropriate_class = appropriate_class.superclass
end

existing_slugs = appropriate_class.where(:slug => pattern, :_id.ne => _id).only(:slug).map { |record| record.slug }
if existing_slugs.count > 0
max_counter = existing_slugs.map { |slug| (pattern.match(slug)[1] || 0).to_i }.max
current_slug << "-#{max_counter + 1}"
end

current_slug
end

def assign_slug
self.slug = generate_unique_slug
end

module ClassMethods
def find_by_slug(slug)
where(:slug => slug).first
Expand All @@ -60,5 +29,40 @@ def find_by_slug_or_id!(slug_or_id)
find_by_slug(slug_or_id) || find(slug_or_id)
end
end

def to_param
slug || super
end

private
def assign_slug?
true
end

def generate_slug
raise NotImplementedError
end

def generate_unique_slug
current_slug = generate_slug
pattern = /^#{Regexp.escape(current_slug)}(?:-(\d+))?$/

appropriate_class = self.class
while (appropriate_class.superclass.include?(Mongoid::Document))
appropriate_class = appropriate_class.superclass
end

existing_slugs = appropriate_class.where(:slug => pattern, :_id.ne => _id).only(:slug).map { |record| record.slug }
if existing_slugs.count > 0
max_counter = existing_slugs.map { |slug| (pattern.match(slug)[1] || 0).to_i }.max
current_slug << "-#{max_counter + 1}"
end

current_slug
end

def assign_slug
self.slug = generate_unique_slug
end
end
end
37 changes: 37 additions & 0 deletions spec/mongoid/slugify_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ def generate_slug
class ComicBook < Book
end

class CookBook < Book
private
def assign_slug?
slug.blank?
end
end

class Person
include Mongoid::Document
include Mongoid::Slugify
Expand Down Expand Up @@ -98,6 +105,36 @@ module Mongoid
end
end

context "when assign_slug? is configured to work only when slug is empty" do
let(:book) do
CookBook.create(:title => "A Thousand Plateaus")
end

it "generates a slug" do
book.to_param.should eql "a-thousand-plateaus"
end

it "does not update the slug" do
book.title = "Anti Oedipus"
book.save
book.to_param.should eql "a-thousand-plateaus"
end

it "updates the slug if it's nil" do
book.title = "Anti Oedipus"
book.slug = nil
book.save
book.to_param.should eql "anti-oedipus"
end

it "updates the slug if it's empty" do
book.title = "Anti Oedipus"
book.slug = ""
book.save
book.to_param.should eql "anti-oedipus"
end
end

context "when the slug is composed of multiple fields" do
let!(:author) do
Author.create(
Expand Down

0 comments on commit 85b9a7d

Please sign in to comment.