dougcole-friendly_id 2.0.5 → 2.0.6
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/History.txt +20 -0
- data/Manifest.txt +10 -18
- data/README.rdoc +34 -5
- data/Rakefile +8 -0
- data/VERSION.yml +1 -1
- data/lib/friendly_id.rb +33 -13
- data/lib/friendly_id/non_sluggable_class_methods.rb +3 -3
- data/lib/friendly_id/non_sluggable_instance_methods.rb +9 -1
- data/lib/friendly_id/slug.rb +14 -12
- data/lib/friendly_id/sluggable_class_methods.rb +14 -3
- data/lib/friendly_id/sluggable_instance_methods.rb +11 -4
- data/lib/friendly_id/version.rb +1 -1
- data/test/custom_slug_normalizer_test.rb +35 -0
- data/test/models/book.rb +2 -0
- data/test/{fixtures → models}/country.rb +0 -0
- data/test/models/novel.rb +3 -0
- data/test/{fixtures → models}/person.rb +0 -0
- data/test/models/post.rb +3 -0
- data/test/models/thing.rb +6 -0
- data/test/{fixtures → models}/user.rb +0 -0
- data/test/non_slugged_test.rb +71 -60
- data/test/schema.rb +29 -20
- data/test/scoped_model_test.rb +43 -13
- data/test/slug_test.rb +93 -74
- data/test/slugged_model_test.rb +263 -0
- data/test/sti_test.rb +48 -0
- data/test/test_helper.rb +30 -29
- metadata +15 -20
- data/lib/friendly_id/shoulda_macros.rb +0 -36
- data/test/database.yml +0 -3
- data/test/fixtures/countries.yml +0 -4
- data/test/fixtures/people.yml +0 -7
- data/test/fixtures/post.rb +0 -3
- data/test/fixtures/posts.yml +0 -23
- data/test/fixtures/slugs.yml +0 -53
- data/test/fixtures/users.yml +0 -7
- data/test/rails/2.x/app/controllers/application.rb +0 -0
- data/test/rails/2.x/config/boot.rb +0 -109
- data/test/rails/2.x/config/database.yml +0 -3
- data/test/rails/2.x/config/environment.rb +0 -7
- data/test/rails/2.x/config/environments/test.rb +0 -6
- data/test/rails/2.x/config/routes.rb +0 -0
- data/test/sluggable_test.rb +0 -185
@@ -1,36 +0,0 @@
|
|
1
|
-
module FriendlyId
|
2
|
-
|
3
|
-
# A Shoulda[http://www.thoughtbot.com/projects/shoulda/] macros for testing
|
4
|
-
# models using FriendlyId.
|
5
|
-
module ShouldaMacros
|
6
|
-
|
7
|
-
# Ensure that a model is using FriendlyId.
|
8
|
-
def self.should_have_friendly_id(column, options = {})
|
9
|
-
|
10
|
-
options.assert_valid_keys(:use_slug)
|
11
|
-
klass = self.model_class
|
12
|
-
|
13
|
-
should "have friendly id for #{method}" do
|
14
|
-
assert_respond_to klass, :friendly_id_options,
|
15
|
-
"#{klass} does not respond to friendly_id_options"
|
16
|
-
assert_equal column, klass.friendly_id_options[:method]
|
17
|
-
end
|
18
|
-
|
19
|
-
if options[:use_slug]
|
20
|
-
should "include/extend friendly_id's sluggable modules" do
|
21
|
-
assert klass.extended_by.include?(FriendlyId::SluggableClassMethods),
|
22
|
-
"#{klass} does not extend FriendlyId::SluggableClassMethods"
|
23
|
-
assert klass.include?(FriendlyId::SluggableInstanceMethods),
|
24
|
-
"#{klass} not include FriendlyId::SluggableInstanceMethods"
|
25
|
-
end
|
26
|
-
else
|
27
|
-
should "include/extend friendly_id's non-sluggable modules" do
|
28
|
-
assert klass.extended_by.include?(FriendlyId::NonSluggableClassMethods),
|
29
|
-
"#{klass} does not extend FriendlyId::NonSluggableClassMethods"
|
30
|
-
assert klass.include?(FriendlyId::NonSluggableInstanceMethods),
|
31
|
-
"#{klass} not include FriendlyId::NonSluggableInstanceMethods"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/test/database.yml
DELETED
data/test/fixtures/countries.yml
DELETED
data/test/fixtures/people.yml
DELETED
data/test/fixtures/post.rb
DELETED
data/test/fixtures/posts.yml
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
without_slug:
|
2
|
-
name: Without a slug
|
3
|
-
content: Content without a slug
|
4
|
-
|
5
|
-
with_one_slug:
|
6
|
-
name: With one slug
|
7
|
-
content: Content with one slug
|
8
|
-
|
9
|
-
with_two_slugs:
|
10
|
-
name: With two slugs
|
11
|
-
content: Content with two slugs
|
12
|
-
|
13
|
-
common_title:
|
14
|
-
name: Common Title
|
15
|
-
content: A post with a very common title
|
16
|
-
|
17
|
-
common_title2:
|
18
|
-
name: Common Title
|
19
|
-
content: A second post with a very common title
|
20
|
-
|
21
|
-
john_smith:
|
22
|
-
name: John Smith
|
23
|
-
content: Should allow for identical slug names between sluggable types
|
data/test/fixtures/slugs.yml
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
post_with_same_friendly_id_as_person:
|
2
|
-
name: john-smith
|
3
|
-
sluggable: john_smith (Post)
|
4
|
-
|
5
|
-
person_with_same_friendly_id_as_post:
|
6
|
-
name: john-smith
|
7
|
-
sluggable: john_smith (Person)
|
8
|
-
|
9
|
-
one:
|
10
|
-
name: with-one-slug
|
11
|
-
sluggable: with_one_slug
|
12
|
-
sluggable_type: Post
|
13
|
-
sequence: 1
|
14
|
-
|
15
|
-
two_old:
|
16
|
-
name: with-two-slugs
|
17
|
-
sluggable: with_two_slugs (Post)
|
18
|
-
sequence: 1
|
19
|
-
|
20
|
-
two_new:
|
21
|
-
name: with-two-slugs-new
|
22
|
-
sluggable: with_two_slugs (Post)
|
23
|
-
sequence: 1
|
24
|
-
|
25
|
-
common_title:
|
26
|
-
name: common-title
|
27
|
-
sluggable: common_title (Post)
|
28
|
-
sequence: 1
|
29
|
-
|
30
|
-
common_title2:
|
31
|
-
name: common-title
|
32
|
-
sluggable: common_title2 (Post)
|
33
|
-
sequence: 2
|
34
|
-
|
35
|
-
john_smith:
|
36
|
-
name: john-smith
|
37
|
-
sluggable: john_smith (Person)
|
38
|
-
sequence: 1
|
39
|
-
scope: argentina
|
40
|
-
|
41
|
-
john_smith2:
|
42
|
-
name: john-smith
|
43
|
-
sluggable: john_smith2 (Person)
|
44
|
-
sequence: 1
|
45
|
-
scope: usa
|
46
|
-
|
47
|
-
argentina:
|
48
|
-
name: argentina
|
49
|
-
sluggable: argentina (Country)
|
50
|
-
|
51
|
-
usa:
|
52
|
-
name: usa
|
53
|
-
sluggable: usa (Country)
|
data/test/fixtures/users.yml
DELETED
File without changes
|
@@ -1,109 +0,0 @@
|
|
1
|
-
# Don't change this file!
|
2
|
-
# Configure your app in config/environment.rb and config/environments/*.rb
|
3
|
-
|
4
|
-
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
5
|
-
|
6
|
-
module Rails
|
7
|
-
class << self
|
8
|
-
def boot!
|
9
|
-
unless booted?
|
10
|
-
preinitialize
|
11
|
-
pick_boot.run
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def booted?
|
16
|
-
defined? Rails::Initializer
|
17
|
-
end
|
18
|
-
|
19
|
-
def pick_boot
|
20
|
-
(vendor_rails? ? VendorBoot : GemBoot).new
|
21
|
-
end
|
22
|
-
|
23
|
-
def vendor_rails?
|
24
|
-
File.exist?("#{RAILS_ROOT}/vendor/rails")
|
25
|
-
end
|
26
|
-
|
27
|
-
def preinitialize
|
28
|
-
load(preinitializer_path) if File.exist?(preinitializer_path)
|
29
|
-
end
|
30
|
-
|
31
|
-
def preinitializer_path
|
32
|
-
"#{RAILS_ROOT}/config/preinitializer.rb"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class Boot
|
37
|
-
def run
|
38
|
-
load_initializer
|
39
|
-
Rails::Initializer.run(:set_load_path)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class VendorBoot < Boot
|
44
|
-
def load_initializer
|
45
|
-
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
|
46
|
-
Rails::Initializer.run(:install_gem_spec_stubs)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class GemBoot < Boot
|
51
|
-
def load_initializer
|
52
|
-
self.class.load_rubygems
|
53
|
-
load_rails_gem
|
54
|
-
require 'initializer'
|
55
|
-
end
|
56
|
-
|
57
|
-
def load_rails_gem
|
58
|
-
if version = self.class.gem_version
|
59
|
-
gem 'rails', version
|
60
|
-
else
|
61
|
-
gem 'rails'
|
62
|
-
end
|
63
|
-
rescue Gem::LoadError => load_error
|
64
|
-
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
65
|
-
exit 1
|
66
|
-
end
|
67
|
-
|
68
|
-
class << self
|
69
|
-
def rubygems_version
|
70
|
-
Gem::RubyGemsVersion rescue nil
|
71
|
-
end
|
72
|
-
|
73
|
-
def gem_version
|
74
|
-
if defined? RAILS_GEM_VERSION
|
75
|
-
RAILS_GEM_VERSION
|
76
|
-
elsif ENV.include?('RAILS_GEM_VERSION')
|
77
|
-
ENV['RAILS_GEM_VERSION']
|
78
|
-
else
|
79
|
-
parse_gem_version(read_environment_rb)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def load_rubygems
|
84
|
-
require 'rubygems'
|
85
|
-
min_version = '1.3.1'
|
86
|
-
unless rubygems_version >= min_version
|
87
|
-
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
88
|
-
exit 1
|
89
|
-
end
|
90
|
-
|
91
|
-
rescue LoadError
|
92
|
-
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
93
|
-
exit 1
|
94
|
-
end
|
95
|
-
|
96
|
-
def parse_gem_version(text)
|
97
|
-
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
98
|
-
end
|
99
|
-
|
100
|
-
private
|
101
|
-
def read_environment_rb
|
102
|
-
File.read("#{RAILS_ROOT}/config/environment.rb")
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# All that for this:
|
109
|
-
Rails.boot!
|
@@ -1,6 +0,0 @@
|
|
1
|
-
config.cache_classes = true
|
2
|
-
config.whiny_nils = true
|
3
|
-
config.action_controller.consider_all_requests_local = true
|
4
|
-
config.action_controller.perform_caching = false
|
5
|
-
config.action_controller.allow_forgery_protection = false
|
6
|
-
config.action_mailer.delivery_method = :test
|
File without changes
|
data/test/sluggable_test.rb
DELETED
@@ -1,185 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/test_helper'
|
2
|
-
|
3
|
-
class SluggableTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
fixtures :posts, :slugs
|
6
|
-
|
7
|
-
def setup
|
8
|
-
Post.friendly_id_options[:max_length] = FriendlyId::ClassMethods::DEFAULT_FRIENDLY_ID_OPTIONS[:max_length]
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_should_allow_for_identical_slug_names_between_sluggable_types
|
12
|
-
assert !Post.find(slugs(:post_with_same_friendly_id_as_person).name).has_better_id?
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_class_should_have_friendly_id_options
|
16
|
-
assert_not_nil Post.friendly_id_options
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_should_generate_slug_text
|
20
|
-
@post = Post.new(:name => "Test post", :content => "Test content")
|
21
|
-
assert_equal "test-post", @post.slug_text
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_should_save_slug_when_creating
|
25
|
-
@post = Post.create(:name => "Test post", :content => "Test content")
|
26
|
-
assert @post.slug
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_to_param_should_always_return_a_string
|
30
|
-
assert_equal String, posts(:without_slug).to_param.class
|
31
|
-
assert_equal String, posts(:with_one_slug).to_param.class
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_finder_options_are_not_ignored
|
35
|
-
assert_raises ActiveRecord::RecordNotFound do
|
36
|
-
Post.find(slugs(:one).name, :conditions => "1 = 2")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_should_still_be_able_to_find_record_by_id
|
41
|
-
post = Post.create!(:name => "New post")
|
42
|
-
Post.create!(:name => "#{post.id.to_s} and some text")
|
43
|
-
assert_equal post, Post.find(post.id)
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
def test_should_not_be_found_using_friendly_id_by_default
|
48
|
-
@post = Post.new
|
49
|
-
assert !@post.found_using_friendly_id?
|
50
|
-
assert @post.found_using_numeric_id?
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_should_be_using_friendly_id_when_find_arg_is_an_array
|
54
|
-
@posts = Post.find([posts(:with_one_slug).friendly_id, posts(:with_two_slugs).friendly_id])
|
55
|
-
assert @posts.all? { |post| post.found_using_friendly_id? }
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_raises_active_record_not_found_when_not_all_records_found
|
59
|
-
assert_raises(ActiveRecord::RecordNotFound) do
|
60
|
-
Post.find([posts(:with_one_slug).slug.name, 'non-existant-slug-record'])
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_should_indicate_if_it_was_found_using_numeric_id
|
65
|
-
@post = Post.find(posts(:with_two_slugs).id)
|
66
|
-
assert @post.found_using_numeric_id?
|
67
|
-
end
|
68
|
-
|
69
|
-
def test_post_should_indicate_if_it_was_found_using_friendly_id
|
70
|
-
@post = Post.find(posts(:with_two_slugs).slug.name)
|
71
|
-
assert @post.found_using_friendly_id?
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_post_should_indicate_if_it_was_found_using_outdated_friendly_id
|
75
|
-
@post = Post.find(posts(:with_two_slugs).slugs.last.name)
|
76
|
-
assert @post.found_using_outdated_friendly_id?
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_should_indicate_there_is_a_better_id_if_found_by_numeric_id
|
80
|
-
@post = Post.find(posts(:with_one_slug).id)
|
81
|
-
assert @post.has_better_id?
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_should_indicate_there_is_a_better_id_if_found_by_outdated_friendly_id
|
85
|
-
@post = Post.find(posts(:with_two_slugs).slugs.last.name)
|
86
|
-
assert @post.has_better_id?
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_slug_should_always_be_the_most_recent
|
90
|
-
@post = Post.find(posts(:with_two_slugs).slug.name)
|
91
|
-
assert !@post.has_better_id?
|
92
|
-
assert slugs(:two_new).name, @post.slug.name
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_should_strip_diactics_from_slug_if_configured_to_do_so
|
96
|
-
Post.friendly_id_options[:strip_diacritics] = true
|
97
|
-
@post = Post.new(:name => "¡FELIZ AÑO!")
|
98
|
-
# Happy anus to you too
|
99
|
-
assert_equal "feliz-ano", @post.slug_text
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_should_not_strip_diactics_from_slug_unless_configured_to_do_so
|
103
|
-
Post.friendly_id_options[:strip_diacritics] = false
|
104
|
-
@post = Post.new(:name => "¡FELIZ AÑO!")
|
105
|
-
assert_equal "feliz-año", @post.slug_text
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_should_not_make_new_slug_unless_friendly_id_method_has_changed
|
109
|
-
posts(:with_one_slug).content = "Edited content"
|
110
|
-
posts(:with_one_slug).save!
|
111
|
-
assert_equal 1, posts(:with_one_slug).slugs.size
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_post_should_make_new_slug_if_friendly_id_method_is_changed
|
115
|
-
posts(:with_one_slug).name = "Edited name"
|
116
|
-
posts(:with_one_slug).save!
|
117
|
-
assert_equal 2, posts(:with_one_slug).slugs.size
|
118
|
-
end
|
119
|
-
|
120
|
-
def test_should_increment_sequence_for_duplicate_slugs
|
121
|
-
@post = Post.create!(:name => slugs(:one).name, :content => "stuff")
|
122
|
-
assert_equal 2, @post.slug.sequence
|
123
|
-
end
|
124
|
-
|
125
|
-
def test_friendly_id_should_contain_sequence_unless_its_1
|
126
|
-
@post = Post.create!(:name => slugs(:one).name, :content => "stuff")
|
127
|
-
assert_equal "#{slugs(:one).name}--2", @post.friendly_id
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_should_truncate_slugs_longer_than_maxlength
|
131
|
-
Post.friendly_id_options[:max_length] = 10
|
132
|
-
@post = Post.new(:name => "x" * 11, :content => "Test content")
|
133
|
-
assert @post.slug_text.length <= Post.friendly_id_options[:max_length]
|
134
|
-
end
|
135
|
-
|
136
|
-
def test_should_ensure_truncated_slugs_that_collide_have_different_sequences
|
137
|
-
Post.friendly_id_options[:max_length] = 2
|
138
|
-
p = Post.create!(:name => "aaa")
|
139
|
-
q = Post.create!(:name => "aaab")
|
140
|
-
assert_not_equal p.friendly_id, q.friendly_id
|
141
|
-
assert_equal p.slug.name, q.slug.name
|
142
|
-
assert_not_equal p.slug.sequence, q.slug.sequence
|
143
|
-
end
|
144
|
-
|
145
|
-
def test_should_be_able_to_rename_back_to_old_friendly_id
|
146
|
-
p = Post.create!(:name => "value")
|
147
|
-
assert_equal "value", p.friendly_id
|
148
|
-
p.name = "different value"
|
149
|
-
p.save!
|
150
|
-
p.reload
|
151
|
-
assert_equal "different-value", p.friendly_id
|
152
|
-
p.name = "value"
|
153
|
-
assert p.save!
|
154
|
-
p.reload
|
155
|
-
assert_equal "value", p.friendly_id
|
156
|
-
end
|
157
|
-
|
158
|
-
def test_should_raise_error_if_friendly_id_is_blank
|
159
|
-
assert_raises(FriendlyId::SlugGenerationError) do
|
160
|
-
Post.create(:name => nil)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def test_should_raise_error_if_normalized_friendly_id_becomes_blank
|
165
|
-
assert_raises(FriendlyId::SlugGenerationError) do
|
166
|
-
post = Post.create!(:name => "-.-")
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def test_should_raise_error_if_slug_text_is_reserved
|
171
|
-
assert_raises(FriendlyId::SlugGenerationError) do
|
172
|
-
Post.create(:name => "new")
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def test_should_allow_eager_loading_of_slugs
|
177
|
-
assert_nothing_raised do
|
178
|
-
Post.find(slugs(:one).name, :include => :slugs)
|
179
|
-
end
|
180
|
-
assert_nothing_raised do
|
181
|
-
Post.find([slugs(:one).name, slugs(:two_new).name], :include => :slugs)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|