slugged 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ module Slugged
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 3
5
+ PATCH = 2
6
+ STRING = [MAJOR, MINOR, PATCH].join(".")
7
+ end
8
+ end
@@ -0,0 +1,77 @@
1
+ require 'helper'
2
+
3
+ class CachingTest < Test::Unit::TestCase
4
+ with_tables :slugs, :users do
5
+
6
+ setup { Slugged::MemoryCache.reset! }
7
+
8
+ context 'with the default slug setup' do
9
+
10
+ setup { setup_slugs! }
11
+
12
+ should 'store a cache automatically after finding it' do
13
+ assert_has_no_cache_for "bob"
14
+ u = User.create :name => "Bob"
15
+ assert_has_cache_for "bob"
16
+ Slugged::MemoryCache.reset!
17
+ assert_has_no_cache_for "bob"
18
+ assert_same_as_slug u, "bob"
19
+ assert_has_cache_for "bob"
20
+ assert_same_as_slug u, "bob"
21
+ end
22
+
23
+ should 'automatically keep cache entries for history by default' do
24
+ setup_slugs!
25
+ assert_has_no_cache_for "bob"
26
+ assert_has_no_cache_for "red"
27
+ assert_has_no_cache_for "sam"
28
+ user = User.create :name => "bob"
29
+ assert_has_cache_for "bob"
30
+ assert_has_no_cache_for "red"
31
+ assert_has_no_cache_for "sam"
32
+ user.update_attributes :name => "Red"
33
+ assert_has_cache_for "bob"
34
+ assert_has_cache_for "red"
35
+ assert_has_no_cache_for "sam"
36
+ user.update_attributes :name => "Sam"
37
+ assert_has_cache_for "bob"
38
+ assert_has_cache_for "red"
39
+ assert_has_cache_for "sam"
40
+ end
41
+
42
+ end
43
+
44
+ should 'remove cache on models without history' do
45
+ setup_slugs! :history => false
46
+ u = User.create :name => "Bob"
47
+ assert_has_cache_for "bob"
48
+ assert_has_no_cache_for "red"
49
+ assert_has_no_cache_for "sam"
50
+ u.update_attributes :name => "Red"
51
+ u.update_attributes :name => "Sam"
52
+ assert_has_no_cache_for "bob"
53
+ assert_has_no_cache_for "red"
54
+ assert_has_cache_for "sam"
55
+ end
56
+
57
+ should 'allow you to disable caching' do
58
+ setup_slugs! :use_cache => false
59
+ assert !User.respond_to?(:has_cache_for_slug?)
60
+ end
61
+
62
+ # Ensure we destroy the contents of the cache after each test.
63
+ teardown { Slugged::MemoryCache.reset! }
64
+
65
+ end
66
+
67
+ protected
68
+
69
+ def assert_has_cache_for(key)
70
+ assert User.has_cache_for_slug?(key), "User should have a cache entry for #{key.inspect}"
71
+ end
72
+
73
+ def assert_has_no_cache_for(key)
74
+ assert !User.has_cache_for_slug?(key), "User should not have a cache entry for #{key.inspect}"
75
+ end
76
+
77
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,44 @@
1
+ $KCODE = 'UTF8'
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler.setup
6
+ Bundler.require
7
+
8
+ require 'test/unit'
9
+ require 'shoulda'
10
+ require 'redgreen' if RUBY_VERSION < '1.9'
11
+ require 'ruby-debug' if ENV['DEBUG']
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'slugged'
16
+ require 'model_definitions'
17
+
18
+ # Use a memory cache for testing.
19
+ Slugged.cache = Slugged::MemoryCache
20
+
21
+ class Test::Unit::TestCase
22
+ extend ReversibleData::ShouldaMacros
23
+
24
+ def setup_slugs!(*args)
25
+ options = args.extract_options!
26
+ field = args.pop || :name
27
+ User.is_sluggable field, options
28
+ end
29
+
30
+ def assert_same_as_slug(user, slug, options = {})
31
+ found_user = User.find_using_slug(slug, options)
32
+ assert_equal user, found_user, "#{slug.inspect} should return #{user.inspect}, got #{found_user.inspect}"
33
+ end
34
+
35
+ def assert_different_to_slug(user, slug, options = {})
36
+ found_user = User.find_using_slug(slug, options)
37
+ assert_not_equal user, found_user, "#{slug.inspect} should not return #{user.inspect}, got same record."
38
+ end
39
+
40
+ def assert_none_for_slug(slug)
41
+ assert User.find_using_slug(slug).blank?, "slug #{slug.inspect} should not return any records."
42
+ end
43
+
44
+ end
@@ -0,0 +1,155 @@
1
+ require 'helper'
2
+ require 'digest/md5'
3
+
4
+ class IsSluggableTest < Test::Unit::TestCase
5
+ with_tables :slugs, :users do
6
+
7
+ class StringWrapper < String
8
+ def to_url; "my-demo-slug"; end
9
+ end
10
+
11
+ context 'with the default slug options' do
12
+
13
+ setup { setup_slugs! }
14
+
15
+ should 'correctly sluggify a value' do
16
+ user = User.create(:name => "Bob")
17
+ assert_equal "bob", user.to_param
18
+ assert_equal "bob", user.cached_slug
19
+ end
20
+
21
+ should 'generate a uuid in place of a slug' do
22
+ user = User.create(:name => '')
23
+ assert user.cached_slug.present?
24
+ end
25
+
26
+ should 'return need to generate a slug when the cahced slug is blank' do
27
+ user = User.new(:name => "Ninja Stuff")
28
+ assert user.cached_slug.blank?
29
+ assert user.should_generate_slug?
30
+ user.save
31
+ assert user.cached_slug.present?
32
+ assert !user.should_generate_slug?
33
+ user.name = 'Awesome'
34
+ assert user.should_generate_slug?
35
+ end
36
+
37
+ should "let you find a record by it's id as needed" do
38
+ user = User.create :name => "Bob"
39
+ assert_equal user, User.find_using_slug(user.id)
40
+ assert_equal user, User.find_using_slug(user.id.to_i)
41
+ end
42
+
43
+ should 'return nil for unfound slugs by default' do
44
+ assert_nil User.find_using_slug("awesome")
45
+ end
46
+
47
+ should 'let you find slugs and raise an exception' do
48
+ assert_raises(ActiveRecord::RecordNotFound) do
49
+ User.find_using_slug!("awesome")
50
+ end
51
+ end
52
+
53
+ should 'default to generate a uuid' do
54
+ user = User.create :name => ""
55
+ assert_match /\A[a-zA-Z0-9]{32}\Z/, user.cached_slug.gsub("-", "")
56
+ user = User.create
57
+ assert_match /\A[a-zA-Z0-9]{32}\Z/, user.cached_slug.gsub("-", "")
58
+ end
59
+
60
+ should 'automatically append a sequence to the end of conflicting slugs' do
61
+ u1 = User.create :name => "ninjas Are awesome"
62
+ u2 = User.create :name => "Ninjas are awesome"
63
+ assert_equal "ninjas-are-awesome", u1.to_slug
64
+ assert_equal "ninjas-are-awesome--1", u2.to_slug
65
+ end
66
+
67
+ should 'let you find out if there is a better way of finding a slug' do
68
+ user = User.create :name => "Bob"
69
+ user.update_attributes! :name => "Ralph"
70
+ assert !User.find_using_slug("ralph").has_better_slug?
71
+ assert User.find_using_slug("bob").has_better_slug?
72
+ assert User.find_using_slug(user.id).has_better_slug?
73
+ end
74
+
75
+ should 'not keep a users slug when updating themselves' do
76
+ user = User.create :name => "bob is awesome"
77
+ assert_equal "bob-is-awesome", user.to_param
78
+ assert !user.new_record?
79
+ user.update_attributes :name => "BOB-is-AWESOME"
80
+ assert_equal "bob-is-awesome", user.to_param
81
+ end
82
+
83
+ end
84
+
85
+ context 'with slug syncing disabled' do
86
+ setup { setup_slugs! :sync => false }
87
+
88
+ should 'let you disable syncing a slug' do
89
+ user = User.create(:name => "Ninja User")
90
+ assert !user.should_generate_slug?
91
+ user.name = "Another User Name"
92
+ assert !user.should_generate_slug?
93
+ end
94
+
95
+ should 'let you force slug generation' do
96
+ user = User.create(:name => "Ninja User")
97
+ assert_equal "ninja-user", user.to_slug
98
+ user.update_attributes :name => "Test User"
99
+ assert_equal "ninja-user", user.to_slug
100
+ user.generate_slug!
101
+ assert_equal "test-user", user.to_slug
102
+ user.reload
103
+ assert_equal "test-user", user.to_slug
104
+ end
105
+
106
+ should 'let you force the update of all slugs' do
107
+ user_a = User.create(:name => "User A")
108
+ user_b = User.create(:name => "User B")
109
+ user_c = User.create(:name => "User C")
110
+ user_a.update_attributes :name => "User A-1"
111
+ user_b.update_attributes :name => "User B-1"
112
+ user_c.update_attributes :name => "User C-1"
113
+ assert_equal "user-a", user_a.to_slug
114
+ assert_equal "user-b", user_b.to_slug
115
+ assert_equal "user-c", user_c.to_slug
116
+ User.update_all_slugs!
117
+ user_a.reload
118
+ user_b.reload
119
+ user_c.reload
120
+ assert_equal "user-a-1", user_a.to_slug
121
+ assert_equal "user-b-1", user_b.to_slug
122
+ assert_equal "user-c-1", user_c.to_slug
123
+ end
124
+
125
+ end
126
+
127
+ context 'setting slug convertors' do
128
+
129
+ should 'let you specify a symbol' do
130
+ setup_slugs! :convertor => :upcase
131
+ assert_equal "AWESOME USER", User.create(:name => "Awesome User").to_slug
132
+ end
133
+
134
+ should 'let you specify a proc' do
135
+ setup_slugs! :convertor => proc { |r| r.reverse.upcase }
136
+ assert_equal "RESU EMOSEWA", User.create(:name => "Awesome User").to_slug
137
+ end
138
+
139
+ should 'call to_url if available by default' do
140
+ setup_slugs!
141
+ original_value = StringWrapper.new("Awesome User")
142
+ assert_equal "my-demo-slug", User.create(:name => original_value).to_slug
143
+ end
144
+
145
+ end
146
+
147
+ should 'set the cached slug to nil if uuid is nil and the source value is blank' do
148
+ setup_slugs! :uuid => nil
149
+ record = User.create(:name => "")
150
+ assert_nil record.cached_slug
151
+ assert_equal record.id.to_s, record.to_slug
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,19 @@
1
+ require 'reversible_data'
2
+
3
+ ReversibleData.in_memory!
4
+
5
+ # Define models here.
6
+
7
+ ReversibleData.add :slugs do |t|
8
+ t.string :scope
9
+ t.string :slug
10
+ t.integer :record_id
11
+ t.datetime :created_at
12
+ end
13
+
14
+ ReversibleData.add :users do |u|
15
+ u.string :name
16
+ u.string :address
17
+ u.string :cached_slug
18
+ u.timestamps
19
+ end
@@ -0,0 +1,86 @@
1
+ require 'helper'
2
+
3
+ class FakedModel
4
+ attr_reader :id
5
+ def self.slug_scope_key; "faked_models"; end
6
+ def initialize(id); @id = id; end
7
+ end
8
+
9
+ class SlugHistoryTest < Test::Unit::TestCase
10
+ with_tables :slugs, :users do
11
+
12
+ context 'for arbitrary models' do
13
+
14
+ setup do
15
+ @record_a = FakedModel.new(12)
16
+ @record_b = FakedModel.new(4)
17
+ Slugged.record_slug(@record_a, "awesome")
18
+ Slugged.record_slug(@record_b, "awesome-1")
19
+ Slugged.record_slug(@record_a, "ninjas")
20
+ end
21
+
22
+ should 'let you lookup a given record id easily' do
23
+ assert Slugged.last_known_slug_id(FakedModel, "felafel").blank?
24
+ assert Slugged.last_known_slug_id(FakedModel, "ninjas-2").blank?
25
+ assert_equal 12, Slugged.last_known_slug_id(FakedModel, "awesome")
26
+ assert_equal 4, Slugged.last_known_slug_id(FakedModel, "awesome-1")
27
+ assert_equal 12, Slugged.last_known_slug_id(FakedModel, "ninjas")
28
+ end
29
+
30
+ should 'let you return slug history for a given record'
31
+
32
+ end
33
+
34
+ context 'on a specific record' do
35
+
36
+ should 'by default record slug history' do
37
+ setup_slugs!
38
+ user = User.create :name => "Bob"
39
+ assert_equal [], user.previous_slugs
40
+ user.update_attributes! :name => "Sal"
41
+ user.update_attributes! :name => "Red"
42
+ user.update_attributes! :name => "Jim"
43
+ assert_same_as_slug user, "red"
44
+ assert_same_as_slug user, "sal"
45
+ assert_same_as_slug user, "bob"
46
+ assert_same_as_slug user, "jim"
47
+ end
48
+
49
+ should 'let you reset history for a slug' do
50
+ setup_slugs!
51
+ user = User.create :name => "Bob"
52
+ user.update_attributes! :name => "Sal"
53
+ user.update_attributes! :name => "Red"
54
+ user.update_attributes! :name => "Jim"
55
+ assert_equal ["red", "sal", "bob"], user.previous_slugs
56
+ user.remove_slug_history!
57
+ assert_equal [], user.previous_slugs
58
+ assert_none_for_slug "red"
59
+ assert_none_for_slug "sal"
60
+ assert_none_for_slug "bob"
61
+ end
62
+
63
+ should 'let you disable recording of slug history' do
64
+ setup_slugs! :history => false
65
+ user = User.create(:name => "Bob")
66
+ assert !user.respond_to?(:previous_slugs)
67
+ user.update_attributes! :name => "Red"
68
+ assert_same_as_slug user, "red"
69
+ assert_different_to_slug user, "bob"
70
+ assert_none_for_slug "bob"
71
+ end
72
+
73
+ should 'remove slug history for a record by default on destroy' do
74
+ setup_slugs!
75
+ user = User.create :name => "Bob"
76
+ user.update_attributes! :name => "Sal"
77
+ user.update_attributes! :name => "Red"
78
+ user.update_attributes! :name => "Jim"
79
+ assert_equal ["red", "sal", "bob"], user.previous_slugs
80
+ user.destroy
81
+ assert_equal [], user.previous_slugs
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,27 @@
1
+ require 'helper'
2
+
3
+ class SluggedTest < Test::Unit::TestCase
4
+
5
+ class SlugScopeTest
6
+ cattr_accessor :slug_scope_key
7
+ self.slug_scope_key = "my-test-scope"
8
+ end
9
+
10
+ should 'return the correct counter versions' do
11
+ assert_equal 'awesome', Slugged.with_counter('awesome')
12
+ assert_equal 'awesome', Slugged.with_counter('awesome', 0)
13
+ assert_equal 'awesome', Slugged.with_counter('awesome', -1)
14
+ assert_equal 'awesome--2', Slugged.with_counter('awesome', 2)
15
+ assert_equal 'awesome--100', Slugged.with_counter('awesome', 100)
16
+ end
17
+
18
+ should 'correct allow you to slug scope keys' do
19
+ assert_equal "my-test-scope", Slugged.key_for_scope(SlugScopeTest)
20
+ assert_equal "my-test-scope", Slugged.key_for_scope(SlugScopeTest.new)
21
+ assert_equal "my-test-scope", Slugged.key_for_scope("my-test-scope")
22
+ assert_equal "", Slugged.key_for_scope(nil)
23
+ assert_equal "1", Slugged.key_for_scope(1)
24
+ assert_equal "awesome", Slugged.key_for_scope(:awesome)
25
+ end
26
+
27
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slugged
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 2
10
+ version: 0.3.2
11
+ platform: ruby
12
+ authors:
13
+ - Darcy Laycock
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-30 00:00:00 +08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :runtime
24
+ name: activerecord
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 7
31
+ segments:
32
+ - 3
33
+ - 0
34
+ - 0
35
+ version: 3.0.0
36
+ requirement: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ prerelease: false
39
+ type: :runtime
40
+ name: activesupport
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 7
47
+ segments:
48
+ - 3
49
+ - 0
50
+ - 0
51
+ version: 3.0.0
52
+ requirement: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ prerelease: false
55
+ type: :runtime
56
+ name: uuid
57
+ version_requirements: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirement: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ prerelease: false
69
+ type: :development
70
+ name: shoulda
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirement: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ prerelease: false
83
+ type: :development
84
+ name: reversible_data
85
+ version_requirements: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirement: *id005
95
+ description: Super simple slugs for ActiveRecord 3.0 and higher, with support for slug history
96
+ email: sutto@sutto.net
97
+ executables: []
98
+
99
+ extensions: []
100
+
101
+ extra_rdoc_files:
102
+ - LICENSE
103
+ - README.md
104
+ files:
105
+ - .document
106
+ - .gitignore
107
+ - .rvmrc
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - lib/generators/slugged/slug_migration/slug_migration_generator.rb
114
+ - lib/generators/slugged/slug_migration/templates/migration.erb
115
+ - lib/generators/slugged/slugs/slugs_generator.rb
116
+ - lib/generators/slugged/slugs/templates/migration.erb
117
+ - lib/slugged.rb
118
+ - lib/slugged/active_record_methods.rb
119
+ - lib/slugged/caching.rb
120
+ - lib/slugged/finders.rb
121
+ - lib/slugged/memory_cache.rb
122
+ - lib/slugged/railtie.rb
123
+ - lib/slugged/scopes.rb
124
+ - lib/slugged/slug.rb
125
+ - lib/slugged/slug_history.rb
126
+ - lib/slugged/version.rb
127
+ - metrics/.gitignore
128
+ - test/caching_test.rb
129
+ - test/helper.rb
130
+ - test/is_sluggable_test.rb
131
+ - test/model_definitions.rb
132
+ - test/slug_history_test.rb
133
+ - test/slugged_test.rb
134
+ has_rdoc: true
135
+ homepage: http://github.com/Sutto/slugged
136
+ licenses: []
137
+
138
+ post_install_message:
139
+ rdoc_options:
140
+ - --charset=UTF-8
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
151
+ version: "0"
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ hash: 3
158
+ segments:
159
+ - 0
160
+ version: "0"
161
+ requirements: []
162
+
163
+ rubyforge_project:
164
+ rubygems_version: 1.3.7
165
+ signing_key:
166
+ specification_version: 3
167
+ summary: Super simple slugs for ActiveRecord 3.0 and higher, with support for slug history
168
+ test_files:
169
+ - test/caching_test.rb
170
+ - test/helper.rb
171
+ - test/is_sluggable_test.rb
172
+ - test/model_definitions.rb
173
+ - test/slug_history_test.rb
174
+ - test/slugged_test.rb