slugalicious 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Tim Morgan
1
+ Copyright (c) 2010 Tim Morgan
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.textile CHANGED
@@ -3,7 +3,7 @@ h1. Slugalicious -- Easy and powerful URL slugging for Rails 3
3
3
  _*(no monkey-patching required)*_
4
4
 
5
5
  | *Author* | Tim Morgan |
6
- | *Version* | 1.0 (Oct 30, 2010) |
6
+ | *Version* | 1.1 (Aug 13, 2011) |
7
7
  | *License* | Released under the MIT license. |
8
8
 
9
9
  h2. About
@@ -186,11 +186,21 @@ def find_product
186
186
  end
187
187
  </code></pre>
188
188
 
189
- The old URL will remain indefinitely, but users who hit it will be redirected to the new URL. Ideally, links to the old URL will be replaced over time with links to the new URL.
190
-
191
- The problem is that even though the old slug is inactive, it's still "taken." If you create a product called "Keyboard", but then rename it to "Piano", the product will claim both the "keyboard" and "piano" slugs. If you had renamed it to make room for a different product called "Keyboard" (like a computer keyboard), you'd find its slug is "keyboard;2" or similar.
192
-
193
- To prevent the slug namespace from becoming more and more polluted over time, websites generally expire inactive slugs after a period of time. To do this in Slugalicious, write a task that periodically checks for and deletes old, inactive @Slug@ records. Such a task could be invoked through a cron job, for instance. An example:
189
+ The old URL will remain indefinitely, but users who hit it will be redirected to
190
+ the new URL. Ideally, links to the old URL will be replaced over time with links
191
+ to the new URL.
192
+
193
+ The problem is that even though the old slug is inactive, it's still "taken." If
194
+ you create a product called "Keyboard", but then rename it to "Piano", the
195
+ product will claim both the "keyboard" and "piano" slugs. If you had renamed it
196
+ to make room for a different product called "Keyboard" (like a computer
197
+ keyboard), you'd find its slug is "keyboard;2" or similar.
198
+
199
+ To prevent the slug namespace from becoming more and more polluted over time,
200
+ websites generally expire inactive slugs after a period of time. To do this in
201
+ Slugalicious, write a task that periodically checks for and deletes old,
202
+ inactive @Slug@ records. Such a task could be invoked through a cron job, for
203
+ instance. An example:
194
204
 
195
205
  <pre><code>
196
206
  Slug.inactive.where([ "created_at < ?", 30.days.ago ]).delete_all
data/lib/slugalicious.rb CHANGED
@@ -147,22 +147,26 @@ module Slugalicious
147
147
 
148
148
  module InstanceMethods
149
149
 
150
+ def slug_object
151
+ slugs.loaded? ? slugs.detect(&:active) : slugs.active.first
152
+ end
153
+ private :slug_object
154
+
150
155
  # @return [String, nil] The slug for this object, or @nil@ if none has been
151
156
  # assigned.
152
157
 
153
158
  def slug
154
- (slugs.loaded? ? slugs.detect(&:active?) : slugs.active.first).try(:slug)
159
+ Rails.cache.fetch("Slug/#{self.class.to_s}/#{id}/slug") do
160
+ slug_object.try(:slug)
161
+ end
155
162
  end
156
163
 
157
164
  # @return [String, nil] The full slug and path for this object, with scope
158
165
  # included, or @nil@ if none has been assigned.
159
166
 
160
167
  def slug_with_path
161
- slug = slugs.loaded? ? slugs.detect(&:active) : slugs.active.first
162
- if slug then
163
- slug.scope.to_s + slug.slug
164
- else
165
- nil
168
+ Rails.cache.fetch("Slug/#{self.class.to_s}/#{id}/slug_with_path") do
169
+ slug_object ? (slug_object.scope.to_s + slug_object.slug) : nil
166
170
  end
167
171
  end
168
172
 
data/slugalicious.gemspec CHANGED
@@ -1,68 +1,64 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{slugalicious}
8
- s.version = "1.0.0"
8
+ s.version = "1.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Tim Morgan"]
12
- s.date = %q{2010-10-30}
11
+ s.authors = [%q{Tim Morgan}]
12
+ s.date = %q{2011-08-13}
13
13
  s.description = %q{Slugalicious adds simple and powerful slugging to your ActiveRecord models.}
14
14
  s.email = %q{git@timothymorgan.info}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.textile"
17
+ "README.textile"
18
18
  ]
19
19
  s.files = [
20
- ".document",
21
- ".gitignore",
22
- ".rspec",
23
- "Gemfile",
24
- "Gemfile.lock",
25
- "LICENSE",
26
- "README.textile",
27
- "Rakefile",
28
- "VERSION",
29
- "lib/slugalicious.rb",
30
- "lib/slugalicious_generator.rb",
31
- "slugalicious.gemspec",
32
- "spec/factories.rb",
33
- "spec/slug_spec.rb",
34
- "spec/slugalicious_spec.rb",
35
- "spec/spec_helper.rb",
36
- "templates/create_slugs.rb",
37
- "templates/slug.rb"
20
+ "LICENSE",
21
+ "README.textile",
22
+ "lib/slugalicious.rb",
23
+ "lib/slugalicious_generator.rb",
24
+ "slugalicious.gemspec",
25
+ "templates/create_slugs.rb",
26
+ "templates/slug.rb"
38
27
  ]
39
28
  s.homepage = %q{http://github.com/riscfuture/slugalicious}
40
- s.rdoc_options = ["--charset=UTF-8"]
41
- s.require_paths = ["lib"]
29
+ s.require_paths = [%q{lib}]
42
30
  s.required_ruby_version = Gem::Requirement.new(">= 1.9")
43
- s.rubygems_version = %q{1.3.7}
31
+ s.rubygems_version = %q{1.8.7}
44
32
  s.summary = %q{Easy-to-use and powerful slugging for Rails 3}
45
- s.test_files = [
46
- "spec/factories.rb",
47
- "spec/slug_spec.rb",
48
- "spec/slugalicious_spec.rb",
49
- "spec/spec_helper.rb"
50
- ]
51
33
 
52
34
  if s.respond_to? :specification_version then
53
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
35
  s.specification_version = 3
55
36
 
56
37
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
38
  s.add_runtime_dependency(%q<rails>, [">= 3.0"])
58
39
  s.add_runtime_dependency(%q<stringex>, [">= 0"])
40
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
41
+ s.add_runtime_dependency(%q<yard>, [">= 0"])
42
+ s.add_runtime_dependency(%q<RedCloth>, [">= 0"])
43
+ s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
44
+ s.add_runtime_dependency(%q<rspec>, [">= 0"])
59
45
  else
60
46
  s.add_dependency(%q<rails>, [">= 3.0"])
61
47
  s.add_dependency(%q<stringex>, [">= 0"])
48
+ s.add_dependency(%q<jeweler>, [">= 0"])
49
+ s.add_dependency(%q<yard>, [">= 0"])
50
+ s.add_dependency(%q<RedCloth>, [">= 0"])
51
+ s.add_dependency(%q<sqlite3>, [">= 0"])
52
+ s.add_dependency(%q<rspec>, [">= 0"])
62
53
  end
63
54
  else
64
55
  s.add_dependency(%q<rails>, [">= 3.0"])
65
56
  s.add_dependency(%q<stringex>, [">= 0"])
57
+ s.add_dependency(%q<jeweler>, [">= 0"])
58
+ s.add_dependency(%q<yard>, [">= 0"])
59
+ s.add_dependency(%q<RedCloth>, [">= 0"])
60
+ s.add_dependency(%q<sqlite3>, [">= 0"])
61
+ s.add_dependency(%q<rspec>, [">= 0"])
66
62
  end
67
63
  end
68
64
 
metadata CHANGED
@@ -1,112 +1,130 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: slugalicious
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 1
7
- - 0
8
- - 0
9
- version: 1.0.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Tim Morgan
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-10-30 00:00:00 -07:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-08-13 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rails
22
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &2162887120 !ruby/object:Gem::Requirement
23
17
  none: false
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 3
29
- - 0
30
- version: "3.0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
31
22
  type: :runtime
32
23
  prerelease: false
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
24
+ version_requirements: *2162887120
25
+ - !ruby/object:Gem::Dependency
35
26
  name: stringex
36
- requirement: &id002 !ruby/object:Gem::Requirement
27
+ requirement: &2162886240 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2162886240
36
+ - !ruby/object:Gem::Dependency
37
+ name: jeweler
38
+ requirement: &2162884900 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2162884900
47
+ - !ruby/object:Gem::Dependency
48
+ name: yard
49
+ requirement: &2162884020 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *2162884020
58
+ - !ruby/object:Gem::Dependency
59
+ name: RedCloth
60
+ requirement: &2162883400 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *2162883400
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: &2162882740 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *2162882740
80
+ - !ruby/object:Gem::Dependency
81
+ name: rspec
82
+ requirement: &2162882100 !ruby/object:Gem::Requirement
37
83
  none: false
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- version: "0"
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
44
88
  type: :runtime
45
89
  prerelease: false
46
- version_requirements: *id002
90
+ version_requirements: *2162882100
47
91
  description: Slugalicious adds simple and powerful slugging to your ActiveRecord models.
48
92
  email: git@timothymorgan.info
49
93
  executables: []
50
-
51
94
  extensions: []
52
-
53
- extra_rdoc_files:
95
+ extra_rdoc_files:
54
96
  - LICENSE
55
97
  - README.textile
56
- files:
57
- - .document
58
- - .gitignore
59
- - .rspec
60
- - Gemfile
61
- - Gemfile.lock
98
+ files:
62
99
  - LICENSE
63
100
  - README.textile
64
- - Rakefile
65
- - VERSION
66
101
  - lib/slugalicious.rb
67
102
  - lib/slugalicious_generator.rb
68
103
  - slugalicious.gemspec
69
- - spec/factories.rb
70
- - spec/slug_spec.rb
71
- - spec/slugalicious_spec.rb
72
- - spec/spec_helper.rb
73
104
  - templates/create_slugs.rb
74
105
  - templates/slug.rb
75
- has_rdoc: true
76
106
  homepage: http://github.com/riscfuture/slugalicious
77
107
  licenses: []
78
-
79
108
  post_install_message:
80
- rdoc_options:
81
- - --charset=UTF-8
82
- require_paths:
109
+ rdoc_options: []
110
+ require_paths:
83
111
  - lib
84
- required_ruby_version: !ruby/object:Gem::Requirement
112
+ required_ruby_version: !ruby/object:Gem::Requirement
85
113
  none: false
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- segments:
90
- - 1
91
- - 9
92
- version: "1.9"
93
- required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '1.9'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
119
  none: false
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- segments:
99
- - 0
100
- version: "0"
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
101
124
  requirements: []
102
-
103
125
  rubyforge_project:
104
- rubygems_version: 1.3.7
126
+ rubygems_version: 1.8.7
105
127
  signing_key:
106
128
  specification_version: 3
107
129
  summary: Easy-to-use and powerful slugging for Rails 3
108
- test_files:
109
- - spec/factories.rb
110
- - spec/slug_spec.rb
111
- - spec/slugalicious_spec.rb
112
- - spec/spec_helper.rb
130
+ test_files: []
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/.gitignore DELETED
@@ -1,26 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
- .bundle
21
- .rvmrc
22
- test.sqlite
23
-
24
- ## PROJECT::DOCUMENTATION
25
- .yardoc
26
- doc
data/.rspec DELETED
@@ -1 +0,0 @@
1
- -cfs
data/Gemfile DELETED
@@ -1,17 +0,0 @@
1
- source :rubygems
2
-
3
- # DEPENDENCIES
4
- gem 'rails', '>= 3.0'
5
- gem 'stringex'
6
-
7
- # DEVELOPMENT
8
- gem 'jeweler'
9
- gem 'yard'
10
- gem 'RedCloth', require: 'redcloth'
11
- gem 'sqlite3'
12
-
13
- # TEST
14
- gem 'rspec'
15
- group :test do
16
- gem 'factory_girl'
17
- end
data/Gemfile.lock DELETED
@@ -1,107 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- RedCloth (4.2.3)
5
- abstract (1.0.0)
6
- actionmailer (3.0.1)
7
- actionpack (= 3.0.1)
8
- mail (~> 2.2.5)
9
- actionpack (3.0.1)
10
- activemodel (= 3.0.1)
11
- activesupport (= 3.0.1)
12
- builder (~> 2.1.2)
13
- erubis (~> 2.6.6)
14
- i18n (~> 0.4.1)
15
- rack (~> 1.2.1)
16
- rack-mount (~> 0.6.12)
17
- rack-test (~> 0.5.4)
18
- tzinfo (~> 0.3.23)
19
- activemodel (3.0.1)
20
- activesupport (= 3.0.1)
21
- builder (~> 2.1.2)
22
- i18n (~> 0.4.1)
23
- activerecord (3.0.1)
24
- activemodel (= 3.0.1)
25
- activesupport (= 3.0.1)
26
- arel (~> 1.0.0)
27
- tzinfo (~> 0.3.23)
28
- activeresource (3.0.1)
29
- activemodel (= 3.0.1)
30
- activesupport (= 3.0.1)
31
- activesupport (3.0.1)
32
- arel (1.0.1)
33
- activesupport (~> 3.0.0)
34
- builder (2.1.2)
35
- diff-lcs (1.1.2)
36
- erubis (2.6.6)
37
- abstract (>= 1.0.0)
38
- factory_girl (1.3.2)
39
- ffi (0.6.3)
40
- rake (>= 0.8.7)
41
- gemcutter (0.6.1)
42
- git (1.2.5)
43
- i18n (0.4.2)
44
- jeweler (1.4.0)
45
- gemcutter (>= 0.1.0)
46
- git (>= 1.2.5)
47
- rubyforge (>= 2.0.0)
48
- json_pure (1.4.6)
49
- mail (2.2.9)
50
- activesupport (>= 2.3.6)
51
- i18n (~> 0.4.1)
52
- mime-types (~> 1.16)
53
- treetop (~> 1.4.8)
54
- mime-types (1.16)
55
- polyglot (0.3.1)
56
- rack (1.2.1)
57
- rack-mount (0.6.13)
58
- rack (>= 1.0.0)
59
- rack-test (0.5.6)
60
- rack (>= 1.0)
61
- rails (3.0.1)
62
- actionmailer (= 3.0.1)
63
- actionpack (= 3.0.1)
64
- activerecord (= 3.0.1)
65
- activeresource (= 3.0.1)
66
- activesupport (= 3.0.1)
67
- bundler (~> 1.0.0)
68
- railties (= 3.0.1)
69
- railties (3.0.1)
70
- actionpack (= 3.0.1)
71
- activesupport (= 3.0.1)
72
- rake (>= 0.8.4)
73
- thor (~> 0.14.0)
74
- rake (0.8.7)
75
- rspec (2.0.1)
76
- rspec-core (~> 2.0.1)
77
- rspec-expectations (~> 2.0.1)
78
- rspec-mocks (~> 2.0.1)
79
- rspec-core (2.0.1)
80
- rspec-expectations (2.0.1)
81
- diff-lcs (>= 1.1.2)
82
- rspec-mocks (2.0.1)
83
- rspec-core (~> 2.0.1)
84
- rspec-expectations (~> 2.0.1)
85
- rubyforge (2.0.4)
86
- json_pure (>= 1.1.7)
87
- sqlite3 (0.1.1)
88
- ffi (>= 0.6.3)
89
- stringex (1.2.0)
90
- thor (0.14.3)
91
- treetop (1.4.8)
92
- polyglot (>= 0.3.1)
93
- tzinfo (0.3.23)
94
- yard (0.6.1)
95
-
96
- PLATFORMS
97
- ruby
98
-
99
- DEPENDENCIES
100
- RedCloth
101
- factory_girl
102
- jeweler
103
- rails (>= 3.0)
104
- rspec
105
- sqlite3
106
- stringex
107
- yard
data/Rakefile DELETED
@@ -1,37 +0,0 @@
1
- require 'rake'
2
- begin
3
- require 'bundler'
4
- rescue LoadError
5
- puts "Bundler is not installed; install with `gem install bundler`."
6
- exit 1
7
- end
8
-
9
- Bundler.require :default
10
-
11
- Jeweler::Tasks.new do |gem|
12
- gem.name = "slugalicious"
13
- gem.summary = %Q{Easy-to-use and powerful slugging for Rails 3}
14
- gem.description = %Q{Slugalicious adds simple and powerful slugging to your ActiveRecord models.}
15
- gem.email = "git@timothymorgan.info"
16
- gem.homepage = "http://github.com/riscfuture/slugalicious"
17
- gem.authors = [ "Tim Morgan" ]
18
- gem.required_ruby_version = '>= 1.9'
19
- gem.add_dependency "rails", ">= 3.0"
20
- gem.add_dependency 'stringex'
21
- end
22
- Jeweler::GemcutterTasks.new
23
-
24
- require 'rspec/core/rake_task'
25
- RSpec::Core::RakeTask.new
26
-
27
- YARD::Rake::YardocTask.new('doc') do |doc|
28
- doc.options << "-m" << "textile"
29
- doc.options << "--protected"
30
- doc.options << "-r" << "README.textile"
31
- doc.options << "-o" << "doc"
32
- doc.options << "--title" << "Slugalicious Documentation".inspect
33
-
34
- doc.files = [ 'lib/**/*', 'README.textile', 'templates/slug.rb' ]
35
- end
36
-
37
- task(default: :spec)
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.0.0
data/spec/factories.rb DELETED
@@ -1,14 +0,0 @@
1
- Factory.define :slug do |f|
2
- f.sequence(:slug) { |n| "slug-#{n}" }
3
- f.active true
4
- end
5
-
6
- Factory.define :user do |f|
7
- f.first_name "Doctor"
8
- f.last_name "Spaceman"
9
- end
10
-
11
- Factory.define :abuser do |f|
12
- f.first_name "Doctor"
13
- f.last_name "Spaceman"
14
- end
data/spec/slug_spec.rb DELETED
@@ -1,65 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Slug do
4
- before :each do
5
- @record = Factory(:user)
6
- Slug.delete_all
7
- end
8
-
9
- describe "validation" do
10
- it "should not allow an active slug to be created if one already exists" do
11
- Factory(:slug, sluggable: @record)
12
- slug = Factory.build(:slug, sluggable: @record)
13
- slug.should_not be_valid
14
- slug.errors[:active].should_not be_empty
15
- end
16
-
17
- it "should not allow a slug to be made active if one already exists" do
18
- Factory(:slug, sluggable: @record)
19
- slug = Factory(:slug, sluggable: @record, active: false)
20
- slug.active = true
21
- slug.should_not be_valid
22
- slug.errors[:active].should_not be_empty
23
- end
24
-
25
- it "should allow an active slug to be created if none exists" do
26
- slug = Factory.build(:slug, sluggable: @record)
27
- slug.should be_valid
28
- end
29
-
30
- it "should allow a slug to be made active if none exists" do
31
- slug = Factory(:slug, sluggable: @record, active: false)
32
- slug.active = true
33
- slug.should be_valid
34
- end
35
-
36
- it "should allow an inactive slug to be modified if the active field is not changing" do
37
- Factory(:slug, sluggable: @record)
38
- slug = Factory(:slug, sluggable: @record, active: false)
39
- slug.scope = 'test'
40
- slug.should be_valid
41
- end
42
- end
43
-
44
- describe "#activate!" do
45
- it "should mark the slug as active" do
46
- slug = Factory(:slug, sluggable: Factory(:user), active: false)
47
- slug.activate!
48
- slug.should be_active
49
- end
50
-
51
- it "should deactivate all the record's other slugs" do
52
- record = Factory(:user)
53
- s1 = Slug.for(record).first
54
- s2 = Factory(:slug, sluggable: record, active: false)
55
- s3 = Factory(:slug, sluggable: record, active: false)
56
-
57
- slug = Factory(:slug, sluggable: record, active: false)
58
- slug.activate!
59
-
60
- s1.reload.should_not be_active
61
- s2.reload.should_not be_active
62
- s3.reload.should_not be_active
63
- end
64
- end
65
- end
@@ -1,232 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe Slugalicious do
4
- before :each do
5
- @model = Class.new
6
- @model.send :include, ActiveModel::Validations
7
- @model.send :include, ActiveModel::Validations::Callbacks
8
- @model.send :include, ActiveRecord::Callbacks
9
- @model.send :include, ActiveRecord::Validations
10
- @model.stub!(:has_many)
11
- @model.send :include, Slugalicious
12
- end
13
-
14
- describe "#slugged" do
15
- it "should raise an error if no generators are given" do
16
- expect { @model.send(:slugged, { options: 'here' }) }.to raise_error(ArgumentError)
17
- end
18
- end
19
-
20
- describe "#to_param" do
21
- it "should return the slug" do
22
- user = Factory(:user)
23
- user.slug.should_not be_nil
24
- user.to_param.should eql(user.slug)
25
- end
26
-
27
- it "should return the full slug path when scoped" do
28
- User._slug_procs.clear
29
- User.send :slugged, :first_name, scope: :last_name
30
-
31
- user = Factory(:user, last_name: 'test/')
32
- user.to_param.should eql('test/doctor')
33
- end
34
- end
35
-
36
- context "slug generation" do
37
- before :each do
38
- User._slug_procs.clear
39
- User._slug_blacklist.clear
40
- end
41
-
42
- it "should set the slug according to the generator and apply the slugifier" do
43
- User.send :slugged, :first_name
44
- object = Factory(:user, first_name: "Sancho", last_name: "Sample")
45
- object.slug.should eql("sancho")
46
- end
47
-
48
- it "should generate from a proc as well as a symbol" do
49
- User.send :slugged, ->(person) { "#{person.first_name} #{person.last_name}" }
50
- object = Factory(:user, first_name: "Foo", last_name: "bar")
51
- object.slug.should eql("foo-bar")
52
- end
53
-
54
- it "should give priority to the first non-nil slug" do
55
- User.send :slugged, :gender, :last_name
56
- object = Factory(:user, gender: nil, last_name: "Bar")
57
- object.slug.should eql("bar")
58
- end
59
-
60
- it "should not create a new slug if an existing one matches" do
61
- User.send :slugged, :first_name, :last_name
62
- object = Factory(:user, first_name: 'Foo', last_name: "Bar")
63
- object.slug.should eql("foo")
64
- other_slug = Factory(:slug, slug: 'bar', sluggable: object, active: false)
65
-
66
- object.update_attribute :last_name, 'baz'
67
- object.slug.should eql("foo")
68
- other_slug.reload.active.should be_false
69
- end
70
-
71
- it "should ignore slugs from other models" do
72
- User.send :slugged, :first_name, :last_name
73
- Factory(:abuser, last_name: 'Foo').slug.should eql('foo')
74
- Factory(:user, first_name: 'Foo', last_name: 'Foo').slug.should eql('foo')
75
- end
76
-
77
- it "should use the last-resort generator if nothing else is unique" do
78
- User.send :slugged, :first_name, :last_name
79
- Factory(:user, first_name: 'Foo', last_name: 'Bar').slug.should eql('foo')
80
- Factory(:user, first_name: 'Foo', last_name: 'Bar').slug.should eql('bar')
81
- user = Factory(:user, first_name: 'Foo', last_name: 'Bar')
82
- user.slug.should eql("foo;#{user.id}")
83
- end
84
-
85
- it "should raise an error if all generators return nil" do
86
- User.send :slugged, :gender, :birthdate
87
- -> { Factory(:user, gender: nil, birthdate: nil) }.should raise_error
88
- end
89
-
90
- it "should use the first non-nil slug for the last-resort generator" do
91
- User.send :slugged, :gender, :first_name, :last_name
92
- Factory(:user, first_name: 'Foo', last_name: 'Bar', gender: nil)
93
- Factory(:user, first_name: 'Foo', last_name: 'Bar', gender: nil)
94
- user = Factory(:user, first_name: 'Foo', last_name: 'Bar', gender: nil)
95
- user.slug.should eql("foo;#{user.id}")
96
- end
97
-
98
- it "should use a custom id separator if given" do
99
- User.send :slugged, :first_name, :last_name, id_separator: ':'
100
- Factory(:user, first_name: 'Foo', last_name: 'Bar')
101
- Factory(:user, first_name: 'Foo', last_name: 'Bar')
102
- user = Factory(:user, first_name: 'Foo', last_name: 'Bar')
103
- user.slug.should eql("foo:#{user.id}")
104
- end
105
-
106
- it "should avoid blacklisted slugs" do
107
- User.send :slugged, :first_name, :last_name
108
- Factory(:user, first_name: 'New', last_name: 'Bar').slug.should eql('bar')
109
- end
110
-
111
- it "should use a custom blacklist" do
112
- User.send :slugged, :first_name, :last_name, blacklist: %w( foo bar )
113
- Factory(:user, first_name: 'Foo', last_name: 'Baz').slug.should eql('baz')
114
- end
115
-
116
- it "should wrap the blacklist array" do
117
- User.send :slugged, :first_name, :last_name, blacklist: 'foo'
118
- Factory(:user, first_name: 'Foo', last_name: 'Baz').slug.should eql('baz')
119
- end
120
-
121
- it "should only search for available slugs inside the scope if given" do
122
- User.send :slugged, :first_name, :last_name, scope: :callsign
123
-
124
- Factory(:user, first_name: 'Foo', last_name: 'Bar', callsign: 'One').slug.should eql('foo')
125
- Factory(:user, first_name: 'Foo', last_name: 'Baz', callsign: 'One').slug.should eql('baz')
126
- Factory(:user, first_name: 'Boo', last_name: 'Bar', callsign: 'One').slug.should eql('boo')
127
-
128
- Factory(:user, first_name: 'Foo', last_name: 'Bar', callsign: 'Two').slug.should eql('foo')
129
- Factory(:user, first_name: 'Foo', last_name: 'Baz', callsign: 'Two').slug.should eql('baz')
130
- end
131
-
132
- it "should accept a proc for a scope" do
133
- User.send :slugged, :first_name, :last_name, scope: ->(object) { object.callsign[0] }
134
-
135
- Factory(:user, first_name: 'Foo', last_name: 'Bar', callsign: 'One').slug.should eql('foo')
136
- Factory(:user, first_name: 'Foo', last_name: 'Baz', callsign: 'Only').slug.should eql('baz')
137
- Factory(:user, first_name: 'Boo', last_name: 'Bar', callsign: 'Ocho').slug.should eql('boo')
138
-
139
- Factory(:user, first_name: 'Foo', last_name: 'Bar', callsign: 'Two').slug.should eql('foo')
140
- Factory(:user, first_name: 'Foo', last_name: 'Baz', callsign: 'Tres').slug.should eql('baz')
141
- end
142
-
143
- it "should enforce a maximum length of 126 characters" do
144
- User.send :slugged, :first_name
145
-
146
- user = Factory(:user)
147
- user.first_name = 'A'*500
148
- user.save(validate: false)
149
- user.slug.should eql('a'*126)
150
- end
151
-
152
- it "should shorten left of the ID separator" do
153
- User.send :slugged, :first_name
154
-
155
- user1 = Factory(:user)
156
- user1.first_name = 'A'*500
157
- user1.save(validate: false)
158
-
159
- user2 = Factory(:user)
160
- user2.first_name = 'A'*500
161
- user2.save(validate: false)
162
-
163
- user2.slug.size.should eql(126)
164
- user2.slug.should match(/^a+;#{user2.id}$/)
165
- end
166
-
167
- it "should raise an error if no unique slugs are available" do
168
- old_length = Slugalicious::MAX_SLUG_LENGTH
169
- Slugalicious::MAX_SLUG_LENGTH = 1
170
-
171
- User.send :slugged, ->(object) { 'f' }, blacklist: 'f'
172
- -> { Factory(:user, first_name: 'Foo', last_name: 'Bar') }.should raise_error
173
-
174
- Slugalicious::MAX_SLUG_LENGTH = old_length
175
- end
176
- end
177
-
178
- describe "#find_from_slug" do
179
- it "should return a Slug object for a slug" do
180
- User.send :slugged, :first_name, :last_name
181
- user1 = Factory(:user, first_name: "FN1", last_name: "LN1")
182
- User.find_from_slug('fn1').should eql(user1)
183
- end
184
-
185
- it "should exclude slugs of other models" do
186
- User.send :slugged, :first_name, :last_name
187
- user1 = Factory(:user, first_name: "FN1", last_name: "LN1")
188
- Factory(:abuser, first_name: 'FN1')
189
- User.find_from_slug('fn1').should eql(user1)
190
- end
191
-
192
- it "should locate an object within a given scope" do
193
- User.send :slugged, :first_name, scope: :last_name
194
- user1 = Factory(:user, first_name: "FN1", last_name: "LN1")
195
- user2 = Factory(:user, first_name: "FN1", last_name: "LN2")
196
- User.find_from_slug('fn1', 'LN1').should eql(user1)
197
- User.find_from_slug('fn1', 'LN2').should eql(user2)
198
- end
199
-
200
- it "should raise ActiveRecord::RecordNotFound if the slug does not exist" do
201
- -> { User.find_from_slug('nonexist') }.should raise_error(ActiveRecord::RecordNotFound)
202
- end
203
-
204
- it "should raise ActiveRecord::RecordNotFound if the slug does not exist in scope" do
205
- User.send :slugged, :first_name, scope: :last_name
206
- Factory(:user, first_name: "FN1", last_name: "LN1")
207
- Factory(:user, first_name: "FN2", last_name: "LN2")
208
- -> { User.find_from_slug('fn2', 'ln1') }.should raise_error(ActiveRecord::RecordNotFound)
209
- end
210
-
211
- it "should find inactive slugs" do
212
- User.send :slugged, :first_name
213
- user = Factory(:user, first_name: 'New')
214
- Factory(:slug, sluggable: user, slug: 'old', active: false)
215
- User.find_from_slug('old').should eql(user)
216
- end
217
- end
218
-
219
- describe "#find_from_slug_path" do
220
- it "should call #find_from_slug with the slug and no scope for unscoped models" do
221
- User.send :slugged, :first_name
222
- User.should_receive(:find_from_slug).once.with("test", '')
223
- User.find_from_slug_path("test")
224
- end
225
-
226
- it "should call #find_from_slug with the slug and scope for scoped models" do
227
- User.send :slugged, :first_name, scope: :last_name
228
- User.should_receive(:find_from_slug).once.with("test", "path/to/")
229
- User.find_from_slug_path("path/to/test")
230
- end
231
- end
232
- end
data/spec/spec_helper.rb DELETED
@@ -1,45 +0,0 @@
1
- Bundler.require :default, :test
2
- require 'active_support'
3
- require 'active_record'
4
-
5
- $LOAD_PATH.unshift(File.dirname(__FILE__))
6
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
-
8
- require 'slugalicious'
9
-
10
- ActiveRecord::Base.establish_connection(
11
- adapter: 'sqlite3',
12
- database: 'test.sqlite'
13
- )
14
- require "#{File.dirname __FILE__}/../templates/slug"
15
-
16
- class User < ActiveRecord::Base
17
- include Slugalicious
18
- slugged :last_name, ->(user) { "#{user.first_name} #{user.last_name}" }
19
- end
20
- class Abuser < ActiveRecord::Base
21
- include Slugalicious
22
- slugged :last_name, ->(user) { "#{user.first_name} #{user.last_name}" }
23
- end
24
-
25
- require "#{File.dirname __FILE__}/factories"
26
-
27
- RSpec.configure do |config|
28
- config.before(:each) do
29
- Slug.connection.execute "DROP TABLE IF EXISTS slugs"
30
- Slug.connection.execute <<-SQL
31
- CREATE TABLE slugs (
32
- id INTEGER PRIMARY KEY ASC,
33
- sluggable_type VARCHAR(126) NOT NULL,
34
- sluggable_id INTEGER NOT NULL,
35
- active BOOLEAN NOT NULL DEFAULT 1,
36
- slug VARCHAR(126) NOT NULL,
37
- scope VARCHAR(126)
38
- )
39
- SQL
40
- User.connection.execute "DROP TABLE IF EXISTS users"
41
- User.connection.execute "CREATE TABLE users (id INTEGER PRIMARY KEY ASC, first_name TEXT, last_name TEXT, callsign TEXT, gender VARCHAR(7))"
42
- Abuser.connection.execute "DROP TABLE IF EXISTS abusers"
43
- Abuser.connection.execute "CREATE TABLE abusers (id INTEGER PRIMARY KEY ASC, first_name TEXT, last_name TEXT, callsign TEXT, gender VARCHAR(7))"
44
- end
45
- end