mongoid_slug 0.3.0 → 0.4.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.rdoc +20 -2
- data/lib/mongoid_slug.rb +26 -27
- data/spec/models/author.rb +1 -0
- data/spec/models/bar.rb +8 -0
- data/spec/models/baz.rb +8 -0
- data/spec/models/book.rb +1 -0
- data/spec/models/foo.rb +7 -0
- data/spec/mongoid_slug_spec.rb +74 -12
- metadata +10 -4
data/README.rdoc
CHANGED
|
@@ -7,13 +7,31 @@ This gem generates a URL slug/permalink based on fields in a Mongoid model.
|
|
|
7
7
|
include Mongoid::Slug
|
|
8
8
|
field :title
|
|
9
9
|
slug :title
|
|
10
|
+
embeds_many :authors
|
|
10
11
|
end
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
class Author
|
|
14
|
+
include Mongoid::Document
|
|
15
|
+
include Mongoid::Slug
|
|
16
|
+
field :first_name
|
|
17
|
+
field :last_name
|
|
18
|
+
slug :first_name, :last_name
|
|
19
|
+
embedded_in :book, :inverse_of => :authors
|
|
20
|
+
end
|
|
21
|
+
|
|
12
22
|
>> book = Book.create(:title => "A Thousand Plateaus")
|
|
13
23
|
>> book.to_param
|
|
14
24
|
"a-thousand-plateaus"
|
|
15
25
|
>> book.update_attributes(:title => "Anti Oedipus")
|
|
16
26
|
>> book.to_param
|
|
17
27
|
"anti-oedipus"
|
|
18
|
-
>> Book.
|
|
28
|
+
>> Book.where(:slug => 'anti-oedipus').first
|
|
19
29
|
#<Book _id: 4c23b1f7faa4a7479a000009, slug: "anti-oedipus", title: "Anti Oedipus">
|
|
30
|
+
>> author = book.authors.create(:first_name => "Gilles", :last_name => "Deleuze")
|
|
31
|
+
>> author.to_param
|
|
32
|
+
=> "gilles-deleuze"
|
|
33
|
+
>> author.update_attributes(:first => "Félix", :last_name => "Guattari")
|
|
34
|
+
>> author.to_param
|
|
35
|
+
=> "félix-guattari"
|
|
36
|
+
>> book.authors.where(:slug => 'felix-guattari).first
|
|
37
|
+
=> #<Author _id: 4c31e362faa4a7050e000003, slug: "félix-guattari", last_name: "Guattari", first_name: "Félix">
|
data/lib/mongoid_slug.rb
CHANGED
|
@@ -3,22 +3,14 @@ module Mongoid::Slug
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
included do
|
|
6
|
-
cattr_accessor :
|
|
6
|
+
cattr_accessor :slugged_fields
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
module ClassMethods #:nodoc:
|
|
10
10
|
# Set a field or a number of fields as source of slug
|
|
11
11
|
def slug(*fields)
|
|
12
|
-
self.
|
|
13
|
-
field :slug;
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# This returns an array containing the match rather than
|
|
17
|
-
# the match itself.
|
|
18
|
-
#
|
|
19
|
-
# http://groups.google.com/group/mongoid/browse_thread/thread/5905589e108d7cc0
|
|
20
|
-
def find_by_slug(slug)
|
|
21
|
-
where(:slug => slug).limit(1)
|
|
12
|
+
self.slugged_fields = fields
|
|
13
|
+
field :slug; before_save :generate_slug
|
|
22
14
|
end
|
|
23
15
|
end
|
|
24
16
|
|
|
@@ -28,33 +20,40 @@ module Mongoid::Slug
|
|
|
28
20
|
|
|
29
21
|
private
|
|
30
22
|
|
|
31
|
-
def
|
|
32
|
-
if
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.class.slugged.any? do |field|
|
|
39
|
-
self.send(field.to_s + '_changed?')
|
|
23
|
+
def duplicates_of(slug, association_chain=[])
|
|
24
|
+
if embedded?
|
|
25
|
+
association_chain << association_name
|
|
26
|
+
_parent.send :duplicates_of, slug, association_chain
|
|
27
|
+
else
|
|
28
|
+
association_chain.reverse! << "slug"
|
|
29
|
+
collection.find(association_chain.join(".") => slug)
|
|
40
30
|
end
|
|
41
31
|
end
|
|
42
32
|
|
|
43
33
|
def find_unique_slug(suffix='')
|
|
44
34
|
slug = ("#{slug_base} #{suffix}").parameterize
|
|
45
35
|
|
|
46
|
-
if (
|
|
47
|
-
_parent.collection.find("#{association_name}.slug" => slug) :
|
|
48
|
-
collection.find(:slug => slug)
|
|
49
|
-
).reject{ |doc| doc.id == self.id }.empty?
|
|
36
|
+
if duplicates_of(slug).reject{ |doc| doc.id == self.id }.empty?
|
|
50
37
|
slug
|
|
51
38
|
else
|
|
52
|
-
|
|
53
|
-
find_unique_slug(
|
|
39
|
+
suffix = suffix.blank? ? '1' : "#{suffix.to_i + 1}"
|
|
40
|
+
find_unique_slug(suffix)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def generate_slug
|
|
45
|
+
if new_record? || slugged_fields_changed?
|
|
46
|
+
self.slug = find_unique_slug
|
|
54
47
|
end
|
|
55
48
|
end
|
|
56
49
|
|
|
57
50
|
def slug_base
|
|
58
|
-
self.class.
|
|
51
|
+
self.class.slugged_fields.collect{ |field| self.send(field) }.join(" ")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def slugged_fields_changed?
|
|
55
|
+
self.class.slugged_fields.any? do |field|
|
|
56
|
+
self.send(field.to_s + '_changed?')
|
|
57
|
+
end
|
|
59
58
|
end
|
|
60
59
|
end
|
data/spec/models/author.rb
CHANGED
data/spec/models/bar.rb
ADDED
data/spec/models/baz.rb
ADDED
data/spec/models/book.rb
CHANGED
data/spec/models/foo.rb
ADDED
data/spec/mongoid_slug_spec.rb
CHANGED
|
@@ -43,10 +43,8 @@ describe Mongoid::Slug do
|
|
|
43
43
|
@book.slug.should eql former_slug
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Book.find_by_slug(@book.slug).first.should eql @book
|
|
49
|
-
end
|
|
46
|
+
it "finds by slug" do
|
|
47
|
+
Book.where(:slug => @book.slug).first.should eql @book
|
|
50
48
|
end
|
|
51
49
|
|
|
52
50
|
end
|
|
@@ -86,10 +84,8 @@ describe Mongoid::Slug do
|
|
|
86
84
|
@subject.slug.should eql former_slug
|
|
87
85
|
end
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
@book.subjects.find_by_slug(@subject.slug).first.should eql @subject
|
|
92
|
-
end
|
|
87
|
+
it "finds by slug" do
|
|
88
|
+
@book.subjects.where(:slug => @subject.slug).first.should eql @subject
|
|
93
89
|
end
|
|
94
90
|
|
|
95
91
|
end
|
|
@@ -147,10 +143,76 @@ describe Mongoid::Slug do
|
|
|
147
143
|
@author.slug.should_not match /\d$/
|
|
148
144
|
end
|
|
149
145
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Author.find_by_slug("gilles-deleuze").first.should eql @author
|
|
153
|
-
end
|
|
146
|
+
it "finds by slug" do
|
|
147
|
+
Author.where(:slug => "gilles-deleuze").first.should eql @author
|
|
154
148
|
end
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context "deeply embedded relationships" do
|
|
153
|
+
|
|
154
|
+
before(:each) do
|
|
155
|
+
@foo = Foo.create(:name => "foo")
|
|
156
|
+
@bar = @foo.bars.create(:name => "bar")
|
|
157
|
+
@baz = @bar.bazes.create(:name => "baz")
|
|
158
|
+
@baz = Foo.first.bars.first.bazes.first # Better to be paranoid and reload from db
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "generates slug" do
|
|
162
|
+
@baz.to_param.should eql(@baz.name.parameterize)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "updates slug" do
|
|
166
|
+
@baz.update_attributes(:name => "lorem")
|
|
167
|
+
@baz.to_param.should eql "lorem".parameterize
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "generates a unique slug" do
|
|
171
|
+
similar_baz = @bar.bazes.create(:name => @baz.name)
|
|
172
|
+
similar_baz.to_param.should_not eql @baz.to_param
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "appends a counter when slug is not unique" do
|
|
176
|
+
similar_baz = @bar.bazes.create(:name => @baz.name)
|
|
177
|
+
similar_baz.slug.should match /\d$/
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "does not append a counter when slug is unique" do
|
|
181
|
+
@baz.slug.should_not match /\d$/
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "does not update slug if slugged field has not changed" do
|
|
185
|
+
former_slug = @baz.slug
|
|
186
|
+
@baz.update_attributes(:other => "Lorem ipsum dolor sit amet")
|
|
187
|
+
@baz.slug.should eql former_slug
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "finds by slug" do
|
|
191
|
+
@bar.bazes.where(:slug => @baz.slug).first.should eql @baz
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe "#duplicates_of" do
|
|
197
|
+
|
|
198
|
+
before(:each) do
|
|
199
|
+
@foo = Foo.create(:name => "foo")
|
|
200
|
+
@bar = @foo.bars.create(:name => "bar")
|
|
201
|
+
@baz = @bar.bazes.create(:name => "baz")
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should find duplicate slug of a root document" do
|
|
205
|
+
@foo.send(:duplicates_of, @foo.slug).count.should eql 1
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "should find duplicate slug of an embedded document" do
|
|
209
|
+
@bar.send(:duplicates_of, @bar.slug).count.should eql 1
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it "should find duplicate slug of a deeply-embedded document" do
|
|
213
|
+
@baz.send(:duplicates_of, @baz.slug).count.should eql 1
|
|
214
|
+
end
|
|
215
|
+
|
|
155
216
|
end
|
|
217
|
+
|
|
156
218
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mongoid_slug
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 15
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
|
-
-
|
|
8
|
+
- 4
|
|
9
9
|
- 0
|
|
10
|
-
version: 0.
|
|
10
|
+
version: 0.4.0
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Hakan Ensari
|
|
@@ -16,7 +16,7 @@ autorequire:
|
|
|
16
16
|
bindir: bin
|
|
17
17
|
cert_chain: []
|
|
18
18
|
|
|
19
|
-
date: 2010-
|
|
19
|
+
date: 2010-07-05 00:00:00 +01:00
|
|
20
20
|
default_executable:
|
|
21
21
|
dependencies:
|
|
22
22
|
- !ruby/object:Gem::Dependency
|
|
@@ -50,7 +50,10 @@ files:
|
|
|
50
50
|
- README.rdoc
|
|
51
51
|
- lib/mongoid_slug.rb
|
|
52
52
|
- spec/models/author.rb
|
|
53
|
+
- spec/models/bar.rb
|
|
54
|
+
- spec/models/baz.rb
|
|
53
55
|
- spec/models/book.rb
|
|
56
|
+
- spec/models/foo.rb
|
|
54
57
|
- spec/models/publisher.rb
|
|
55
58
|
- spec/models/subject.rb
|
|
56
59
|
- spec/mongoid_slug_spec.rb
|
|
@@ -91,7 +94,10 @@ specification_version: 3
|
|
|
91
94
|
summary: Generates a URL slug in a Mongoid model
|
|
92
95
|
test_files:
|
|
93
96
|
- spec/models/author.rb
|
|
97
|
+
- spec/models/bar.rb
|
|
98
|
+
- spec/models/baz.rb
|
|
94
99
|
- spec/models/book.rb
|
|
100
|
+
- spec/models/foo.rb
|
|
95
101
|
- spec/models/publisher.rb
|
|
96
102
|
- spec/models/subject.rb
|
|
97
103
|
- spec/mongoid_slug_spec.rb
|