mongoid_slug 0.4.7 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +12 -23
- data/lib/mongoid/slug/version.rb +1 -1
- data/lib/mongoid/slug.rb +49 -43
- data/spec/models/book.rb +0 -2
- data/spec/models/{baz.rb → partner.rb} +2 -3
- data/spec/models/person.rb +2 -2
- data/spec/models/relationship.rb +8 -0
- data/spec/mongoid/slug_spec.rb +110 -229
- data/spec/spec_helper.rb +1 -0
- metadata +38 -39
- data/spec/models/bar.rb +0 -8
- data/spec/models/foo.rb +0 -8
- data/spec/models/permanent.rb +0 -6
- data/spec/models/publisher.rb +0 -9
- data/spec/models/sar.rb +0 -7
    
        data/README.md
    CHANGED
    
    | @@ -1,19 +1,16 @@ | |
| 1 1 | 
             
            Mongoid Slug
         | 
| 2 2 | 
             
            ============
         | 
| 3 3 |  | 
| 4 | 
            -
            Mongoid Slug generates a URL slug or permalink based on  | 
| 4 | 
            +
            Mongoid Slug generates a URL slug or permalink based on one or more fields in a Mongoid model. It sits on top of [stringex](https://github.com/rsl/stringex) and works with non-Latin characters.
         | 
| 5 5 |  | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 6 | 
            +
            Quick Start
         | 
| 7 | 
            +
            ---------------
         | 
| 8 8 |  | 
| 9 | 
            -
             | 
| 9 | 
            +
            First, add mongoid_slug to your Gemfile:
         | 
| 10 10 |  | 
| 11 11 | 
             
                gem 'mongoid_slug', :require => 'mongoid/slug'
         | 
| 12 12 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
            -----
         | 
| 15 | 
            -
             | 
| 16 | 
            -
            Here's a book that embeds many authors:
         | 
| 13 | 
            +
            Say you have a book that embeds many authors. You can set up slugs for both resources like this:
         | 
| 17 14 |  | 
| 18 15 | 
             
                class Book
         | 
| 19 16 | 
             
                  include Mongoid::Document
         | 
| @@ -32,36 +29,28 @@ Here's a book that embeds many authors: | |
| 32 29 | 
             
                  embedded_in :book, :inverse_of => :authors
         | 
| 33 30 | 
             
                end
         | 
| 34 31 |  | 
| 35 | 
            -
             | 
| 32 | 
            +
            In your controller, you can use the `find_by_slug` helper:
         | 
| 36 33 |  | 
| 37 34 | 
             
                def find_book
         | 
| 38 | 
            -
                   | 
| 35 | 
            +
                  Book.find_by_slug(params[:book_id])
         | 
| 39 36 | 
             
                end
         | 
| 40 37 |  | 
| 41 | 
            -
                def  | 
| 42 | 
            -
                  @book | 
| 43 | 
            -
                  @author = @book.authors.where(:slug => params[:id]).first
         | 
| 38 | 
            +
                def find_author
         | 
| 39 | 
            +
                  @book.authors.find_by_slug(params[:id])
         | 
| 44 40 | 
             
                end
         | 
| 45 41 |  | 
| 46 | 
            -
            If you are wondering why I did not include a *find_by_slug* helper, [read on](http://groups.google.com/group/mongoid/browse_thread/thread/5905589e108d7cc0?pli=1).
         | 
| 47 | 
            -
             | 
| 48 42 | 
             
            To demo some more functionality in the console:
         | 
| 49 43 |  | 
| 50 44 | 
             
                >> book = Book.create(:title => "A Thousand Plateaus")
         | 
| 51 45 | 
             
                >> book.to_param
         | 
| 52 46 | 
             
                "a-thousand-plateaus"
         | 
| 53 | 
            -
                >> book. | 
| 47 | 
            +
                >> book.title = "Anti Oedipus"
         | 
| 48 | 
            +
                >> book.save
         | 
| 54 49 | 
             
                >> book.to_param
         | 
| 55 50 | 
             
                "anti-oedipus"
         | 
| 56 | 
            -
                >> Book.where(:slug => 'anti-oedipus').first
         | 
| 57 | 
            -
                #<Book _id: 4c23b1f7faa4a7479a000009, slug: "anti-oedipus", title: "Anti Oedipus">
         | 
| 58 51 | 
             
                >> author = book.authors.create(:first_name => "Gilles", :last_name => "Deleuze")
         | 
| 59 52 | 
             
                >> author.to_param
         | 
| 60 53 | 
             
                => "gilles-deleuze"
         | 
| 61 54 | 
             
                >> author.update_attributes(:first => "Félix", :last_name => "Guattari")
         | 
| 62 55 | 
             
                >> author.to_param
         | 
| 63 | 
            -
                => " | 
| 64 | 
            -
                >> book.authors.where(:slug => 'felix-guattari).first
         | 
| 65 | 
            -
                => #<Author _id: 4c31e362faa4a7050e000003, slug: "félix-guattari", last_name: "Guattari", first_name: "Félix">
         | 
| 66 | 
            -
             | 
| 67 | 
            -
            See [sample models in specs]("http://github.com/papercavalier/mongoid-slug/tree/master/spec/models/") for various configuration options.
         | 
| 56 | 
            +
                => "felix-guattari"
         | 
    
        data/lib/mongoid/slug/version.rb
    CHANGED
    
    
    
        data/lib/mongoid/slug.rb
    CHANGED
    
    | @@ -1,76 +1,65 @@ | |
| 1 1 | 
             
            #encoding: utf-8
         | 
| 2 | 
            +
            require 'stringex'
         | 
| 3 | 
            +
             | 
| 2 4 | 
             
            module Mongoid #:nodoc:
         | 
| 3 5 |  | 
| 4 | 
            -
              # Generates a URL slug | 
| 6 | 
            +
              # Generates a URL slug or permalink based on one or more fields in a Mongoid
         | 
| 7 | 
            +
              # model.
         | 
| 5 8 | 
             
              module Slug
         | 
| 6 9 | 
             
                extend ActiveSupport::Concern
         | 
| 7 10 |  | 
| 8 11 | 
             
                included do
         | 
| 9 | 
            -
                  cattr_accessor :slug_name, :slugged_fields | 
| 12 | 
            +
                  cattr_accessor :slug_name, :slugged_fields
         | 
| 10 13 | 
             
                end
         | 
| 11 14 |  | 
| 12 15 | 
             
                module ClassMethods
         | 
| 13 16 |  | 
| 14 | 
            -
                  #  | 
| 15 | 
            -
                   | 
| 16 | 
            -
             | 
| 17 | 
            +
                  # Sets one ore more fields as source of slug.
         | 
| 18 | 
            +
                  #
         | 
| 19 | 
            +
                  # By default, the name of the field that stores the slug is "slug". Pass an
         | 
| 20 | 
            +
                  # alternative name with the :as option.
         | 
| 21 | 
            +
                  #
         | 
| 22 | 
            +
                  # If you wish the slug to be permanent once created, set :permanent to true.
         | 
| 23 | 
            +
                  def slug(*fields)
         | 
| 24 | 
            +
                    options = fields.extract_options!
         | 
| 17 25 |  | 
| 18 | 
            -
                    self.slug_name | 
| 19 | 
            -
                    self. | 
| 20 | 
            -
                    self.slugged_fields = args
         | 
| 26 | 
            +
                    self.slug_name      = options[:as] || :slug
         | 
| 27 | 
            +
                    self.slugged_fields = fields
         | 
| 21 28 |  | 
| 22 29 | 
             
                    field slug_name
         | 
| 23 30 |  | 
| 24 | 
            -
                    if slug_scoped
         | 
| 25 | 
            -
                      index slug_name
         | 
| 26 | 
            -
                    else
         | 
| 27 | 
            -
                      index slug_name, :unique => true
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 31 | 
             
                    if options[:permanent]
         | 
| 31 32 | 
             
                      before_create :generate_slug
         | 
| 32 33 | 
             
                    else
         | 
| 33 34 | 
             
                      before_save :generate_slug
         | 
| 34 35 | 
             
                    end
         | 
| 35 36 | 
             
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # Finds the document with the specified slug or returns nil.
         | 
| 39 | 
            +
                  def find_by_slug(slug)
         | 
| 40 | 
            +
                    where(slug_name => slug).first rescue nil
         | 
| 41 | 
            +
                  end
         | 
| 36 42 | 
             
                end
         | 
| 37 43 |  | 
| 38 44 | 
             
                def to_param
         | 
| 39 | 
            -
                  self.send | 
| 45 | 
            +
                  self.send(slug_name)
         | 
| 40 46 | 
             
                end
         | 
| 41 47 |  | 
| 42 48 | 
             
                private
         | 
| 43 49 |  | 
| 44 | 
            -
                 | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
                    else
         | 
| 49 | 
            -
                      stack << association_name
         | 
| 50 | 
            -
                      _parent.send :find_, slug, stack
         | 
| 51 | 
            -
                    end
         | 
| 52 | 
            -
                  else
         | 
| 53 | 
            -
                    stack.reverse!
         | 
| 54 | 
            -
                    path = (stack + [slug_name]).join(".")
         | 
| 55 | 
            -
                    found = collection.find(path => slug).to_a
         | 
| 56 | 
            -
                
         | 
| 57 | 
            -
                    stack.each do |name|
         | 
| 58 | 
            -
                      if found.any?
         | 
| 59 | 
            -
                        found = found.first.send(name).to_a
         | 
| 60 | 
            -
                      end
         | 
| 61 | 
            -
                    end
         | 
| 62 | 
            -
                
         | 
| 63 | 
            -
                    found
         | 
| 64 | 
            -
                  end
         | 
| 50 | 
            +
                attr_reader :slug_counter
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def build_slug
         | 
| 53 | 
            +
                  ("#{slug_base} #{slug_counter}").to_url
         | 
| 65 54 | 
             
                end
         | 
| 66 55 |  | 
| 67 | 
            -
                def find_unique_slug | 
| 68 | 
            -
                  slug =  | 
| 69 | 
            -
                  if  | 
| 56 | 
            +
                def find_unique_slug
         | 
| 57 | 
            +
                  slug = build_slug
         | 
| 58 | 
            +
                  if unique_slug?(slug)
         | 
| 70 59 | 
             
                    slug
         | 
| 71 60 | 
             
                  else
         | 
| 72 | 
            -
                     | 
| 73 | 
            -
                    find_unique_slug | 
| 61 | 
            +
                    increment_slug_counter
         | 
| 62 | 
            +
                    find_unique_slug
         | 
| 74 63 | 
             
                  end
         | 
| 75 64 | 
             
                end
         | 
| 76 65 |  | 
| @@ -80,14 +69,31 @@ module Mongoid #:nodoc: | |
| 80 69 | 
             
                  end
         | 
| 81 70 | 
             
                end
         | 
| 82 71 |  | 
| 72 | 
            +
                def increment_slug_counter
         | 
| 73 | 
            +
                  @slug_counter = (slug_counter.to_i + 1).to_s
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 83 76 | 
             
                def slug_base
         | 
| 84 | 
            -
                  self.class.slugged_fields. | 
| 77 | 
            +
                  self.class.slugged_fields.map do |field|
         | 
| 78 | 
            +
                    self.send(field)
         | 
| 79 | 
            +
                  end.join(" ")
         | 
| 85 80 | 
             
                end
         | 
| 86 81 |  | 
| 87 82 | 
             
                def slugged_fields_changed?
         | 
| 88 83 | 
             
                  self.class.slugged_fields.any? do |field|
         | 
| 89 | 
            -
                    self.send(field | 
| 84 | 
            +
                    self.send("#{field}_changed?")
         | 
| 90 85 | 
             
                  end
         | 
| 91 86 | 
             
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def unique_slug?(slug)
         | 
| 89 | 
            +
                  if embedded?
         | 
| 90 | 
            +
                    _parent.send(association_name)
         | 
| 91 | 
            +
                  else
         | 
| 92 | 
            +
                    self.class
         | 
| 93 | 
            +
                  end.
         | 
| 94 | 
            +
                    where(slug_name => slug).
         | 
| 95 | 
            +
                    reject { |doc| doc.id == self.id }.
         | 
| 96 | 
            +
                    empty?
         | 
| 97 | 
            +
                end
         | 
| 92 98 | 
             
              end
         | 
| 93 99 | 
             
            end
         | 
    
        data/spec/models/book.rb
    CHANGED
    
    
    
        data/spec/models/person.rb
    CHANGED
    
    
    
        data/spec/mongoid/slug_spec.rb
    CHANGED
    
    | @@ -2,317 +2,198 @@ | |
| 2 2 | 
             
            require "spec_helper"
         | 
| 3 3 |  | 
| 4 4 | 
             
            module Mongoid
         | 
| 5 | 
            -
             | 
| 6 5 | 
             
              describe Slug do
         | 
| 6 | 
            +
                let!(:book) do
         | 
| 7 | 
            +
                  Book.create(:title => "A Thousand Plateaus")
         | 
| 8 | 
            +
                end
         | 
| 7 9 |  | 
| 8 | 
            -
                 | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
                  it "generates slug" do
         | 
| 13 | 
            -
                    book.to_param.should eql book.title.parameterize
         | 
| 14 | 
            -
                  end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                  it "updates slug" do
         | 
| 17 | 
            -
                    book.update_attributes(:title => "Anti Oedipus")
         | 
| 18 | 
            -
                    book.to_param.should eql "Anti Oedipus".parameterize
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  it "generates a unique slug" do
         | 
| 22 | 
            -
                    similar_book = Book.create(:title => book.title)
         | 
| 23 | 
            -
                    similar_book.to_param.should_not eql book.to_param
         | 
| 10 | 
            +
                context "when the object is top-level" do
         | 
| 11 | 
            +
                  it "generates a slug" do
         | 
| 12 | 
            +
                    book.to_param.should eql "a-thousand-plateaus"
         | 
| 24 13 | 
             
                  end
         | 
| 25 14 |  | 
| 26 | 
            -
                  it " | 
| 27 | 
            -
                     | 
| 28 | 
            -
                     | 
| 15 | 
            +
                  it "updates the slug" do
         | 
| 16 | 
            +
                    book.title = "Anti Oedipus"
         | 
| 17 | 
            +
                    book.save
         | 
| 18 | 
            +
                    book.to_param.should eql "anti-oedipus"
         | 
| 29 19 | 
             
                  end
         | 
| 30 20 |  | 
| 31 | 
            -
                  it " | 
| 32 | 
            -
                     | 
| 21 | 
            +
                  it "generates a unique slug by appending a counter to duplicate text" do
         | 
| 22 | 
            +
                    dup = Book.create(:title => book.title)
         | 
| 23 | 
            +
                    dup.to_param.should eql "a-thousand-plateaus-1"
         | 
| 33 24 | 
             
                  end
         | 
| 34 25 |  | 
| 35 26 | 
             
                  it "does not update slug if slugged fields have not changed" do
         | 
| 36 | 
            -
                     | 
| 37 | 
            -
                    book. | 
| 38 | 
            -
                    book.to_param.should eql former_slug
         | 
| 27 | 
            +
                    book.save
         | 
| 28 | 
            +
                    book.to_param.should eql "a-thousand-plateaus"
         | 
| 39 29 | 
             
                  end
         | 
| 40 30 |  | 
| 41 | 
            -
                  it "does not  | 
| 42 | 
            -
                     | 
| 43 | 
            -
                    book. | 
| 44 | 
            -
                    book.to_param.should eql  | 
| 31 | 
            +
                  it "does not change slug if slugged fields have changed but generated slug is identical" do
         | 
| 32 | 
            +
                    book.title = "a thousand plateaus"
         | 
| 33 | 
            +
                    book.save
         | 
| 34 | 
            +
                    book.to_param.should eql "a-thousand-plateaus"
         | 
| 45 35 | 
             
                  end
         | 
| 46 36 |  | 
| 47 37 | 
             
                  it "finds by slug" do
         | 
| 48 | 
            -
                    Book. | 
| 38 | 
            +
                    Book.find_by_slug(book.to_param).should eql book
         | 
| 49 39 | 
             
                  end
         | 
| 50 | 
            -
             | 
| 51 40 | 
             
                end
         | 
| 52 41 |  | 
| 53 | 
            -
                context "when  | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
                  it "generates slug" do
         | 
| 58 | 
            -
                    subject.to_param.should eql(subject.name.parameterize)
         | 
| 42 | 
            +
                context "when the object is embedded" do
         | 
| 43 | 
            +
                  let(:subject) do
         | 
| 44 | 
            +
                    book.subjects.create(:name => "Psychoanalysis")
         | 
| 59 45 | 
             
                  end
         | 
| 60 46 |  | 
| 61 | 
            -
                  it " | 
| 62 | 
            -
                    subject. | 
| 63 | 
            -
                    subject.to_param.should eql "Schizoanalysis".parameterize
         | 
| 47 | 
            +
                  it "generates a slug" do
         | 
| 48 | 
            +
                    subject.to_param.should eql "psychoanalysis"
         | 
| 64 49 | 
             
                  end
         | 
| 65 50 |  | 
| 66 | 
            -
                  it " | 
| 67 | 
            -
                     | 
| 68 | 
            -
                     | 
| 51 | 
            +
                  it "updates the slug" do
         | 
| 52 | 
            +
                    subject.name = "Schizoanalysis"
         | 
| 53 | 
            +
                    subject.save
         | 
| 54 | 
            +
                    subject.to_param.should eql "schizoanalysis"
         | 
| 69 55 | 
             
                  end
         | 
| 70 56 |  | 
| 71 | 
            -
                  it " | 
| 72 | 
            -
                     | 
| 73 | 
            -
                     | 
| 74 | 
            -
                  end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  it "does not append a counter when slug is unique" do
         | 
| 77 | 
            -
                    subject.to_param.should_not match /\d$/
         | 
| 57 | 
            +
                  it "generates a unique slug by appending a counter to duplicate text" do
         | 
| 58 | 
            +
                    dup = book.subjects.create(:name => subject.name)
         | 
| 59 | 
            +
                    dup.to_param.should eql 'psychoanalysis-1'
         | 
| 78 60 | 
             
                  end
         | 
| 79 61 |  | 
| 80 62 | 
             
                  it "does not update slug if slugged fields have not changed" do
         | 
| 81 | 
            -
                     | 
| 82 | 
            -
                    subject. | 
| 83 | 
            -
                    subject.to_param.should eql former_slug
         | 
| 63 | 
            +
                    subject.save
         | 
| 64 | 
            +
                    subject.to_param.should eql "psychoanalysis"
         | 
| 84 65 | 
             
                  end
         | 
| 85 66 |  | 
| 86 | 
            -
                  it "does not  | 
| 87 | 
            -
                     | 
| 88 | 
            -
                    subject. | 
| 89 | 
            -
                    subject.to_param.should eql former_slug
         | 
| 67 | 
            +
                  it "does not change slug if slugged fields have changed but generated slug is identical" do
         | 
| 68 | 
            +
                    subject.name = "PSYCHOANALYSIS"
         | 
| 69 | 
            +
                    subject.to_param.should eql "psychoanalysis"
         | 
| 90 70 | 
             
                  end
         | 
| 91 71 |  | 
| 92 72 | 
             
                  it "finds by slug" do
         | 
| 93 | 
            -
                    book.subjects. | 
| 73 | 
            +
                    book.subjects.find_by_slug(subject.to_param).should eql subject
         | 
| 94 74 | 
             
                  end
         | 
| 95 | 
            -
             | 
| 96 75 | 
             
                end
         | 
| 97 76 |  | 
| 98 | 
            -
                context "when  | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
                  it "generates slug" do
         | 
| 103 | 
            -
                    publisher.to_param.should eql(publisher.name.parameterize)
         | 
| 104 | 
            -
                  end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                  it "updates slug" do
         | 
| 107 | 
            -
                    publisher.update_attributes(:name => "Harvard UP")
         | 
| 108 | 
            -
                    publisher.to_param.should eql "Harvard UP".parameterize
         | 
| 77 | 
            +
                context "when the object is embedded in another embedded object" do
         | 
| 78 | 
            +
                  let(:person) do
         | 
| 79 | 
            +
                    Person.create(:name => "John Doe")
         | 
| 109 80 | 
             
                  end
         | 
| 110 81 |  | 
| 111 | 
            -
                   | 
| 112 | 
            -
                     | 
| 113 | 
            -
                    publisher.update_attributes(:year => 2001)
         | 
| 114 | 
            -
                    publisher.to_param.should eql former_slug
         | 
| 82 | 
            +
                  let(:relationship) do
         | 
| 83 | 
            +
                    person.relationships.create(:name => "Engagement")
         | 
| 115 84 | 
             
                  end
         | 
| 116 85 |  | 
| 117 | 
            -
                   | 
| 118 | 
            -
                     | 
| 119 | 
            -
                    publisher.update_attributes(:name => "oup")
         | 
| 120 | 
            -
                    publisher.to_param.should eql former_slug
         | 
| 86 | 
            +
                  let(:partner) do
         | 
| 87 | 
            +
                    relationship.partners.create(:name => "Jane Smith")
         | 
| 121 88 | 
             
                  end
         | 
| 122 89 |  | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
                context "when the slug is composed of multiple fields" do
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                  let(:author) { Author.create(:first_name => "Gilles", :last_name => "Deleuze") }
         | 
| 128 | 
            -
             | 
| 129 | 
            -
                  it "generates slug" do
         | 
| 130 | 
            -
                    author.to_param.should eql("Gilles Deleuze".parameterize)
         | 
| 90 | 
            +
                  it "generates a slug" do
         | 
| 91 | 
            +
                    partner.to_param.should eql "jane-smith"
         | 
| 131 92 | 
             
                  end
         | 
| 132 93 |  | 
| 133 | 
            -
                  it "updates slug" do
         | 
| 134 | 
            -
                     | 
| 135 | 
            -
                     | 
| 94 | 
            +
                  it "updates the slug" do
         | 
| 95 | 
            +
                    partner.name = "Jane Doe"
         | 
| 96 | 
            +
                    partner.save
         | 
| 97 | 
            +
                    partner.to_param.should eql "jane-doe"
         | 
| 136 98 | 
             
                  end
         | 
| 137 99 |  | 
| 138 | 
            -
                  it "generates a unique slug" do
         | 
| 139 | 
            -
                     | 
| 140 | 
            -
             | 
| 141 | 
            -
                    similar_author.to_param.should_not eql author.to_param
         | 
| 100 | 
            +
                  it "generates a unique slug by appending a counter to duplicate text" do
         | 
| 101 | 
            +
                    dup = relationship.partners.create(:name => partner.name)
         | 
| 102 | 
            +
                    dup.to_param.should eql "jane-smith-1"
         | 
| 142 103 | 
             
                  end
         | 
| 143 104 |  | 
| 144 | 
            -
                  it " | 
| 145 | 
            -
                     | 
| 146 | 
            -
             | 
| 147 | 
            -
                    similar_author.to_param.should match /\d$/
         | 
| 105 | 
            +
                  it "does not update slug if slugged fields have not changed" do
         | 
| 106 | 
            +
                    partner.save
         | 
| 107 | 
            +
                    partner.to_param.should eql "jane-smith"
         | 
| 148 108 | 
             
                  end
         | 
| 149 109 |  | 
| 150 | 
            -
                  it "does not  | 
| 151 | 
            -
                     | 
| 110 | 
            +
                  it "does not change slug if slugged fields have changed but generated slug is identical" do
         | 
| 111 | 
            +
                    partner.name = "JANE SMITH"
         | 
| 112 | 
            +
                    partner.to_param.should eql "jane-smith"
         | 
| 152 113 | 
             
                  end
         | 
| 153 114 |  | 
| 154 | 
            -
                  it " | 
| 155 | 
            -
                     | 
| 156 | 
            -
                     | 
| 157 | 
            -
                     | 
| 115 | 
            +
                  it "scopes by parent object" do
         | 
| 116 | 
            +
                    affair = person.relationships.create(:name => "Affair")
         | 
| 117 | 
            +
                    lover = affair.partners.create(:name => partner.name)
         | 
| 118 | 
            +
                    lover.to_param.should eql partner.to_param
         | 
| 158 119 | 
             
                  end
         | 
| 159 120 |  | 
| 160 121 | 
             
                  it "finds by slug" do
         | 
| 161 | 
            -
                     | 
| 162 | 
            -
                    Author.where(:slug => "gilles-deleuze").first.should eql author
         | 
| 122 | 
            +
                    relationship.partners.find_by_slug(partner.to_param).should eql partner
         | 
| 163 123 | 
             
                  end
         | 
| 164 | 
            -
             | 
| 165 124 | 
             
                end
         | 
| 166 125 |  | 
| 167 | 
            -
                context "when the  | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
                    bar.bazes.create(:name => "baz")
         | 
| 173 | 
            -
                    Foo.first.bars.first.bazes.first # Better to be paranoid and reload from db
         | 
| 174 | 
            -
                  end
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                  it "generates slug" do
         | 
| 177 | 
            -
                    baz.to_param.should eql(baz.name.parameterize)
         | 
| 178 | 
            -
                  end
         | 
| 179 | 
            -
             | 
| 180 | 
            -
                  it "updates slug" do
         | 
| 181 | 
            -
                    baz.update_attributes(:name => "lorem")
         | 
| 182 | 
            -
                    baz.to_param.should eql "lorem".parameterize
         | 
| 183 | 
            -
                  end
         | 
| 184 | 
            -
             | 
| 185 | 
            -
                  it "generates a unique slug" do
         | 
| 186 | 
            -
                    similar_baz = bar.bazes.create(:name => baz.name)
         | 
| 187 | 
            -
                    similar_baz.to_param.should_not eql baz.to_param
         | 
| 126 | 
            +
                context "when the slug is composed of multiple fields" do
         | 
| 127 | 
            +
                  let!(:author) do
         | 
| 128 | 
            +
                    Author.create(
         | 
| 129 | 
            +
                      :first_name => "Gilles",
         | 
| 130 | 
            +
                      :last_name  => "Deleuze")
         | 
| 188 131 | 
             
                  end
         | 
| 189 132 |  | 
| 190 | 
            -
                  it " | 
| 191 | 
            -
                     | 
| 192 | 
            -
                    similar_baz.to_param.should match /\d$/
         | 
| 133 | 
            +
                  it "generates a slug" do
         | 
| 134 | 
            +
                    author.to_param.should eql "gilles-deleuze"
         | 
| 193 135 | 
             
                  end
         | 
| 194 136 |  | 
| 195 | 
            -
                  it " | 
| 196 | 
            -
                     | 
| 137 | 
            +
                  it "updates the slug" do
         | 
| 138 | 
            +
                    author.first_name = "Félix"
         | 
| 139 | 
            +
                    author.last_name  = "Guattari"
         | 
| 140 | 
            +
                    author.save
         | 
| 141 | 
            +
                    author.to_param.should eql "felix-guattari"
         | 
| 197 142 | 
             
                  end
         | 
| 198 143 |  | 
| 199 | 
            -
                  it " | 
| 200 | 
            -
                     | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 144 | 
            +
                  it "generates a unique slug by appending a counter to duplicate text" do
         | 
| 145 | 
            +
                    dup = Author.create(
         | 
| 146 | 
            +
                      :first_name => author.first_name,
         | 
| 147 | 
            +
                      :last_name  => author.last_name)
         | 
| 148 | 
            +
                    dup.to_param.should eql 'gilles-deleuze-1'
         | 
| 203 149 | 
             
                  end
         | 
| 204 150 |  | 
| 205 | 
            -
                  it "does not update slug if slugged fields have changed but generated slug is  | 
| 206 | 
            -
                     | 
| 207 | 
            -
                     | 
| 208 | 
            -
                     | 
| 151 | 
            +
                  it "does not update slug if slugged fields have changed but generated slug is identical" do
         | 
| 152 | 
            +
                    author.last_name = "DELEUZE"
         | 
| 153 | 
            +
                    author.save
         | 
| 154 | 
            +
                    author.to_param.should eql 'gilles-deleuze'
         | 
| 209 155 | 
             
                  end
         | 
| 210 156 |  | 
| 211 157 | 
             
                  it "finds by slug" do
         | 
| 212 | 
            -
                     | 
| 158 | 
            +
                    Author.find_by_slug("gilles-deleuze").should eql author
         | 
| 213 159 | 
             
                  end
         | 
| 214 | 
            -
             | 
| 215 160 | 
             
                end
         | 
| 216 161 |  | 
| 217 | 
            -
                context "when the  | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
                  it "sets the slug field name" do
         | 
| 222 | 
            -
                    person.respond_to?(:permalink).should be_true
         | 
| 223 | 
            -
                    person.send(:permalink).should eql "john-doe"
         | 
| 224 | 
            -
                  end
         | 
| 225 | 
            -
             | 
| 226 | 
            -
                  it "generates slug" do
         | 
| 227 | 
            -
                    person.to_param.should eql(person.name.parameterize)
         | 
| 228 | 
            -
                  end
         | 
| 229 | 
            -
             | 
| 230 | 
            -
                  it "updates slug" do
         | 
| 231 | 
            -
                    person.update_attributes(:name => "Jane Doe")
         | 
| 232 | 
            -
                    person.to_param.should eql "Jane Doe".parameterize
         | 
| 233 | 
            -
                  end
         | 
| 234 | 
            -
             | 
| 235 | 
            -
                  it "generates a unique slug" do
         | 
| 236 | 
            -
                    similar_person = Person.create(:name => person.name)
         | 
| 237 | 
            -
                    similar_person.to_param.should_not eql person.to_param
         | 
| 238 | 
            -
                  end
         | 
| 239 | 
            -
             | 
| 240 | 
            -
                  it "appends a counter when slug is not unique" do
         | 
| 241 | 
            -
                    similar_person = Person.create(:name => person.name)
         | 
| 242 | 
            -
                    similar_person.to_param.should match /\d$/
         | 
| 243 | 
            -
                  end
         | 
| 244 | 
            -
             | 
| 245 | 
            -
                  it "does not append a counter when slug is unique" do
         | 
| 246 | 
            -
                    person.to_param.should_not match /\d$/
         | 
| 247 | 
            -
                  end
         | 
| 248 | 
            -
             | 
| 249 | 
            -
                  it "does not update slug if slugged fields have not changed" do
         | 
| 250 | 
            -
                    former_slug = person.to_param
         | 
| 251 | 
            -
                    person.update_attributes(:age => 31)
         | 
| 252 | 
            -
                    person.to_param.should eql former_slug
         | 
| 253 | 
            -
                  end
         | 
| 254 | 
            -
             | 
| 255 | 
            -
                  it "does not update slug if slugged fields have changed but generated slug is the same" do
         | 
| 256 | 
            -
                    former_slug = person.to_param
         | 
| 257 | 
            -
                    person.update_attributes(:name => "JOHN DOE")
         | 
| 258 | 
            -
                    person.to_param.should eql former_slug
         | 
| 162 | 
            +
                context "when the field name for the slug is set with the :as option" do
         | 
| 163 | 
            +
                  let(:person) do
         | 
| 164 | 
            +
                    Person.create(:name => "John Doe")
         | 
| 259 165 | 
             
                  end
         | 
| 260 166 |  | 
| 261 | 
            -
                  it " | 
| 262 | 
            -
                     | 
| 167 | 
            +
                  it "sets the slug field name" do
         | 
| 168 | 
            +
                    person.should respond_to(:permalink)
         | 
| 169 | 
            +
                    person.permalink.should eql "john-doe"
         | 
| 263 170 | 
             
                  end
         | 
| 264 | 
            -
             | 
| 265 171 | 
             
                end
         | 
| 266 172 |  | 
| 267 | 
            -
                 | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 270 | 
            -
                  let(:bar) { foo.bars.create(:name => "bar") }
         | 
| 271 | 
            -
                  let(:baz) { bar.bazes.create(:name => "baz") }
         | 
| 272 | 
            -
             | 
| 273 | 
            -
                  it "finds duplicate slug of a root document" do
         | 
| 274 | 
            -
                    foo.send(:find_, foo.to_param).count.should eql 1
         | 
| 173 | 
            +
                context "when slug is set to be permanent with the :permanent option" do
         | 
| 174 | 
            +
                  let(:person) do
         | 
| 175 | 
            +
                    Person.create(:name => "John Doe")
         | 
| 275 176 | 
             
                  end
         | 
| 276 177 |  | 
| 277 | 
            -
                  it " | 
| 278 | 
            -
                     | 
| 178 | 
            +
                  it "does not change the slug when the slugged fields are updated" do
         | 
| 179 | 
            +
                    person.name = "Jane Doe"
         | 
| 180 | 
            +
                    person.save
         | 
| 181 | 
            +
                    person.to_param.should eql "john-doe"
         | 
| 279 182 | 
             
                  end
         | 
| 280 | 
            -
             | 
| 281 | 
            -
                  it "finds duplicate slug of a deeply-embedded document" do
         | 
| 282 | 
            -
                    baz.send(:find_, baz.to_param).count.should eql 1
         | 
| 283 | 
            -
                  end
         | 
| 284 | 
            -
             | 
| 285 183 | 
             
                end
         | 
| 286 | 
            -
              
         | 
| 287 | 
            -
                context "when slug is scoped" do
         | 
| 288 184 |  | 
| 289 | 
            -
             | 
| 290 | 
            -
                   | 
| 291 | 
            -
                   | 
| 292 | 
            -
             | 
| 293 | 
            -
                  it "generates a unique slug inside the same parent object" do
         | 
| 294 | 
            -
                    similar_sar = foo.sars.create(:name => sar.name)
         | 
| 295 | 
            -
                    similar_sar.to_param.should_not eql sar.to_param
         | 
| 296 | 
            -
                  end
         | 
| 297 | 
            -
                
         | 
| 298 | 
            -
                  it "generates the same slug in different parent object" do
         | 
| 299 | 
            -
                    other_sar = foo2.sars.create(:name => sar.name)
         | 
| 300 | 
            -
                    other_sar.to_param.should eql sar.to_param
         | 
| 301 | 
            -
                  end
         | 
| 302 | 
            -
             | 
| 303 | 
            -
                end
         | 
| 304 | 
            -
             | 
| 305 | 
            -
                context "when slug is permanent" do
         | 
| 185 | 
            +
                it "works with non-Latin characters" do
         | 
| 186 | 
            +
                  book.title = "Капитал"
         | 
| 187 | 
            +
                  book.save
         | 
| 188 | 
            +
                  book.to_param.should eql "kapital"
         | 
| 306 189 |  | 
| 307 | 
            -
                   | 
| 308 | 
            -
             | 
| 309 | 
            -
                   | 
| 310 | 
            -
                    permanent.update_attributes(:title => "This is not a nodding song")
         | 
| 311 | 
            -
                    permanent.to_param.should eql "This is a nodding song".parameterize
         | 
| 312 | 
            -
                  end
         | 
| 190 | 
            +
                  book.title = "Ελλάδα"
         | 
| 191 | 
            +
                  book.save
         | 
| 192 | 
            +
                  book.to_param.should eql "ellada"
         | 
| 313 193 |  | 
| 194 | 
            +
                  book.title = "中文"
         | 
| 195 | 
            +
                  book.save
         | 
| 196 | 
            +
                  book.to_param.should eql 'zhong-wen'
         | 
| 314 197 | 
             
                end
         | 
| 315 | 
            -
             | 
| 316 198 | 
             
              end
         | 
| 317 | 
            -
             | 
| 318 199 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,22 +1,20 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: mongoid_slug
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash: 1
         | 
| 5 4 | 
             
              prerelease: false
         | 
| 6 5 | 
             
              segments: 
         | 
| 7 6 | 
             
              - 0
         | 
| 8 | 
            -
              -  | 
| 9 | 
            -
              -  | 
| 10 | 
            -
              version: 0. | 
| 7 | 
            +
              - 5
         | 
| 8 | 
            +
              - 0
         | 
| 9 | 
            +
              version: 0.5.0
         | 
| 11 10 | 
             
            platform: ruby
         | 
| 12 11 | 
             
            authors: 
         | 
| 13 | 
            -
            -  | 
| 14 | 
            -
            - Gerhard Lazu
         | 
| 12 | 
            +
            - Paper Cavalier
         | 
| 15 13 | 
             
            autorequire: 
         | 
| 16 14 | 
             
            bindir: bin
         | 
| 17 15 | 
             
            cert_chain: []
         | 
| 18 16 |  | 
| 19 | 
            -
            date: 2010- | 
| 17 | 
            +
            date: 2010-12-28 00:00:00 -03:00
         | 
| 20 18 | 
             
            default_executable: 
         | 
| 21 19 | 
             
            dependencies: 
         | 
| 22 20 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -27,65 +25,76 @@ dependencies: | |
| 27 25 | 
             
                requirements: 
         | 
| 28 26 | 
             
                - - ~>
         | 
| 29 27 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 30 | 
            -
                    hash: 62196421
         | 
| 31 28 | 
             
                    segments: 
         | 
| 32 29 | 
             
                    - 2
         | 
| 33 30 | 
             
                    - 0
         | 
| 34 31 | 
             
                    - 0
         | 
| 35 32 | 
             
                    - beta
         | 
| 36 | 
            -
                    -  | 
| 37 | 
            -
                    version: 2.0.0.beta. | 
| 33 | 
            +
                    - 20
         | 
| 34 | 
            +
                    version: 2.0.0.beta.20
         | 
| 38 35 | 
             
              type: :runtime
         | 
| 39 36 | 
             
              version_requirements: *id001
         | 
| 40 37 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 41 | 
            -
              name:  | 
| 38 | 
            +
              name: stringex
         | 
| 42 39 | 
             
              prerelease: false
         | 
| 43 40 | 
             
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 44 41 | 
             
                none: false
         | 
| 45 42 | 
             
                requirements: 
         | 
| 46 43 | 
             
                - - ~>
         | 
| 47 44 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 48 | 
            -
                    hash: 17
         | 
| 49 45 | 
             
                    segments: 
         | 
| 50 46 | 
             
                    - 1
         | 
| 47 | 
            +
                    - 2
         | 
| 48 | 
            +
                    - 0
         | 
| 49 | 
            +
                    version: 1.2.0
         | 
| 50 | 
            +
              type: :runtime
         | 
| 51 | 
            +
              version_requirements: *id002
         | 
| 52 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 53 | 
            +
              name: bson_ext
         | 
| 54 | 
            +
              prerelease: false
         | 
| 55 | 
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         | 
| 56 | 
            +
                none: false
         | 
| 57 | 
            +
                requirements: 
         | 
| 58 | 
            +
                - - ~>
         | 
| 59 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 60 | 
            +
                    segments: 
         | 
| 51 61 | 
             
                    - 1
         | 
| 52 62 | 
             
                    - 1
         | 
| 53 | 
            -
                     | 
| 63 | 
            +
                    - 5
         | 
| 64 | 
            +
                    version: 1.1.5
         | 
| 54 65 | 
             
              type: :development
         | 
| 55 | 
            -
              version_requirements: * | 
| 66 | 
            +
              version_requirements: *id003
         | 
| 56 67 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 57 68 | 
             
              name: database_cleaner
         | 
| 58 69 | 
             
              prerelease: false
         | 
| 59 | 
            -
              requirement: & | 
| 70 | 
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         | 
| 60 71 | 
             
                none: false
         | 
| 61 72 | 
             
                requirements: 
         | 
| 62 73 | 
             
                - - ~>
         | 
| 63 74 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 64 | 
            -
                    hash: 7
         | 
| 65 75 | 
             
                    segments: 
         | 
| 66 76 | 
             
                    - 0
         | 
| 67 77 | 
             
                    - 6
         | 
| 68 78 | 
             
                    - 0
         | 
| 69 79 | 
             
                    version: 0.6.0
         | 
| 70 80 | 
             
              type: :development
         | 
| 71 | 
            -
              version_requirements: * | 
| 81 | 
            +
              version_requirements: *id004
         | 
| 72 82 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 73 83 | 
             
              name: rspec
         | 
| 74 84 | 
             
              prerelease: false
         | 
| 75 | 
            -
              requirement: & | 
| 85 | 
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         | 
| 76 86 | 
             
                none: false
         | 
| 77 87 | 
             
                requirements: 
         | 
| 78 88 | 
             
                - - ~>
         | 
| 79 89 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 80 | 
            -
                    hash: 13
         | 
| 81 90 | 
             
                    segments: 
         | 
| 82 91 | 
             
                    - 2
         | 
| 92 | 
            +
                    - 3
         | 
| 83 93 | 
             
                    - 0
         | 
| 84 | 
            -
                     | 
| 85 | 
            -
                    version: 2.0.1
         | 
| 94 | 
            +
                    version: 2.3.0
         | 
| 86 95 | 
             
              type: :development
         | 
| 87 | 
            -
              version_requirements: * | 
| 88 | 
            -
            description:  | 
| 96 | 
            +
              version_requirements: *id005
         | 
| 97 | 
            +
            description: Mongoid Slug generates a URL slug or permalink based on one or more fields in a Mongoid model.
         | 
| 89 98 | 
             
            email: 
         | 
| 90 99 | 
             
            - code@papercavalier.com
         | 
| 91 100 | 
             
            executables: []
         | 
| @@ -100,19 +109,15 @@ files: | |
| 100 109 | 
             
            - LICENSE
         | 
| 101 110 | 
             
            - README.md
         | 
| 102 111 | 
             
            - spec/models/author.rb
         | 
| 103 | 
            -
            - spec/models/bar.rb
         | 
| 104 | 
            -
            - spec/models/baz.rb
         | 
| 105 112 | 
             
            - spec/models/book.rb
         | 
| 106 | 
            -
            - spec/models/ | 
| 107 | 
            -
            - spec/models/permanent.rb
         | 
| 113 | 
            +
            - spec/models/partner.rb
         | 
| 108 114 | 
             
            - spec/models/person.rb
         | 
| 109 | 
            -
            - spec/models/ | 
| 110 | 
            -
            - spec/models/sar.rb
         | 
| 115 | 
            +
            - spec/models/relationship.rb
         | 
| 111 116 | 
             
            - spec/models/subject.rb
         | 
| 112 117 | 
             
            - spec/mongoid/slug_spec.rb
         | 
| 113 118 | 
             
            - spec/spec_helper.rb
         | 
| 114 119 | 
             
            has_rdoc: true
         | 
| 115 | 
            -
            homepage: http://github.com/papercavalier/ | 
| 120 | 
            +
            homepage: http://github.com/papercavalier/mongoid-slug
         | 
| 116 121 | 
             
            licenses: []
         | 
| 117 122 |  | 
| 118 123 | 
             
            post_install_message: 
         | 
| @@ -125,7 +130,6 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 125 130 | 
             
              requirements: 
         | 
| 126 131 | 
             
              - - ">="
         | 
| 127 132 | 
             
                - !ruby/object:Gem::Version 
         | 
| 128 | 
            -
                  hash: 3
         | 
| 129 133 | 
             
                  segments: 
         | 
| 130 134 | 
             
                  - 0
         | 
| 131 135 | 
             
                  version: "0"
         | 
| @@ -134,7 +138,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 134 138 | 
             
              requirements: 
         | 
| 135 139 | 
             
              - - ">="
         | 
| 136 140 | 
             
                - !ruby/object:Gem::Version 
         | 
| 137 | 
            -
                  hash: 3
         | 
| 138 141 | 
             
                  segments: 
         | 
| 139 142 | 
             
                  - 0
         | 
| 140 143 | 
             
                  version: "0"
         | 
| @@ -144,17 +147,13 @@ rubyforge_project: mongoid_slug | |
| 144 147 | 
             
            rubygems_version: 1.3.7
         | 
| 145 148 | 
             
            signing_key: 
         | 
| 146 149 | 
             
            specification_version: 3
         | 
| 147 | 
            -
            summary: Generates a URL slug | 
| 150 | 
            +
            summary: Generates a URL slug
         | 
| 148 151 | 
             
            test_files: 
         | 
| 149 152 | 
             
            - spec/models/author.rb
         | 
| 150 | 
            -
            - spec/models/bar.rb
         | 
| 151 | 
            -
            - spec/models/baz.rb
         | 
| 152 153 | 
             
            - spec/models/book.rb
         | 
| 153 | 
            -
            - spec/models/ | 
| 154 | 
            -
            - spec/models/permanent.rb
         | 
| 154 | 
            +
            - spec/models/partner.rb
         | 
| 155 155 | 
             
            - spec/models/person.rb
         | 
| 156 | 
            -
            - spec/models/ | 
| 157 | 
            -
            - spec/models/sar.rb
         | 
| 156 | 
            +
            - spec/models/relationship.rb
         | 
| 158 157 | 
             
            - spec/models/subject.rb
         | 
| 159 158 | 
             
            - spec/mongoid/slug_spec.rb
         | 
| 160 159 | 
             
            - spec/spec_helper.rb
         | 
    
        data/spec/models/bar.rb
    DELETED
    
    
    
        data/spec/models/foo.rb
    DELETED
    
    
    
        data/spec/models/permanent.rb
    DELETED
    
    
    
        data/spec/models/publisher.rb
    DELETED