friendly_id 2.2.7 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/Changelog.md +225 -0
  2. data/Contributors.md +28 -0
  3. data/Guide.md +509 -0
  4. data/LICENSE +1 -1
  5. data/README.md +76 -0
  6. data/Rakefile +48 -15
  7. data/extras/bench.rb +59 -0
  8. data/extras/extras.rb +31 -0
  9. data/extras/prof.rb +14 -0
  10. data/extras/template-gem.rb +1 -1
  11. data/extras/template-plugin.rb +1 -1
  12. data/generators/friendly_id/friendly_id_generator.rb +1 -1
  13. data/generators/friendly_id/templates/create_slugs.rb +2 -2
  14. data/lib/friendly_id.rb +54 -63
  15. data/lib/friendly_id/active_record2.rb +47 -0
  16. data/lib/friendly_id/active_record2/configuration.rb +66 -0
  17. data/lib/friendly_id/active_record2/finders.rb +140 -0
  18. data/lib/friendly_id/active_record2/simple_model.rb +162 -0
  19. data/lib/friendly_id/active_record2/slug.rb +111 -0
  20. data/lib/friendly_id/active_record2/slugged_model.rb +317 -0
  21. data/lib/friendly_id/active_record2/tasks.rb +66 -0
  22. data/lib/friendly_id/active_record2/tasks/friendly_id.rake +19 -0
  23. data/lib/friendly_id/configuration.rb +132 -0
  24. data/lib/friendly_id/finders.rb +106 -0
  25. data/lib/friendly_id/slug_string.rb +292 -0
  26. data/lib/friendly_id/slugged.rb +91 -0
  27. data/lib/friendly_id/status.rb +35 -0
  28. data/lib/friendly_id/test.rb +168 -0
  29. data/lib/friendly_id/version.rb +5 -5
  30. data/rails/init.rb +2 -0
  31. data/test/active_record2/basic_slugged_model_test.rb +14 -0
  32. data/test/active_record2/cached_slug_test.rb +61 -0
  33. data/test/active_record2/core.rb +93 -0
  34. data/test/active_record2/custom_normalizer_test.rb +20 -0
  35. data/test/active_record2/custom_table_name_test.rb +22 -0
  36. data/test/active_record2/scoped_model_test.rb +111 -0
  37. data/test/active_record2/simple_test.rb +59 -0
  38. data/test/active_record2/slug_test.rb +34 -0
  39. data/test/active_record2/slugged.rb +30 -0
  40. data/test/active_record2/slugged_status_test.rb +61 -0
  41. data/test/active_record2/sti_test.rb +22 -0
  42. data/test/active_record2/support/database.mysql.yml +4 -0
  43. data/test/{support/database.yml.postgres → active_record2/support/database.postgres.yml} +0 -0
  44. data/test/{support/database.yml.sqlite3 → active_record2/support/database.sqlite3.yml} +0 -0
  45. data/test/{support → active_record2/support}/models.rb +28 -0
  46. data/test/active_record2/tasks_test.rb +82 -0
  47. data/test/active_record2/test_helper.rb +107 -0
  48. data/test/friendly_id_test.rb +23 -0
  49. data/test/slug_string_test.rb +74 -0
  50. data/test/test_helper.rb +7 -102
  51. metadata +64 -56
  52. data/History.txt +0 -194
  53. data/README.rdoc +0 -385
  54. data/generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb +0 -12
  55. data/generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb +0 -19
  56. data/init.rb +0 -1
  57. data/lib/friendly_id/helpers.rb +0 -12
  58. data/lib/friendly_id/non_sluggable_class_methods.rb +0 -34
  59. data/lib/friendly_id/non_sluggable_instance_methods.rb +0 -45
  60. data/lib/friendly_id/slug.rb +0 -98
  61. data/lib/friendly_id/sluggable_class_methods.rb +0 -110
  62. data/lib/friendly_id/sluggable_instance_methods.rb +0 -161
  63. data/lib/friendly_id/tasks.rb +0 -56
  64. data/lib/tasks/friendly_id.rake +0 -25
  65. data/lib/tasks/friendly_id.rb +0 -1
  66. data/test/cached_slug_test.rb +0 -109
  67. data/test/custom_slug_normalizer_test.rb +0 -36
  68. data/test/non_slugged_test.rb +0 -99
  69. data/test/scoped_model_test.rb +0 -64
  70. data/test/slug_test.rb +0 -105
  71. data/test/slugged_model_test.rb +0 -348
  72. data/test/sti_test.rb +0 -49
  73. data/test/tasks_test.rb +0 -105
@@ -1,25 +0,0 @@
1
- namespace :friendly_id do
2
- desc "Make slugs for a model."
3
- task :make_slugs => :environment do
4
- validate_model_given
5
- FriendlyId::Tasks.make_slugs(ENV["MODEL"]) do |r|
6
- puts "%s(%d) friendly_id set to '%s'" % [r.class.to_s, r.id, r.slug.name]
7
- end
8
- end
9
-
10
- desc "Regenereate slugs for a model."
11
- task :redo_slugs => :environment do
12
- validate_model_given
13
- FriendlyId::Tasks.delete_slugs_for(ENV["MODEL"])
14
- Rake::Task["friendly_id:make_slugs"].invoke
15
- end
16
-
17
- desc "Kill obsolete slugs older than DAYS=45 days."
18
- task :remove_old_slugs => :environment do
19
- FriendlyId::Tasks.delete_old_slugs(ENV["DAYS"], ENV["MODEL"])
20
- end
21
- end
22
-
23
- def validate_model_given
24
- raise 'USAGE: rake friendly_id:make_slugs MODEL=MyModelName' if ENV["MODEL"].nil?
25
- end
@@ -1 +0,0 @@
1
- load 'tasks/friendly_id.rake'
@@ -1,109 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class CachedSlugModelTest < Test::Unit::TestCase
4
-
5
- context "A slugged model with a cached_slugs column" do
6
-
7
- setup do
8
- @paris = City.new(:name => "Paris")
9
- @paris.save!
10
- end
11
-
12
- teardown do
13
- City.delete_all
14
- Slug.delete_all
15
- end
16
-
17
- should "have a slug" do
18
- assert_not_nil @paris.slug
19
- end
20
-
21
- should "have a cached slug" do
22
- assert_not_nil @paris.my_slug
23
- end
24
-
25
- should "have a to_param method that returns the cached slug" do
26
- assert_equal "paris", @paris.to_param
27
- end
28
-
29
- should "protect the cached slug value" do
30
- @paris.update_attributes(:my_slug => "Madrid")
31
- @paris.reload
32
- assert_equal "paris", @paris.my_slug
33
- end
34
-
35
- should "cache the incremented sequence for duplicate slug names" do
36
- paris2 = City.create!(:name => "Paris")
37
- assert_equal 2, paris2.slug.sequence
38
- assert_equal "paris--2", paris2.my_slug
39
- end
40
-
41
- should "not update the cached slug column if it has not changed" do
42
- @paris.population = 10_000_000
43
- @paris.expects(:my_slug=).never
44
- @paris.save
45
- end
46
-
47
-
48
- context "found by its friendly id" do
49
-
50
- setup do
51
- @paris = City.find(@paris.friendly_id)
52
- end
53
-
54
- should "not indicate that it has a better id" do
55
- assert !@paris.has_better_id?
56
- end
57
-
58
- end
59
-
60
- context "found by its numeric id" do
61
-
62
- setup do
63
- @paris = City.find(@paris.id)
64
- end
65
-
66
- should "indicate that it has a better id" do
67
- assert @paris.has_better_id?
68
- end
69
-
70
- end
71
-
72
-
73
- context "with a new slug" do
74
-
75
- setup do
76
- @paris.name = "Paris, France"
77
- @paris.save!
78
- @paris.reload
79
- end
80
-
81
- should "have its cached slug updated" do
82
- assert_equal "paris-france", @paris.my_slug
83
- end
84
-
85
- should "have its cached slug synchronized with its friendly_id" do
86
- assert_equal @paris.my_slug, @paris.friendly_id
87
- end
88
-
89
- end
90
-
91
-
92
- context "with a cached_slug column" do
93
-
94
- setup do
95
- District.delete_all
96
- @district = District.new(:name => "Latin Quarter")
97
- @district.save!
98
- end
99
-
100
- should "have its cached_slug filled automatically" do
101
- assert_equal @district.cached_slug, "latin-quarter"
102
- end
103
-
104
- end
105
-
106
- end
107
-
108
- end
109
-
@@ -1,36 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class CustomSlugNormalizerTest < Test::Unit::TestCase
4
-
5
- context "A slugged model using a custom slug generator" do
6
-
7
- setup do
8
- Person.friendly_id_options = FriendlyId::DEFAULT_OPTIONS.merge(:method => :name, :use_slug => true)
9
- end
10
-
11
- teardown do
12
- Person.delete_all
13
- Slug.delete_all
14
- end
15
-
16
- should "invoke the block code" do
17
- @person = Person.create!(:name => "Joe Schmoe")
18
- assert_equal "JOE SCHMOE", @person.friendly_id
19
- end
20
-
21
- should "respect the max_length option" do
22
- Person.friendly_id_options = Person.friendly_id_options.merge(:max_length => 3)
23
- @person = Person.create!(:name => "Joe Schmoe")
24
- assert_equal "JOE", @person.friendly_id
25
- end
26
-
27
- should "respect the reserved option" do
28
- Person.friendly_id_options = Person.friendly_id_options.merge(:reserved => ["JOE"])
29
- assert_raises FriendlyId::SlugGenerationError do
30
- Person.create!(:name => "Joe")
31
- end
32
- end
33
-
34
- end
35
-
36
- end
@@ -1,99 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class NonSluggedTest < Test::Unit::TestCase
4
-
5
- context "A non-slugged model with default FriendlyId options" do
6
-
7
- setup do
8
- @user = User.create!(:name => "joe")
9
- end
10
-
11
- teardown do
12
- User.delete_all
13
- end
14
-
15
- should "have friendly_id options" do
16
- assert_not_nil User.friendly_id_options
17
- end
18
-
19
- should "not have a slug" do
20
- assert !@user.respond_to?(:slug)
21
- end
22
-
23
- should "be findable by its friendly_id" do
24
- assert User.find(@user.friendly_id)
25
- end
26
-
27
- should "be findable by its regular id" do
28
- assert User.find(@user.id)
29
- end
30
-
31
- should "respect finder conditions" do
32
- assert_raises ActiveRecord::RecordNotFound do
33
- User.find(@user.friendly_id, :conditions => "1 = 2")
34
- end
35
- end
36
-
37
- should "indicate if it was found by its friendly id" do
38
- user = User.find(@user.friendly_id)
39
- assert user.found_using_friendly_id?
40
- end
41
-
42
- should "indicate if it was found by its numeric id" do
43
- user = User.find(@user.id)
44
- assert user.found_using_numeric_id?
45
- end
46
-
47
- should "indicate if it has a better id" do
48
- user = User.find(@user.id)
49
- assert user.has_better_id?
50
- end
51
-
52
- should "not validate if the friendly_id text is reserved" do
53
- user = User.new(:name => "new")
54
- assert !user.valid?
55
- end
56
-
57
- should "have always string for a friendly_id" do
58
- assert_equal String, @user.to_param.class
59
- end
60
-
61
- should "return its id if the friendly_id is null" do
62
- @user.name = nil
63
- assert_equal @user.id.to_s, @user.to_param
64
- end
65
-
66
-
67
- context "when using an array as the find argument" do
68
-
69
- setup do
70
- @user2 = User.create(:name => "jane")
71
- end
72
-
73
- should "return results" do
74
- assert_equal 2, User.find([@user.friendly_id, @user2.friendly_id]).size
75
- end
76
-
77
- should "not allow mixed friendly and non-friendly ids for the same record" do
78
- assert_raises ActiveRecord::RecordNotFound do
79
- User.find([@user.id, @user.friendly_id]).size
80
- end
81
- end
82
-
83
- should "raise an error when all records are not found" do
84
- assert_raises ActiveRecord::RecordNotFound do
85
- User.find(['bad', 'bad2'])
86
- end
87
- end
88
-
89
- should "indicate if the results were found using a friendly_id" do
90
- users = User.find([@user.id, @user2.friendly_id], :order => "name ASC")
91
- assert users[0].found_using_friendly_id?
92
- assert users[1].found_using_numeric_id?
93
- end
94
-
95
- end
96
-
97
- end
98
-
99
- end
@@ -1,64 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
-
4
- class ScopedModelTest < Test::Unit::TestCase
5
-
6
- context "A slugged model that uses a scope" do
7
-
8
- setup do
9
- @usa = Country.create!(:name => "USA")
10
- @canada = Country.create!(:name => "Canada")
11
- @resident = Resident.create!(:name => "John Smith", :country => @usa)
12
- @resident2 = Resident.create!(:name => "John Smith", :country => @canada)
13
- end
14
-
15
- teardown do
16
- Resident.delete_all
17
- Country.delete_all
18
- Slug.delete_all
19
- end
20
-
21
- should "should not show the scope in the friendly_id" do
22
- assert_equal "john-smith", @resident.friendly_id
23
- assert_equal "john-smith", @resident2.friendly_id
24
- end
25
-
26
- should "find all scoped records without scope" do
27
- assert_equal 2, Resident.find(:all, @resident.friendly_id).size
28
- end
29
-
30
- should "find a single scoped records with a scope as a string" do
31
- assert Resident.find(@resident.friendly_id, :scope => @resident.country.to_param)
32
- end
33
-
34
- should "find a single scoped records with a scope" do
35
- assert Resident.find(@resident.friendly_id, :scope => @resident.country)
36
- end
37
-
38
- should "raise an error when finding a single scoped record with no scope" do
39
- assert_raises ActiveRecord::RecordNotFound do
40
- Resident.find(@resident.friendly_id)
41
- end
42
- end
43
-
44
- should "append scope error info when missing scope causes a find to fail" do
45
- begin
46
- Resident.find(@resident.friendly_id)
47
- fail "The find should not have succeeded"
48
- rescue ActiveRecord::RecordNotFound => e
49
- assert_match /expected scope/, e.message
50
- end
51
- end
52
-
53
- should "append scope error info when the scope value causes a find to fail" do
54
- begin
55
- Resident.find(@resident.friendly_id, :scope => "badscope")
56
- fail "The find should not have succeeded"
57
- rescue ActiveRecord::RecordNotFound => e
58
- assert_match /scope=badscope/, e.message
59
- end
60
- end
61
-
62
- end
63
-
64
- end
data/test/slug_test.rb DELETED
@@ -1,105 +0,0 @@
1
- # encoding: utf-8
2
- require File.dirname(__FILE__) + '/test_helper'
3
-
4
- class SlugTest < Test::Unit::TestCase
5
-
6
- context "a slug" do
7
-
8
- teardown do
9
- Slug.delete_all
10
- Post.delete_all
11
- end
12
-
13
- should "indicate if it is the most recent slug" do
14
- post = Post.create!(:name => "test title")
15
- post.name = "a new title"
16
- post.save!
17
- assert post.slugs.last.is_most_recent?
18
- assert !post.slugs.first.is_most_recent?
19
- end
20
-
21
- end
22
-
23
- context "the Slug class" do
24
-
25
- should "parse the slug name and sequence" do
26
- assert_equal ["test", "2"], Slug::parse("test--2")
27
- end
28
-
29
- should "parse with a default sequence of 1" do
30
- assert_equal ["test", "1"], Slug::parse("test")
31
- end
32
-
33
- should "should strip diacritics" do
34
- assert_equal "acai", Slug::strip_diacritics("açaí")
35
- end
36
-
37
- should "strip diacritics correctly " do
38
- input = "ÀÁÂÃÄÅÆÇÈÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"
39
- output = Slug::strip_diacritics(input).split(//)
40
- expected = "AAAAAAAECEEEIIIIDNOOOOOOUUUUYThssaaaaaaaeceeeeiiiidnoooooouuuuythy".split(//)
41
- output.each_index do |i|
42
- assert_equal expected[i], output[i]
43
- end
44
- end
45
-
46
- end
47
-
48
- context "the Slug class's to_friendly_id method" do
49
-
50
- should "include the sequence if the sequence is greater than 1" do
51
- slug = Slug.new(:name => "test", :sequence => 2)
52
- assert_equal "test--2", slug.to_friendly_id
53
- end
54
-
55
- should "not include the sequence if the sequence is 1" do
56
- slug = Slug.new(:name => "test", :sequence => 1)
57
- assert_equal "test", slug.to_friendly_id
58
- end
59
-
60
- end
61
-
62
- context "the Slug class's normalize method" do
63
-
64
- should "should lowercase strings" do
65
- assert_match /abc/, Slug::normalize("ABC")
66
- end
67
-
68
- should "should replace whitespace with dashes" do
69
- assert_match /a-b/, Slug::normalize("a b")
70
- end
71
-
72
- should "should replace 2spaces with 1dash" do
73
- assert_match /a-b/, Slug::normalize("a b")
74
- end
75
-
76
- should "should remove punctuation" do
77
- assert_match /abc/, Slug::normalize('abc!@#$%^&*•¶§∞¢££¡¿()><?"":;][]\.,/')
78
- end
79
-
80
- should "should strip trailing space" do
81
- assert_match /ab/, Slug::normalize("ab ")
82
- end
83
-
84
- should "should strip leading space" do
85
- assert_match /ab/, Slug::normalize(" ab")
86
- end
87
-
88
- should "should strip trailing slashes" do
89
- assert_match /ab/, Slug::normalize("ab-")
90
- end
91
-
92
- should "should strip leading slashes" do
93
- assert_match /ab/, Slug::normalize("-ab")
94
- end
95
-
96
- should "should not modify valid name strings" do
97
- assert_match /a-b-c-d/, Slug::normalize("a-b-c-d")
98
- end
99
-
100
- should "work with non roman chars" do
101
- assert_equal "検-索", Slug::normalize("検 索")
102
- end
103
-
104
- end
105
- end