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 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