mongoid_slug 0.7.2 → 0.8.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.
@@ -39,7 +39,9 @@ module Mongoid #:nodoc:
39
39
  #
40
40
  # * `:index`, which specifies whether an index should be defined for the
41
41
  # slug. Defaults to `false` and has no effect if the document is em-
42
- # bedded.
42
+ # bedded. Make sure you have a unique index on the slug of root
43
+ # documents to avoid the (very unlikely) race condition that would ensue
44
+ # if two documents with identical slugs were to be saved simultaneously.
43
45
  #
44
46
  # Alternatively, this method can be given a block to build a custom slug
45
47
  # out of the specified fields.
@@ -59,9 +61,9 @@ module Mongoid #:nodoc:
59
61
  # end
60
62
  #
61
63
  def slug(*fields, &block)
62
- options = fields.extract_options!
63
- self.slug_scope = options[:scope]
64
- self.slug_name = options[:as] || :slug
64
+ options = fields.extract_options!
65
+ self.slug_scope = options[:scope]
66
+ self.slug_name = options[:as] || :slug
65
67
  self.slugged_fields = fields.map(&:to_s)
66
68
 
67
69
  self.slug_builder =
@@ -69,7 +71,7 @@ module Mongoid #:nodoc:
69
71
  block
70
72
  else
71
73
  lambda do |doc|
72
- slugged_fields.map { |f| doc.read_attribute(f) }.join(',')
74
+ slugged_fields.map { |f| doc.read_attribute(f) }.join(' ')
73
75
  end
74
76
  end
75
77
 
@@ -94,20 +96,13 @@ module Mongoid #:nodoc:
94
96
  end
95
97
 
96
98
  def self.find_by_#{slug_name}!(slug)
97
- where(slug_name => slug).first || raise(Mongoid::Errors::DocumentNotFound.new(self.class, slug))
99
+ where(slug_name => slug).first ||
100
+ raise(Mongoid::Errors::DocumentNotFound.new(self.class, slug))
98
101
  end
99
102
  CODE
100
103
  end
101
104
  end
102
105
 
103
- # Regenerates slug.
104
- #
105
- # Should come in handy when generating slugs for an existing collection.
106
- def slug!
107
- generate_slug!
108
- save
109
- end
110
-
111
106
  # Returns the slug.
112
107
  def to_param
113
108
  read_attribute(slug_name)
@@ -116,20 +111,29 @@ module Mongoid #:nodoc:
116
111
  private
117
112
 
118
113
  def find_unique_slug
114
+ # TODO: An epic method which calls for refactoring.
119
115
  slug = slug_builder.call(self).to_url
120
-
116
+
121
117
  # Regular expression that matches slug, slug-1, slug-2, ... slug-n
122
118
  # If slug_name field was indexed, MongoDB will utilize that index to
123
119
  # match /^.../ pattern
124
- pattern = /^#{Regexp.escape(slug)}(?:-\d+)?$/
120
+ pattern = /^#{Regexp.escape(slug)}(?:-(\d+))?$/
125
121
 
126
- # Get the maximum counter slug
127
- max_counter_slug = uniqueness_scope.only(slug_name).
122
+ existing_slugs =
123
+ uniqueness_scope.
124
+ only(slug_name).
128
125
  where(slug_name => pattern, :_id.ne => _id).
129
- order_by([slug_name, :desc]).first.try(:read_attribute, slug_name)
126
+ map {|obj| obj.try(:read_attribute, slug_name)}
130
127
 
131
- if max_counter_slug
132
- max_counter = max_counter_slug.match(/-(\d+)$/).try(:[], 1).to_i
128
+ if existing_slugs.count > 0
129
+ # sort the existing_slugs in increasing order by comparing the suffix
130
+ # numbers:
131
+ # slug, slug-1, slug-2, ..., slug-n
132
+ existing_slugs.sort! do |a, b|
133
+ (pattern.match(a)[1] || -1).to_i <=> (pattern.match(b)[1] || -1).to_i
134
+ end
135
+ max_counter = existing_slugs.last.match(/-(\d+)$/).try(:[], 1).to_i
136
+
133
137
  # Use max_counter + 1 as unique counter
134
138
  slug += "-#{max_counter + 1}"
135
139
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid #:nodoc:
2
2
  module Slug
3
- VERSION = '0.7.2'
3
+ VERSION = '0.8.0'
4
4
  end
5
5
  end
@@ -0,0 +1,9 @@
1
+ class Page
2
+ include Mongoid::Document
3
+ include Mongoid::Slug
4
+ field :title
5
+ field :content
6
+ field :order, :type => Integer
7
+ slug :title
8
+ default_scope asc(:order)
9
+ end
@@ -19,8 +19,10 @@ module Mongoid
19
19
  end
20
20
 
21
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"
22
+ 15.times{ |x|
23
+ dup = Book.create(:title => book.title)
24
+ dup.to_param.should eql "a-thousand-plateaus-#{x+1}"
25
+ }
24
26
  end
25
27
 
26
28
  it "does not update slug if slugged fields have not changed" do
@@ -39,6 +41,12 @@ module Mongoid
39
41
  end
40
42
  end
41
43
 
44
+ context "when using default_scope on a model" do
45
+ it "find_unique_slug should work correctly" do
46
+ Page.create!(:title => "Title", :content => "Content", :order => 1)
47
+ end
48
+ end
49
+
42
50
  context "when the object is embedded" do
43
51
  let(:subject) do
44
52
  book.subjects.create(:name => "Psychoanalysis")
@@ -322,32 +330,6 @@ module Mongoid
322
330
  end
323
331
  end
324
332
 
325
- describe "#slug!" do
326
- before do
327
- class Foo
328
- include Mongoid::Document
329
- field :name
330
- end
331
- end
332
-
333
- let!(:foo) do
334
- Foo.create(:name => "John")
335
- end
336
-
337
- it "regenerates slug" do
338
- class Foo
339
- include Mongoid::Slug
340
- slug :name
341
- end
342
-
343
- foo.reload.slug.should be_nil
344
-
345
- foo.slug!
346
-
347
- foo.reload.slug.should eql 'john'
348
- end
349
- end
350
-
351
333
  describe ".find_by_slug" do
352
334
  let!(:book) { Book.create(:title => "A Thousand Plateaus") }
353
335
 
@@ -15,7 +15,7 @@ require File.expand_path("../../lib/mongoid/slug", __FILE__)
15
15
 
16
16
  Dir["#{File.dirname(__FILE__)}/models/*.rb"].each { |f| require f }
17
17
 
18
- Rspec.configure do |c|
18
+ RSpec.configure do |c|
19
19
  c.before(:all) { DatabaseCleaner.strategy = :truncation }
20
20
  c.before(:each) { DatabaseCleaner.clean }
21
21
  end
metadata CHANGED
@@ -1,8 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_slug
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.7.2
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 8
8
+ - 0
9
+ version: 0.8.0
6
10
  platform: ruby
7
11
  authors:
8
12
  - Paper Cavalier
@@ -10,7 +14,7 @@ autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
16
 
13
- date: 2011-04-14 00:00:00 +01:00
17
+ date: 2011-06-10 00:00:00 +01:00
14
18
  default_executable:
15
19
  dependencies:
16
20
  - !ruby/object:Gem::Dependency
@@ -21,7 +25,10 @@ dependencies:
21
25
  requirements:
22
26
  - - ~>
23
27
  - !ruby/object:Gem::Version
24
- version: 2.0.0
28
+ segments:
29
+ - 2
30
+ - 0
31
+ version: "2.0"
25
32
  type: :runtime
26
33
  version_requirements: *id001
27
34
  - !ruby/object:Gem::Dependency
@@ -32,9 +39,40 @@ dependencies:
32
39
  requirements:
33
40
  - - ~>
34
41
  - !ruby/object:Gem::Version
35
- version: 1.2.0
42
+ segments:
43
+ - 1
44
+ - 2
45
+ version: "1.2"
36
46
  type: :runtime
37
47
  version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: database_cleaner
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 6
59
+ version: "0.6"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 2
72
+ - 6
73
+ version: "2.6"
74
+ type: :development
75
+ version_requirements: *id004
38
76
  description: Mongoid Slug generates a URL slug or permalink based on one or more fields in a Mongoid model.
39
77
  email:
40
78
  - code@papercavalier.com
@@ -54,6 +92,7 @@ files:
54
92
  - spec/models/book.rb
55
93
  - spec/models/caption.rb
56
94
  - spec/models/comic_book.rb
95
+ - spec/models/page.rb
57
96
  - spec/models/partner.rb
58
97
  - spec/models/person.rb
59
98
  - spec/models/relationship.rb
@@ -74,17 +113,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
74
113
  requirements:
75
114
  - - ">="
76
115
  - !ruby/object:Gem::Version
116
+ segments:
117
+ - 0
77
118
  version: "0"
78
119
  required_rubygems_version: !ruby/object:Gem::Requirement
79
120
  none: false
80
121
  requirements:
81
122
  - - ">="
82
123
  - !ruby/object:Gem::Version
124
+ segments:
125
+ - 0
83
126
  version: "0"
84
127
  requirements: []
85
128
 
86
129
  rubyforge_project: mongoid_slug
87
- rubygems_version: 1.5.2
130
+ rubygems_version: 1.3.7
88
131
  signing_key:
89
132
  specification_version: 3
90
133
  summary: Generates a URL slug
@@ -94,6 +137,7 @@ test_files:
94
137
  - spec/models/book.rb
95
138
  - spec/models/caption.rb
96
139
  - spec/models/comic_book.rb
140
+ - spec/models/page.rb
97
141
  - spec/models/partner.rb
98
142
  - spec/models/person.rb
99
143
  - spec/models/relationship.rb