friendly_id4 4.0.0.beta4 → 4.0.0.beta5
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/.yardopts +4 -0
- data/README.md +21 -24
- data/Rakefile +1 -1
- data/friendly_id.gemspec +2 -2
- data/lib/friendly_id.rb +102 -8
- data/lib/friendly_id/base.rb +76 -8
- data/lib/friendly_id/configuration.rb +9 -27
- data/lib/friendly_id/finder_methods.rb +8 -0
- data/lib/friendly_id/history.rb +35 -0
- data/lib/friendly_id/migration.rb +1 -0
- data/lib/friendly_id/object_utils.rb +16 -6
- data/lib/friendly_id/reserved.rb +46 -0
- data/lib/friendly_id/scoped.rb +101 -19
- data/lib/friendly_id/slug.rb +3 -0
- data/lib/friendly_id/slug_sequencer.rb +3 -0
- data/lib/friendly_id/slugged.rb +180 -8
- data/lib/generators/friendly_id_generator.rb +3 -0
- data/test/base_test.rb +23 -0
- data/test/configuration_test.rb +6 -6
- data/test/core_test.rb +3 -11
- data/test/helper.rb +2 -2
- data/test/history_test.rb +9 -9
- data/test/object_utils_test.rb +3 -3
- data/test/reserved_test.rb +26 -0
- data/test/scoped_test.rb +8 -8
- data/test/shared.rb +15 -15
- data/test/slugged_test.rb +30 -20
- metadata +19 -18
- data/Guide.md +0 -363
- data/lib/friendly_id/version.rb +0 -9
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'rails/generators'
|
2
2
|
require 'rails/generators/migration'
|
3
3
|
|
4
|
+
# This generator adds a migration for the {FriendlyId::History
|
5
|
+
# FriendlyId::History} addon.
|
4
6
|
class FriendlyIdGenerator < Rails::Generators::Base
|
5
7
|
include Rails::Generators::Migration
|
6
8
|
|
7
9
|
source_root File.expand_path('../../friendly_id', __FILE__)
|
8
10
|
|
11
|
+
# Copies the migration template to db/migrate.
|
9
12
|
def copy_files(*args)
|
10
13
|
migration_template 'migration.rb', 'db/migrate/create_friendly_id_slugs.rb'
|
11
14
|
end
|
data/test/base_test.rb
CHANGED
@@ -28,4 +28,27 @@ class CoreTest < MiniTest::Unit::TestCase
|
|
28
28
|
assert_equal :bar, klass.friendly_id_config.slug_column
|
29
29
|
end
|
30
30
|
|
31
|
+
test "the block passed to friendly_id should be evaluated before arguments" do
|
32
|
+
klass = Class.new(ActiveRecord::Base) do
|
33
|
+
extend FriendlyId
|
34
|
+
friendly_id :foo do |config|
|
35
|
+
config.base = :bar
|
36
|
+
end
|
37
|
+
end
|
38
|
+
assert_equal :foo, klass.friendly_id_config.base
|
39
|
+
end
|
40
|
+
|
41
|
+
test "should allow defaults to be set via a block" do
|
42
|
+
begin
|
43
|
+
FriendlyId.defaults do |config|
|
44
|
+
config.base = :foo
|
45
|
+
end
|
46
|
+
klass = Class.new(ActiveRecord::Base) do
|
47
|
+
extend FriendlyId
|
48
|
+
end
|
49
|
+
assert_equal :foo, klass.friendly_id_config.base
|
50
|
+
ensure
|
51
|
+
FriendlyId.instance_variable_set :@defaults, nil
|
52
|
+
end
|
53
|
+
end
|
31
54
|
end
|
data/test/configuration_test.rb
CHANGED
@@ -5,22 +5,22 @@ class ConfigurationTest < MiniTest::Unit::TestCase
|
|
5
5
|
include FriendlyId::Test
|
6
6
|
|
7
7
|
def setup
|
8
|
-
@
|
8
|
+
@model_class = Class.new(ActiveRecord::Base)
|
9
9
|
end
|
10
10
|
|
11
|
-
test "should set
|
12
|
-
config = FriendlyId::Configuration.new @
|
13
|
-
assert_equal @
|
11
|
+
test "should set model class on initialization" do
|
12
|
+
config = FriendlyId::Configuration.new @model_class
|
13
|
+
assert_equal @model_class, config.model_class
|
14
14
|
end
|
15
15
|
|
16
16
|
test "should set options on initialization if present" do
|
17
|
-
config = FriendlyId::Configuration.new @
|
17
|
+
config = FriendlyId::Configuration.new @model_class, :base => "hello"
|
18
18
|
assert_equal "hello", config.base
|
19
19
|
end
|
20
20
|
|
21
21
|
test "should raise error if passed unrecognized option" do
|
22
22
|
assert_raises NoMethodError do
|
23
|
-
FriendlyId::Configuration.new @
|
23
|
+
FriendlyId::Configuration.new @model_class, :foo => "bar"
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
data/test/core_test.rb
CHANGED
@@ -12,7 +12,7 @@ class CoreTest < MiniTest::Unit::TestCase
|
|
12
12
|
include FriendlyId::Test
|
13
13
|
include FriendlyId::Test::Shared
|
14
14
|
|
15
|
-
def
|
15
|
+
def model_class
|
16
16
|
Author
|
17
17
|
end
|
18
18
|
|
@@ -21,18 +21,10 @@ class CoreTest < MiniTest::Unit::TestCase
|
|
21
21
|
end
|
22
22
|
|
23
23
|
test "model classes should have a friendly id config" do
|
24
|
-
assert
|
25
|
-
end
|
26
|
-
|
27
|
-
test "should reserve 'new' and 'edit' by default" do
|
28
|
-
["new", "edit"].each do |word|
|
29
|
-
transaction do
|
30
|
-
assert_raises(ActiveRecord::RecordInvalid) {klass.create! :name => word}
|
31
|
-
end
|
32
|
-
end
|
24
|
+
assert model_class.friendly_id(:name).friendly_id_config
|
33
25
|
end
|
34
26
|
|
35
27
|
test "instances should have a friendly id" do
|
36
|
-
with_instance_of(
|
28
|
+
with_instance_of(model_class) {|record| assert record.friendly_id}
|
37
29
|
end
|
38
30
|
end
|
data/test/helper.rb
CHANGED
@@ -37,9 +37,9 @@ module FriendlyId
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def with_instance_of(*args)
|
40
|
-
|
40
|
+
model_class = args.shift
|
41
41
|
args[0] ||= {:name => "a"}
|
42
|
-
transaction { yield
|
42
|
+
transaction { yield model_class.create!(*args) }
|
43
43
|
end
|
44
44
|
|
45
45
|
module Database
|
data/test/history_test.rb
CHANGED
@@ -10,16 +10,16 @@ class HistoryTest < MiniTest::Unit::TestCase
|
|
10
10
|
include FriendlyId::Test
|
11
11
|
include FriendlyId::Test::Shared
|
12
12
|
|
13
|
-
def
|
13
|
+
def model_class
|
14
14
|
Manual
|
15
15
|
end
|
16
16
|
|
17
17
|
test "should insert record in slugs table on create" do
|
18
|
-
with_instance_of(
|
18
|
+
with_instance_of(model_class) {|record| assert !record.friendly_id_slugs.empty?}
|
19
19
|
end
|
20
20
|
|
21
21
|
test "should not create new slug record if friendly_id is not changed" do
|
22
|
-
with_instance_of(
|
22
|
+
with_instance_of(model_class) do |record|
|
23
23
|
record.active = true
|
24
24
|
record.save!
|
25
25
|
assert_equal 1, FriendlyIdSlug.count
|
@@ -27,7 +27,7 @@ class HistoryTest < MiniTest::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
test "should create new slug record when friendly_id changes" do
|
30
|
-
with_instance_of(
|
30
|
+
with_instance_of(model_class) do |record|
|
31
31
|
record.name = record.name + "b"
|
32
32
|
record.save!
|
33
33
|
assert_equal 2, FriendlyIdSlug.count
|
@@ -35,20 +35,20 @@ class HistoryTest < MiniTest::Unit::TestCase
|
|
35
35
|
end
|
36
36
|
|
37
37
|
test "should be findable by old slugs" do
|
38
|
-
with_instance_of(
|
38
|
+
with_instance_of(model_class) do |record|
|
39
39
|
old_friendly_id = record.friendly_id
|
40
40
|
record.name = record.name + "b"
|
41
41
|
record.save!
|
42
|
-
assert found =
|
42
|
+
assert found = model_class.find_by_friendly_id(old_friendly_id)
|
43
43
|
assert !found.readonly?
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
test "should raise error if used with scoped" do
|
48
|
-
|
49
|
-
|
48
|
+
model_class = Class.new(ActiveRecord::Base)
|
49
|
+
model_class.extend FriendlyId
|
50
50
|
assert_raises RuntimeError do
|
51
|
-
|
51
|
+
model_class.friendly_id :name, :use => [:history, :scoped]
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
data/test/object_utils_test.rb
CHANGED
@@ -19,8 +19,8 @@ class ObjectUtilsTest < MiniTest::Unit::TestCase
|
|
19
19
|
end
|
20
20
|
|
21
21
|
test "ActiveRecord::Base instances should be unfriendly_ids" do
|
22
|
-
|
23
|
-
|
24
|
-
assert
|
22
|
+
model_class = Class.new(ActiveRecord::Base)
|
23
|
+
model_class.table_name = "authors"
|
24
|
+
assert model_class.new.unfriendly_id?
|
25
25
|
end
|
26
26
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
class ReservedTest < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
include FriendlyId::Test
|
6
|
+
|
7
|
+
class Journalist < ActiveRecord::Base
|
8
|
+
extend FriendlyId
|
9
|
+
friendly_id :name
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def model_class
|
14
|
+
Journalist
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should reserve 'new' and 'edit' by default" do
|
18
|
+
["new", "edit"].each do |word|
|
19
|
+
transaction do
|
20
|
+
assert_raises(ActiveRecord::RecordInvalid) {model_class.create! :name => word}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
data/test/scoped_test.rb
CHANGED
@@ -16,7 +16,7 @@ class ScopedTest < MiniTest::Unit::TestCase
|
|
16
16
|
include FriendlyId::Test
|
17
17
|
include FriendlyId::Test::Shared
|
18
18
|
|
19
|
-
def
|
19
|
+
def model_class
|
20
20
|
Novel
|
21
21
|
end
|
22
22
|
|
@@ -25,10 +25,10 @@ class ScopedTest < MiniTest::Unit::TestCase
|
|
25
25
|
end
|
26
26
|
|
27
27
|
test "should detect scope column from explicit column name" do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
assert_equal "dummy",
|
28
|
+
model_class = Class.new(ActiveRecord::Base)
|
29
|
+
model_class.extend FriendlyId
|
30
|
+
model_class.friendly_id :empty, :use => :scoped, :scope => :dummy
|
31
|
+
assert_equal "dummy", model_class.friendly_id_config.scope_column
|
32
32
|
end
|
33
33
|
|
34
34
|
test "should allow duplicate slugs outside scope" do
|
@@ -48,10 +48,10 @@ class ScopedTest < MiniTest::Unit::TestCase
|
|
48
48
|
end
|
49
49
|
|
50
50
|
test "should raise error if used with history" do
|
51
|
-
|
52
|
-
|
51
|
+
model_class = Class.new(ActiveRecord::Base)
|
52
|
+
model_class.extend FriendlyId
|
53
53
|
assert_raises RuntimeError do
|
54
|
-
|
54
|
+
model_class.friendly_id :name, :use => [:scoped, :history]
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
data/test/shared.rb
CHANGED
@@ -3,69 +3,69 @@ module FriendlyId
|
|
3
3
|
module Shared
|
4
4
|
|
5
5
|
test "finds should respect conditions" do
|
6
|
-
with_instance_of(
|
6
|
+
with_instance_of(model_class) do |record|
|
7
7
|
assert_raises(ActiveRecord::RecordNotFound) do
|
8
|
-
|
8
|
+
model_class.where("1 = 2").find record.friendly_id
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
test "should be findable by friendly id" do
|
14
|
-
with_instance_of(
|
14
|
+
with_instance_of(model_class) {|record| assert model_class.find record.friendly_id}
|
15
15
|
end
|
16
16
|
|
17
17
|
test "should be findable by id as integer" do
|
18
|
-
with_instance_of(
|
18
|
+
with_instance_of(model_class) {|record| assert model_class.find record.id.to_i}
|
19
19
|
end
|
20
20
|
|
21
21
|
test "should be findable by id as string" do
|
22
|
-
with_instance_of(
|
22
|
+
with_instance_of(model_class) {|record| assert model_class.find record.id.to_s}
|
23
23
|
end
|
24
24
|
|
25
25
|
test "should be findable by numeric friendly_id" do
|
26
|
-
with_instance_of(
|
26
|
+
with_instance_of(model_class, :name => "206") {|record| assert model_class.find record.friendly_id}
|
27
27
|
end
|
28
28
|
|
29
29
|
test "to_param should return the friendly_id" do
|
30
|
-
with_instance_of(
|
30
|
+
with_instance_of(model_class) {|record| assert_equal record.friendly_id, record.to_param}
|
31
31
|
end
|
32
32
|
|
33
33
|
test "should be findable by themselves" do
|
34
|
-
with_instance_of(
|
34
|
+
with_instance_of(model_class) {|record| assert_equal record, model_class.find(record)}
|
35
35
|
end
|
36
36
|
|
37
37
|
test "updating record's other values should not change the friendly_id" do
|
38
|
-
with_instance_of
|
38
|
+
with_instance_of model_class do |record|
|
39
39
|
old = record.friendly_id
|
40
40
|
record.update_attributes! :active => false
|
41
|
-
assert
|
41
|
+
assert model_class.find old
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
test "instances found by a single id should not be read-only" do
|
46
|
-
with_instance_of(
|
46
|
+
with_instance_of(model_class) {|record| assert !model_class.find(record.friendly_id).readonly?}
|
47
47
|
end
|
48
48
|
|
49
49
|
test "failing finds with unfriendly_id should raise errors normally" do
|
50
|
-
assert_raises(ActiveRecord::RecordNotFound) {
|
50
|
+
assert_raises(ActiveRecord::RecordNotFound) {model_class.find 0}
|
51
51
|
end
|
52
52
|
|
53
53
|
test "should return numeric id if the friendly_id is nil" do
|
54
|
-
with_instance_of(
|
54
|
+
with_instance_of(model_class) do |record|
|
55
55
|
record.expects(:friendly_id).returns(nil)
|
56
56
|
assert_equal record.id.to_s, record.to_param
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
60
|
test "should return numeric id if the friendly_id is an empty string" do
|
61
|
-
with_instance_of(
|
61
|
+
with_instance_of(model_class) do |record|
|
62
62
|
record.expects(:friendly_id).returns("")
|
63
63
|
assert_equal record.id.to_s, record.to_param
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
67
|
test "should return numeric id if the friendly_id is blank" do
|
68
|
-
with_instance_of(
|
68
|
+
with_instance_of(model_class) do |record|
|
69
69
|
record.expects(:friendly_id).returns(" ")
|
70
70
|
assert_equal record.id.to_s, record.to_param
|
71
71
|
end
|
data/test/slugged_test.rb
CHANGED
@@ -12,16 +12,16 @@ class SluggedTest < MiniTest::Unit::TestCase
|
|
12
12
|
include FriendlyId::Test
|
13
13
|
include FriendlyId::Test::Shared
|
14
14
|
|
15
|
-
def
|
15
|
+
def model_class
|
16
16
|
Journalist
|
17
17
|
end
|
18
18
|
|
19
19
|
test "configuration should have a sequence_separator" do
|
20
|
-
assert !
|
20
|
+
assert !model_class.friendly_id_config.sequence_separator.empty?
|
21
21
|
end
|
22
22
|
|
23
23
|
test "should make a new slug if the friendly_id method value has changed" do
|
24
|
-
with_instance_of
|
24
|
+
with_instance_of model_class do |record|
|
25
25
|
record.name = "Changed Value"
|
26
26
|
record.save!
|
27
27
|
assert_equal "changed-value", record.slug
|
@@ -29,21 +29,31 @@ class SluggedTest < MiniTest::Unit::TestCase
|
|
29
29
|
end
|
30
30
|
|
31
31
|
test "should increment the slug sequence for duplicate friendly ids" do
|
32
|
-
with_instance_of
|
33
|
-
record2 =
|
32
|
+
with_instance_of model_class do |record|
|
33
|
+
record2 = model_class.create! :name => record.name
|
34
34
|
assert record2.friendly_id.match(/2\z/)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
test "should not add slug sequence on update after other conflicting slugs were added" do
|
39
|
-
with_instance_of
|
39
|
+
with_instance_of model_class do |record|
|
40
40
|
old = record.friendly_id
|
41
|
-
record2 =
|
41
|
+
record2 = model_class.create! :name => record.name
|
42
42
|
record.save!
|
43
43
|
record.reload
|
44
44
|
assert_equal old, record.to_param
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
test "should not increment sequence on save" do
|
49
|
+
with_instance_of model_class do |record|
|
50
|
+
record2 = model_class.create! :name => record.name
|
51
|
+
record2.active = !record2.active
|
52
|
+
record2.save!
|
53
|
+
assert record2.friendly_id.match(/2\z/)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
47
57
|
end
|
48
58
|
|
49
59
|
class SlugSequencerTest < MiniTest::Unit::TestCase
|
@@ -51,12 +61,12 @@ class SlugSequencerTest < MiniTest::Unit::TestCase
|
|
51
61
|
include FriendlyId::Test
|
52
62
|
|
53
63
|
test "should quote column names" do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
64
|
+
model_class = Class.new(ActiveRecord::Base)
|
65
|
+
model_class.table_name = "journalists"
|
66
|
+
model_class.extend FriendlyId
|
67
|
+
model_class.friendly_id :name, :use => :slugged, :slug_column => "strange name"
|
58
68
|
begin
|
59
|
-
with_instance_of(
|
69
|
+
with_instance_of(model_class) {|record| assert model_class.find(record.friendly_id)}
|
60
70
|
rescue ActiveRecord::StatementInvalid
|
61
71
|
flunk "column name was not quoted"
|
62
72
|
end
|
@@ -72,20 +82,20 @@ class SlugSeparatorTest < MiniTest::Unit::TestCase
|
|
72
82
|
friendly_id :name, :use => :slugged, :sequence_separator => ":"
|
73
83
|
end
|
74
84
|
|
75
|
-
def
|
85
|
+
def model_class
|
76
86
|
Journalist
|
77
87
|
end
|
78
88
|
|
79
89
|
test "should increment sequence with configured sequence separator" do
|
80
|
-
with_instance_of
|
81
|
-
record2 =
|
90
|
+
with_instance_of model_class do |record|
|
91
|
+
record2 = model_class.create! :name => record.name
|
82
92
|
assert record2.friendly_id.match(/:2\z/)
|
83
93
|
end
|
84
94
|
end
|
85
95
|
|
86
96
|
test "should detect when a sequenced slug has changed" do
|
87
|
-
with_instance_of
|
88
|
-
record2 =
|
97
|
+
with_instance_of model_class do |record|
|
98
|
+
record2 = model_class.create! :name => record.name
|
89
99
|
assert !record2.slug_sequencer.slug_changed?
|
90
100
|
record2.name = "hello world"
|
91
101
|
assert record2.slug_sequencer.slug_changed?
|
@@ -96,14 +106,14 @@ end
|
|
96
106
|
class SluggedRegressionsTest < MiniTest::Unit::TestCase
|
97
107
|
include FriendlyId::Test
|
98
108
|
|
99
|
-
def
|
109
|
+
def model_class
|
100
110
|
Journalist
|
101
111
|
end
|
102
112
|
|
103
113
|
test "should increment the slug sequence for duplicate friendly ids beyond 10" do
|
104
|
-
with_instance_of
|
114
|
+
with_instance_of model_class do |record|
|
105
115
|
(2..12).each do |i|
|
106
|
-
r =
|
116
|
+
r = model_class.create! :name => record.name
|
107
117
|
assert r.friendly_id.match(/#{i}\z/)
|
108
118
|
end
|
109
119
|
end
|