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.
- data/lib/mongoid/slug.rb +25 -21
- data/lib/mongoid/slug/version.rb +1 -1
- data/spec/models/page.rb +9 -0
- data/spec/mongoid/slug_spec.rb +10 -28
- data/spec/spec_helper.rb +1 -1
- metadata +50 -6
data/lib/mongoid/slug.rb
CHANGED
@@ -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
|
63
|
-
self.slug_scope
|
64
|
-
self.slug_name
|
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 ||
|
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)}(
|
120
|
+
pattern = /^#{Regexp.escape(slug)}(?:-(\d+))?$/
|
125
121
|
|
126
|
-
|
127
|
-
|
122
|
+
existing_slugs =
|
123
|
+
uniqueness_scope.
|
124
|
+
only(slug_name).
|
128
125
|
where(slug_name => pattern, :_id.ne => _id).
|
129
|
-
|
126
|
+
map {|obj| obj.try(:read_attribute, slug_name)}
|
130
127
|
|
131
|
-
if
|
132
|
-
|
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
|
data/lib/mongoid/slug/version.rb
CHANGED
data/spec/models/page.rb
ADDED
data/spec/mongoid/slug_spec.rb
CHANGED
@@ -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
|
-
|
23
|
-
|
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
|
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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-
|
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
|
-
|
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
|
-
|
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.
|
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
|