mongoid_slug 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|