mongoid_slug 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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.find_by_slug("anti-oedipus").first
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 :slugged
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.slugged = fields
13
- field :slug; index :slug, :unique => true; before_save :slugify
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 slugify
32
- if new_record? || slugged_changed?
33
- self.slug = find_unique_slug
34
- end
35
- end
36
-
37
- def slugged_changed?
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 (embedded? ?
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
- new_suffix = suffix.blank? ? '1' : "#{suffix.to_i + 1}"
53
- find_unique_slug(new_suffix)
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.slugged.collect{ |field| self.send(field) }.join(" ")
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
@@ -4,4 +4,5 @@ class Author
4
4
  field :first_name
5
5
  field :last_name
6
6
  slug :first_name, :last_name
7
+ referenced_in :book
7
8
  end
@@ -0,0 +1,8 @@
1
+ class Bar
2
+ include Mongoid::Document
3
+ include Mongoid::Slug
4
+ field :name
5
+ slug :name
6
+ embeds_many :bazes, :class_name => "Baz"
7
+ embedded_in :foo, :inverse_of => :bars
8
+ end
@@ -0,0 +1,8 @@
1
+ class Baz
2
+ include Mongoid::Document
3
+ include Mongoid::Slug
4
+ field :name
5
+ field :other
6
+ slug :name
7
+ embedded_in :bar, :inverse_of => :bazes
8
+ end
data/spec/models/book.rb CHANGED
@@ -6,4 +6,5 @@ class Book
6
6
  slug :title
7
7
  embeds_one :publisher
8
8
  embeds_many :subjects
9
+ references_many :authors
9
10
  end
@@ -0,0 +1,7 @@
1
+ class Foo
2
+ include Mongoid::Document
3
+ include Mongoid::Slug
4
+ field :name
5
+ slug :name
6
+ embeds_many :bars
7
+ end
@@ -43,10 +43,8 @@ describe Mongoid::Slug do
43
43
  @book.slug.should eql former_slug
44
44
  end
45
45
 
46
- context ".find_by_slug" do
47
- it "finds by slug" do
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
- context ".find_by_slug" do
90
- it "finds by slug" do
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
- context ".find_by_slug" do
151
- it "finds by slug" do
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: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.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-06-30 00:00:00 +01:00
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