friendly_id4 4.0.0.beta6 → 4.0.0.pre
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/README.md +47 -68
- data/Rakefile +13 -108
- data/lib/friendly_id.rb +97 -117
- data/lib/friendly_id/scoped.rb +17 -116
- data/lib/friendly_id/slugged.rb +89 -183
- data/lib/friendly_id/test.rb +23 -0
- data/lib/friendly_id/test/generic.rb +84 -0
- data/lib/friendly_id/version.rb +9 -0
- data/test/core_test.rb +54 -16
- data/test/scoped_test.rb +39 -35
- data/test/slugged_test.rb +45 -64
- data/test/test_helper.rb +23 -0
- metadata +61 -125
- data/.gemtest +0 -0
- data/.gitignore +0 -11
- data/.yardopts +0 -4
- data/WhatsNew.md +0 -142
- data/bench.rb +0 -63
- data/friendly_id.gemspec +0 -31
- data/lib/friendly_id/base.rb +0 -134
- data/lib/friendly_id/configuration.rb +0 -78
- data/lib/friendly_id/finder_methods.rb +0 -20
- data/lib/friendly_id/history.rb +0 -64
- data/lib/friendly_id/migration.rb +0 -18
- data/lib/friendly_id/model.rb +0 -22
- data/lib/friendly_id/object_utils.rb +0 -40
- data/lib/friendly_id/reserved.rb +0 -46
- data/lib/friendly_id/slug.rb +0 -6
- data/lib/friendly_id/slug_sequencer.rb +0 -82
- data/lib/generators/friendly_id_generator.rb +0 -24
- data/test/base_test.rb +0 -54
- data/test/config/mysql.yml +0 -5
- data/test/config/mysql2.yml +0 -5
- data/test/config/postgres.yml +0 -6
- data/test/config/sqlite3.yml +0 -3
- data/test/configuration_test.rb +0 -27
- data/test/helper.rb +0 -90
- data/test/history_test.rb +0 -55
- data/test/object_utils_test.rb +0 -26
- data/test/reserved_test.rb +0 -26
- data/test/schema.rb +0 -56
- data/test/shared.rb +0 -118
- data/test/sti_test.rb +0 -48
@@ -0,0 +1,23 @@
|
|
1
|
+
# Allow declarative test definitions inside modules.
|
2
|
+
class Module
|
3
|
+
def test(name, &block)
|
4
|
+
define_method("test_#{name.gsub(/[^a-z0-9]/i, "_")}".to_sym, &block)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# Use this to create models in your tests, rather than define
|
9
|
+
# a bunch of static models. This allows for much more
|
10
|
+
# flexbile and granular tests.
|
11
|
+
#
|
12
|
+
# @name The table name - make sure it is unique.
|
13
|
+
# @args The args that will be passed to +has_friendly_id+.
|
14
|
+
# @block The block that will be passed to +create_table+.
|
15
|
+
def make_model(name, *args, &block)
|
16
|
+
ActiveRecord::Migration.create_table(name, &block)
|
17
|
+
Class.new(ActiveRecord::Base) do
|
18
|
+
self.table_name = name
|
19
|
+
has_friendly_id(*args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require "friendly_id/test/generic"
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
module Test
|
3
|
+
# Tests for any model that implements FriendlyId. Any test that tests model
|
4
|
+
# features should include this module.
|
5
|
+
module Generic
|
6
|
+
|
7
|
+
def teardown
|
8
|
+
klass.delete_all
|
9
|
+
end
|
10
|
+
|
11
|
+
def instance
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def klass
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def other_class
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
test "model classes should have a friendly id config" do
|
24
|
+
assert_not_nil klass.friendly_id_config
|
25
|
+
end
|
26
|
+
|
27
|
+
test "finds should respect conditions" do
|
28
|
+
assert_raise ActiveRecord::RecordNotFound do
|
29
|
+
klass.find(instance.friendly_id, :conditions => "1 = 2")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
test "instances should have a friendly id" do
|
34
|
+
assert_not_nil instance.friendly_id
|
35
|
+
end
|
36
|
+
|
37
|
+
test "instances should be findable by their friendly id" do
|
38
|
+
assert_equal instance, klass.find(instance.friendly_id)
|
39
|
+
end
|
40
|
+
|
41
|
+
test "instances should be findable by their numeric id as an integer" do
|
42
|
+
assert_equal instance, klass.find(instance.id.to_i)
|
43
|
+
end
|
44
|
+
|
45
|
+
test "instances should be findable by their numeric id as a string" do
|
46
|
+
assert_equal instance, klass.find(instance.id.to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
test "instances should be findable by a numeric friendly_id" do
|
50
|
+
instance = klass.create! :name => "206"
|
51
|
+
assert_equal instance, klass.find(instance.friendly_id)
|
52
|
+
end
|
53
|
+
|
54
|
+
test "to_param should return the friendly_id" do
|
55
|
+
assert_equal instance.friendly_id, instance.to_param
|
56
|
+
end
|
57
|
+
|
58
|
+
test "should allow the same friendly_id across models" do
|
59
|
+
other_instance = other_class.create! :name => instance.name
|
60
|
+
assert_equal other_instance.friendly_id, instance.friendly_id
|
61
|
+
end
|
62
|
+
|
63
|
+
test "instances should be findable by themselves" do
|
64
|
+
assert_equal instance, klass.find(instance)
|
65
|
+
end
|
66
|
+
|
67
|
+
test "updating record's other values should not change the friendly_id" do
|
68
|
+
old = instance.friendly_id
|
69
|
+
instance.save
|
70
|
+
assert klass.find(old)
|
71
|
+
end
|
72
|
+
|
73
|
+
test "instances found by a single id should not be read-only" do
|
74
|
+
assert !klass.find(instance.friendly_id).readonly?, "expected instance not to be readonly"
|
75
|
+
end
|
76
|
+
|
77
|
+
test "failing finds with unfriendly_id should raise errors normally" do
|
78
|
+
assert_raise ActiveRecord::RecordNotFound do
|
79
|
+
klass.find(0)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/test/core_test.rb
CHANGED
@@ -1,30 +1,68 @@
|
|
1
|
-
require File.expand_path("../
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
class ModelTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include FriendlyId::Test::Generic
|
6
|
+
|
7
|
+
def instance(name = "user")
|
8
|
+
@instance ||= klass.create!(:name => name)
|
7
9
|
end
|
8
|
-
end
|
9
10
|
|
10
|
-
|
11
|
+
# @TODO - this kind of setup is repeated in a few places and should probably
|
12
|
+
# be abstracted.
|
13
|
+
def klass
|
14
|
+
@@klass ||= make_model("core", :name) do |t|
|
15
|
+
t.string :name, :unique => true
|
16
|
+
t.boolean :active, :default => true
|
17
|
+
end
|
18
|
+
@@klass
|
19
|
+
end
|
11
20
|
|
12
|
-
|
13
|
-
|
21
|
+
def other_class
|
22
|
+
@@other_class ||= make_model("core_two", :name) do |t|
|
23
|
+
t.string :name, :unique => true
|
24
|
+
t.boolean :active, :default => true
|
25
|
+
end
|
26
|
+
end
|
14
27
|
|
15
|
-
def
|
16
|
-
|
28
|
+
def setup
|
29
|
+
klass.stubs(:name).returns("Cores")
|
30
|
+
other_class.stubs(:name).returns("CoreTwos")
|
17
31
|
end
|
18
32
|
|
19
33
|
test "models don't use friendly_id by default" do
|
20
|
-
assert !Class.new(ActiveRecord::Base).
|
34
|
+
assert !Class.new(ActiveRecord::Base).uses_friendly_id?
|
35
|
+
end
|
36
|
+
|
37
|
+
test "integers should be unfriendly ids" do
|
38
|
+
assert 1.unfriendly_id?
|
21
39
|
end
|
22
40
|
|
23
|
-
test "
|
24
|
-
assert
|
41
|
+
test "ActiveRecord::Base instances should be unfriendly_ids" do
|
42
|
+
assert klass.new.unfriendly_id?
|
25
43
|
end
|
26
44
|
|
27
|
-
test "
|
28
|
-
|
45
|
+
test "numeric strings are neither friendly nor unfriendly" do
|
46
|
+
assert_equal nil, "1".friendly_id?
|
47
|
+
assert_equal nil, "1".unfriendly_id?
|
29
48
|
end
|
49
|
+
|
50
|
+
test "strings with letters are friendly_ids" do
|
51
|
+
assert "a".friendly_id?
|
52
|
+
end
|
53
|
+
|
54
|
+
test "should raise error when bad config options are set" do
|
55
|
+
assert_raises ArgumentError do
|
56
|
+
klass.has_friendly_id :smeg, :garbage => :in
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
test "reserves 'new' and 'edit' by default" do
|
61
|
+
FriendlyId::Configuration::DEFAULTS[:reserved_words].each do |word|
|
62
|
+
assert_raises ActiveRecord::RecordInvalid do
|
63
|
+
klass.create! :name => word
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
30
68
|
end
|
data/test/scoped_test.rb
CHANGED
@@ -1,57 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path("../test_helper", __FILE__)
|
3
|
+
require "friendly_id/scoped"
|
4
|
+
|
5
|
+
Restaurant = make_model("restaurants", :name) do |t|
|
6
|
+
t.string :name
|
7
|
+
t.string :slug
|
8
|
+
t.integer :city_id
|
6
9
|
end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
friendly_id :name, :use => :scoped, :scope => :novelist
|
11
|
+
City = make_model("cities", :name) do |t|
|
12
|
+
t.string :name
|
13
|
+
t.string :slug
|
12
14
|
end
|
13
15
|
|
14
|
-
|
16
|
+
Restaurant.belongs_to :city
|
17
|
+
City.has_many :restaurants
|
18
|
+
City.send :include, FriendlyId::Slugged
|
19
|
+
Restaurant.send :include, FriendlyId::Scoped
|
20
|
+
Restaurant.has_friendly_id :name, :scope => :city
|
15
21
|
|
16
|
-
|
17
|
-
include FriendlyId::Test::Shared::Core
|
22
|
+
class ScopedTest < Test::Unit::TestCase
|
18
23
|
|
19
|
-
def
|
20
|
-
|
24
|
+
def setup
|
25
|
+
Restaurant.delete_all
|
26
|
+
City.delete_all
|
21
27
|
end
|
22
28
|
|
23
29
|
test "should detect scope column from belongs_to relation" do
|
24
|
-
assert_equal "
|
30
|
+
assert_equal "city_id", Restaurant.friendly_id_config.scope_column
|
25
31
|
end
|
26
32
|
|
27
33
|
test "should detect scope column from explicit column name" do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
assert_equal "dummy", model_class.friendly_id_config.scope_column
|
34
|
+
klass = Class.new(ActiveRecord::Base)
|
35
|
+
klass.has_friendly_id :empty, :scope => :dummy
|
36
|
+
assert_equal "dummy", klass.friendly_id_config.scope_column
|
32
37
|
end
|
33
38
|
|
34
39
|
test "should allow duplicate slugs outside scope" do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
c1 = City.create! :name => "Nuñez"
|
41
|
+
c2 = City.create! :name => "Las Cañitas"
|
42
|
+
r1 = Restaurant.create! :name => "La Guitarrita", :city => c1
|
43
|
+
r2 = Restaurant.create! :name => "La Guitarrita", :city => c2
|
44
|
+
assert_equal r1.friendly_id, r2.friendly_id
|
40
45
|
end
|
41
46
|
|
42
47
|
test "should not allow duplicate slugs inside scope" do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
+
c1 = City.create! :name => "Nuñez"
|
49
|
+
r1 = Restaurant.create! :name => "La Guitarrita", :city => c1
|
50
|
+
r2 = Restaurant.create! :name => "La Guitarrita", :city => c1
|
51
|
+
assert_not_equal "la-guitarrita", r2.friendly_id
|
48
52
|
end
|
49
53
|
|
50
|
-
test "
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
54
|
+
test "updating record's other values should not change the friendly_id" do
|
55
|
+
city = City.create! :name => "Nuñez"
|
56
|
+
old = city.friendly_id
|
57
|
+
city.save!
|
58
|
+
assert_equal old, city.friendly_id
|
56
59
|
end
|
60
|
+
|
57
61
|
end
|
data/test/slugged_test.rb
CHANGED
@@ -1,83 +1,64 @@
|
|
1
|
-
require File.expand_path("../
|
1
|
+
require File.expand_path("../test_helper", __FILE__)
|
2
|
+
require "friendly_id/slugged"
|
2
3
|
|
3
|
-
|
4
|
-
Class.new(ActiveRecord::Base) do
|
5
|
-
extend FriendlyId
|
6
|
-
friendly_id :name, :use => :slugged
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
class SluggedTest < MiniTest::Unit::TestCase
|
4
|
+
class SluggedTest < Test::Unit::TestCase
|
11
5
|
|
12
|
-
include FriendlyId::Test
|
13
|
-
include FriendlyId::Test::Shared::Core
|
14
|
-
include FriendlyId::Test::Shared::Slugged
|
6
|
+
include FriendlyId::Test::Generic
|
15
7
|
|
16
|
-
def
|
17
|
-
|
8
|
+
def instance(name = "user")
|
9
|
+
@instance ||= klass.create!(:name => name)
|
18
10
|
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class SlugSequencerTest < MiniTest::Unit::TestCase
|
22
11
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
model_class.friendly_id :name, :use => :slugged, :slug_column => "strange name"
|
30
|
-
begin
|
31
|
-
with_instance_of(model_class) {|record| assert model_class.find(record.friendly_id)}
|
32
|
-
rescue ActiveRecord::StatementInvalid
|
33
|
-
flunk "column name was not quoted"
|
12
|
+
def klass
|
13
|
+
return @@klass if defined?(@@klass)
|
14
|
+
@@klass = make_model("slugged_model", :name) do |t|
|
15
|
+
t.string :name, :unique => true
|
16
|
+
t.string :slug, :unique => true
|
17
|
+
t.boolean :active, :default => true
|
34
18
|
end
|
19
|
+
@@klass.send :include, FriendlyId::Slugged
|
20
|
+
@@klass
|
35
21
|
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class SlugSeparatorTest < MiniTest::Unit::TestCase
|
39
|
-
|
40
|
-
include FriendlyId::Test
|
41
22
|
|
42
|
-
|
43
|
-
|
44
|
-
|
23
|
+
def other_class
|
24
|
+
return @@other_class if defined?(@@other_class)
|
25
|
+
@@other_class = make_model("other_slugged_model", :name) do |t|
|
26
|
+
t.string :name, :unique => true
|
27
|
+
t.string :slug, :unique => true
|
28
|
+
t.boolean :active, :default => true
|
29
|
+
end
|
30
|
+
@@other_class.send :include, FriendlyId::Slugged
|
31
|
+
@@other_class
|
45
32
|
end
|
46
33
|
|
47
|
-
def
|
48
|
-
|
34
|
+
def setup
|
35
|
+
klass.delete_all
|
36
|
+
other_class.delete_all
|
49
37
|
end
|
50
38
|
|
51
|
-
test "should
|
52
|
-
|
53
|
-
record2 = model_class.create! :name => record.name
|
54
|
-
assert record2.friendly_id.match(/:2\z/)
|
55
|
-
end
|
39
|
+
test "configuration should have a sequence_separator" do
|
40
|
+
assert_not_nil klass.friendly_id_config.sequence_separator
|
56
41
|
end
|
57
42
|
|
58
|
-
test "should
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
record2.name = "hello world"
|
63
|
-
assert record2.slug_sequencer.slug_changed?
|
64
|
-
end
|
43
|
+
test "should make a new slug if the friendly_id method value has changed" do
|
44
|
+
instance.name = "Changed Value"
|
45
|
+
instance.save!
|
46
|
+
assert_equal "changed-value", instance.slug
|
65
47
|
end
|
66
|
-
end
|
67
48
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
49
|
+
test "should increment the slug sequence for duplicate friendly ids" do
|
50
|
+
instance2 = klass.create! :name => instance.name
|
51
|
+
assert_match(/2\z/, instance2.friendly_id)
|
52
|
+
instance3 = klass.create! :name => instance.name
|
53
|
+
assert_match(/3\z/, instance3.friendly_id)
|
73
54
|
end
|
74
55
|
|
75
|
-
test "should
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
56
|
+
test "should not add slug sequence on update after other conflicting slugs were added" do
|
57
|
+
old = instance.friendly_id
|
58
|
+
instance2 = klass.create! :name => instance.name
|
59
|
+
instance.save!
|
60
|
+
instance.reload
|
61
|
+
assert_equal old, instance.to_param
|
82
62
|
end
|
83
|
-
|
63
|
+
|
64
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$VERBOSE = false
|
2
|
+
require "rubygems"
|
3
|
+
require "bundler/setup"
|
4
|
+
require "active_record"
|
5
|
+
require "active_support"
|
6
|
+
require "friendly_id"
|
7
|
+
require "friendly_id/test"
|
8
|
+
require "test/unit"
|
9
|
+
require "mocha"
|
10
|
+
|
11
|
+
ActiveRecord::Migration.verbose = false
|
12
|
+
|
13
|
+
# Change the connection args as you see fit to test against different adapters.
|
14
|
+
ActiveRecord::Base.establish_connection(
|
15
|
+
:adapter => "sqlite3",
|
16
|
+
:database => ":memory:"
|
17
|
+
)
|
18
|
+
|
19
|
+
# If you want to see the ActiveRecord log, invoke the tests using `rake test LOG=true`
|
20
|
+
if ENV["LOG"]
|
21
|
+
require "logger"
|
22
|
+
ActiveRecord::Base.logger = Logger.new($stdout)
|
23
|
+
end
|