friendly_id4 4.0.0.pre → 4.0.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/ABOUT.md +139 -0
- data/Guide.md +405 -0
- data/README.md +65 -47
- data/Rakefile +12 -16
- data/bench.rb +71 -0
- data/friendly_id.gemspec +29 -0
- data/lib/friendly_id.rb +9 -116
- data/lib/friendly_id/base.rb +29 -0
- data/lib/friendly_id/configuration.rb +31 -0
- data/lib/friendly_id/finder_methods.rb +14 -0
- data/lib/friendly_id/history.rb +29 -0
- data/lib/friendly_id/migration.rb +17 -0
- data/lib/friendly_id/model.rb +22 -0
- data/lib/friendly_id/object_utils.rb +27 -0
- data/lib/friendly_id/scoped.rb +24 -2
- data/lib/friendly_id/slug_sequencer.rb +79 -0
- data/lib/friendly_id/slugged.rb +11 -84
- data/lib/friendly_id/version.rb +1 -1
- data/lib/generators/friendly_id_generator.rb +21 -0
- data/test/core_test.rb +23 -56
- data/test/helper.rb +41 -0
- data/test/history_test.rb +46 -0
- data/test/object_utils_test.rb +18 -0
- data/test/scoped_test.rb +30 -49
- data/test/shared.rb +47 -0
- data/test/slugged_test.rb +31 -52
- metadata +56 -22
- data/lib/friendly_id/test.rb +0 -23
- data/lib/friendly_id/test/generic.rb +0 -84
- data/test/test_helper.rb +0 -23
data/test/helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require "active_record"
|
4
|
+
require "active_support"
|
5
|
+
require "friendly_id"
|
6
|
+
$VERBOSE = true
|
7
|
+
|
8
|
+
ActiveRecord::Migration.verbose = false
|
9
|
+
|
10
|
+
# Change the connection args as you see fit to test against different adapters.
|
11
|
+
ActiveRecord::Base.establish_connection \
|
12
|
+
:adapter => "sqlite3",
|
13
|
+
:database => ":memory:"
|
14
|
+
|
15
|
+
# If you want to see the ActiveRecord log, invoke the tests using `rake test LOG=true`
|
16
|
+
if ENV["LOG"]
|
17
|
+
require "logger"
|
18
|
+
ActiveRecord::Base.logger = Logger.new($stdout)
|
19
|
+
end
|
20
|
+
|
21
|
+
User, Book = ["users", "books"].map do |table_name|
|
22
|
+
ActiveRecord::Migration.create_table table_name do |t|
|
23
|
+
t.string :name
|
24
|
+
t.boolean :active
|
25
|
+
end
|
26
|
+
Class.new(ActiveRecord::Base)
|
27
|
+
end
|
28
|
+
|
29
|
+
def transaction
|
30
|
+
ActiveRecord::Base.transaction { yield ; raise ActiveRecord::Rollback }
|
31
|
+
end
|
32
|
+
|
33
|
+
def with_instance_of(*args)
|
34
|
+
klass = args.shift
|
35
|
+
args[0] ||= {:name => "a"}
|
36
|
+
transaction { yield klass.create!(*args) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def migration
|
40
|
+
yield ActiveRecord::Migration
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
require "friendly_id/migration"
|
3
|
+
|
4
|
+
CreateFriendlyIdSlugs.up
|
5
|
+
|
6
|
+
migration do |m|
|
7
|
+
m.add_column :users, :slug, :string
|
8
|
+
end
|
9
|
+
|
10
|
+
User.send :include, FriendlyId::History
|
11
|
+
User.has_friendly_id :name
|
12
|
+
|
13
|
+
setup {User}
|
14
|
+
|
15
|
+
|
16
|
+
test "should insert record in slugs table on create" do |klass|
|
17
|
+
with_instance_of(klass) {|record| assert !record.friendly_id_slugs.empty?}
|
18
|
+
end
|
19
|
+
|
20
|
+
test "should not create new slug record if friendly_id is not changed" do |klass|
|
21
|
+
with_instance_of(klass) do |record|
|
22
|
+
record.active = true
|
23
|
+
record.save!
|
24
|
+
assert_equal 1, FriendlyIdSlug.count
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
test "should create new slug record when friendly_id changes" do |klass|
|
29
|
+
with_instance_of(klass) do |record|
|
30
|
+
record.name = record.name + "b"
|
31
|
+
record.save!
|
32
|
+
assert_equal 2, FriendlyIdSlug.count
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
test "should be findable by old slugs" do |klass|
|
37
|
+
with_instance_of(klass) do |record|
|
38
|
+
old_friendly_id = record.friendly_id
|
39
|
+
record.name = record.name + "b"
|
40
|
+
record.save!
|
41
|
+
assert found = klass.find_by_friendly_id(old_friendly_id)
|
42
|
+
assert !found.readonly?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
require File.expand_path("../shared.rb", __FILE__)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
test "strings with letters are friendly_ids" do
|
4
|
+
assert "a".friendly_id?
|
5
|
+
end
|
6
|
+
|
7
|
+
test "integers should be unfriendly ids" do
|
8
|
+
assert 1.unfriendly_id?
|
9
|
+
end
|
10
|
+
|
11
|
+
test "numeric strings are neither friendly nor unfriendly" do
|
12
|
+
assert_equal nil, "1".friendly_id?
|
13
|
+
assert_equal nil, "1".unfriendly_id?
|
14
|
+
end
|
15
|
+
|
16
|
+
test "ActiveRecord::Base instances should be unfriendly_ids" do
|
17
|
+
assert User.new.unfriendly_id?
|
18
|
+
end
|
data/test/scoped_test.rb
CHANGED
@@ -1,61 +1,42 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require File.expand_path("../
|
3
|
-
require "friendly_id/scoped"
|
2
|
+
require File.expand_path("../helper", __FILE__)
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
t.integer :city_id
|
4
|
+
migration do |m|
|
5
|
+
m.add_column :books, :slug, :string
|
6
|
+
m.add_column :books, :user_id, :integer
|
9
7
|
end
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
21
|
-
|
22
|
-
class ScopedTest < Test::Unit::TestCase
|
9
|
+
User.has_many :books
|
10
|
+
Book.belongs_to :user
|
11
|
+
Book.send :include, FriendlyId::Scoped
|
12
|
+
Book.has_friendly_id :name, :scope => :user
|
23
13
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
test "should detect scope column from belongs_to relation" do
|
30
|
-
assert_equal "city_id", Restaurant.friendly_id_config.scope_column
|
31
|
-
end
|
14
|
+
test "should detect scope column from belongs_to relation" do
|
15
|
+
assert_equal "user_id", Book.friendly_id_config.scope_column
|
16
|
+
end
|
32
17
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
18
|
+
test "should detect scope column from explicit column name" do
|
19
|
+
klass = Class.new(ActiveRecord::Base)
|
20
|
+
klass.has_friendly_id :empty, :scope => :dummy
|
21
|
+
assert_equal "dummy", klass.friendly_id_config.scope_column
|
22
|
+
end
|
38
23
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
assert_equal r1.friendly_id, r2.friendly_id
|
24
|
+
test "should allow duplicate slugs outside scope" do
|
25
|
+
transaction do
|
26
|
+
book1 = Book.create! :name => "a", :user => User.create!(:name => "a")
|
27
|
+
book2 = Book.create! :name => "a", :user => User.create!(:name => "b")
|
28
|
+
assert_equal book1.friendly_id, book2.friendly_id
|
45
29
|
end
|
30
|
+
end
|
46
31
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
32
|
+
test "should not allow duplicate slugs inside scope" do
|
33
|
+
with_instance_of User do |user|
|
34
|
+
book1 = Book.create! :name => "a", :user => user
|
35
|
+
book2 = Book.create! :name => "a", :user => user
|
36
|
+
assert book1.friendly_id != book2.friendly_id
|
52
37
|
end
|
38
|
+
end
|
53
39
|
|
54
|
-
|
55
|
-
city = City.create! :name => "Nuñez"
|
56
|
-
old = city.friendly_id
|
57
|
-
city.save!
|
58
|
-
assert_equal old, city.friendly_id
|
59
|
-
end
|
40
|
+
setup { Book }
|
60
41
|
|
61
|
-
|
42
|
+
require File.expand_path("../shared.rb", __FILE__)
|
data/test/shared.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
test "finds should respect conditions" do |klass|
|
2
|
+
with_instance_of(klass) do |record|
|
3
|
+
assert_raise(ActiveRecord::RecordNotFound) do
|
4
|
+
klass.where("1 = 2").find record.friendly_id
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
test "should be findable by friendly id" do |klass|
|
10
|
+
with_instance_of(klass) {|record| assert klass.find record.friendly_id}
|
11
|
+
end
|
12
|
+
|
13
|
+
test "should be findable by id as integer" do |klass|
|
14
|
+
with_instance_of(klass) {|record| assert klass.find record.id.to_i}
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should be findable by id as string" do |klass|
|
18
|
+
with_instance_of(klass) {|record| assert klass.find record.id.to_s}
|
19
|
+
end
|
20
|
+
|
21
|
+
test "should be findable by numeric friendly_id" do |klass|
|
22
|
+
with_instance_of(klass, :name => "206") {|record| assert klass.find record.friendly_id}
|
23
|
+
end
|
24
|
+
|
25
|
+
test "to_param should return the friendly_id" do |klass|
|
26
|
+
with_instance_of(klass) {|record| assert_equal record.friendly_id, record.to_param}
|
27
|
+
end
|
28
|
+
|
29
|
+
test "should be findable by themselves" do |klass|
|
30
|
+
with_instance_of(klass) {|record| assert_equal record, klass.find(record)}
|
31
|
+
end
|
32
|
+
|
33
|
+
test "updating record's other values should not change the friendly_id" do |klass|
|
34
|
+
with_instance_of klass do |record|
|
35
|
+
old = record.friendly_id
|
36
|
+
record.update_attributes! :active => false
|
37
|
+
assert klass.find old
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
test "instances found by a single id should not be read-only" do |klass|
|
42
|
+
with_instance_of(klass) {|record| assert !klass.find(record.friendly_id).readonly?}
|
43
|
+
end
|
44
|
+
|
45
|
+
test "failing finds with unfriendly_id should raise errors normally" do |klass|
|
46
|
+
assert_raise(ActiveRecord::RecordNotFound) {klass.find 0}
|
47
|
+
end
|
data/test/slugged_test.rb
CHANGED
@@ -1,64 +1,43 @@
|
|
1
|
-
require File.expand_path("../
|
2
|
-
require "friendly_id/slugged"
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def instance(name = "user")
|
9
|
-
@instance ||= klass.create!(:name => name)
|
10
|
-
end
|
11
|
-
|
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
|
18
|
-
end
|
19
|
-
@@klass.send :include, FriendlyId::Slugged
|
20
|
-
@@klass
|
3
|
+
[User, Book].map do |klass|
|
4
|
+
migration do |m|
|
5
|
+
m.add_column klass.table_name, :slug, :string
|
6
|
+
m.add_index klass.table_name, :slug, :unique => true
|
21
7
|
end
|
8
|
+
klass.send :include, FriendlyId::Slugged
|
9
|
+
klass.has_friendly_id :name
|
10
|
+
end
|
22
11
|
|
23
|
-
|
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
|
32
|
-
end
|
12
|
+
setup { User }
|
33
13
|
|
34
|
-
|
35
|
-
klass.delete_all
|
36
|
-
other_class.delete_all
|
37
|
-
end
|
14
|
+
require File.expand_path("../shared.rb", __FILE__)
|
38
15
|
|
39
|
-
|
40
|
-
|
41
|
-
|
16
|
+
test "configuration should have a sequence_separator" do |klass|
|
17
|
+
assert !klass.friendly_id_config.sequence_separator.empty?
|
18
|
+
end
|
42
19
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
20
|
+
test "should make a new slug if the friendly_id method value has changed" do |klass|
|
21
|
+
with_instance_of klass do |record|
|
22
|
+
record.name = "Changed Value"
|
23
|
+
record.save!
|
24
|
+
assert_equal "changed-value", record.slug
|
47
25
|
end
|
26
|
+
end
|
48
27
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
assert_match(/3\z/, instance3.friendly_id)
|
28
|
+
test "should increment the slug sequence for duplicate friendly ids" do |klass|
|
29
|
+
with_instance_of klass do |record|
|
30
|
+
record2 = klass.create! :name => record.name
|
31
|
+
assert record2.friendly_id.match(/2\z/)
|
54
32
|
end
|
33
|
+
end
|
55
34
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
35
|
+
test "should not add slug sequence on update after other conflicting slugs were added" do |klass|
|
36
|
+
with_instance_of klass do |record|
|
37
|
+
old = record.friendly_id
|
38
|
+
record2 = klass.create! :name => record.name
|
39
|
+
record.save!
|
40
|
+
record.reload
|
41
|
+
assert_equal old, record.to_param
|
62
42
|
end
|
63
|
-
|
64
43
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: friendly_id4
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 6
|
5
|
-
version: 4.0.0.
|
5
|
+
version: 4.0.0.pre3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Norman Clarke
|
@@ -10,8 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
14
|
-
default_executable:
|
13
|
+
date: 2011-06-25 00:00:00 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: activerecord
|
@@ -25,29 +24,52 @@ dependencies:
|
|
25
24
|
type: :development
|
26
25
|
version_requirements: *id001
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
27
|
+
name: sqlite3
|
29
28
|
prerelease: false
|
30
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
31
30
|
none: false
|
32
31
|
requirements:
|
33
32
|
- - ~>
|
34
33
|
- !ruby/object:Gem::Version
|
35
|
-
version: "
|
34
|
+
version: "1.3"
|
36
35
|
type: :development
|
37
36
|
version_requirements: *id002
|
38
37
|
- !ruby/object:Gem::Dependency
|
39
|
-
name:
|
38
|
+
name: cutest
|
40
39
|
prerelease: false
|
41
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
42
41
|
none: false
|
43
42
|
requirements:
|
44
43
|
- - ~>
|
45
44
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
45
|
+
version: 1.1.2
|
47
46
|
type: :development
|
48
47
|
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: ffaker
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: yard
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id005
|
49
70
|
description: " FriendlyId is the \"Swiss Army bulldozer\" of slugging and permalink plugins\n for Ruby on Rails. It allows you to create pretty URL's and work with\n human-friendly strings as if they were numeric ids for ActiveRecord models.\n"
|
50
|
-
email:
|
71
|
+
email:
|
72
|
+
- norman@njclarke.com
|
51
73
|
executables: []
|
52
74
|
|
53
75
|
extensions: []
|
@@ -55,20 +77,34 @@ extensions: []
|
|
55
77
|
extra_rdoc_files: []
|
56
78
|
|
57
79
|
files:
|
80
|
+
- .gitignore
|
81
|
+
- ABOUT.md
|
82
|
+
- Guide.md
|
83
|
+
- README.md
|
84
|
+
- Rakefile
|
85
|
+
- bench.rb
|
86
|
+
- friendly_id.gemspec
|
87
|
+
- lib/friendly_id.rb
|
88
|
+
- lib/friendly_id/base.rb
|
89
|
+
- lib/friendly_id/configuration.rb
|
90
|
+
- lib/friendly_id/finder_methods.rb
|
91
|
+
- lib/friendly_id/history.rb
|
92
|
+
- lib/friendly_id/migration.rb
|
93
|
+
- lib/friendly_id/model.rb
|
94
|
+
- lib/friendly_id/object_utils.rb
|
58
95
|
- lib/friendly_id/scoped.rb
|
96
|
+
- lib/friendly_id/slug_sequencer.rb
|
59
97
|
- lib/friendly_id/slugged.rb
|
60
|
-
- lib/friendly_id/test/generic.rb
|
61
|
-
- lib/friendly_id/test.rb
|
62
98
|
- lib/friendly_id/version.rb
|
63
|
-
- lib/
|
64
|
-
- README.md
|
65
|
-
- Rakefile
|
99
|
+
- lib/generators/friendly_id_generator.rb
|
66
100
|
- test/core_test.rb
|
101
|
+
- test/helper.rb
|
102
|
+
- test/history_test.rb
|
103
|
+
- test/object_utils_test.rb
|
67
104
|
- test/scoped_test.rb
|
105
|
+
- test/shared.rb
|
68
106
|
- test/slugged_test.rb
|
69
|
-
|
70
|
-
has_rdoc: true
|
71
|
-
homepage: http://norman.github.com/friendly_id_4
|
107
|
+
homepage: http://norman.github.com/friendly_id
|
72
108
|
licenses: []
|
73
109
|
|
74
110
|
post_install_message:
|
@@ -90,12 +126,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
126
|
version: 1.3.1
|
91
127
|
requirements: []
|
92
128
|
|
93
|
-
rubyforge_project:
|
94
|
-
rubygems_version: 1.
|
129
|
+
rubyforge_project: friendly_id
|
130
|
+
rubygems_version: 1.8.5
|
95
131
|
signing_key:
|
96
132
|
specification_version: 3
|
97
133
|
summary: A comprehensive slugging and pretty-URL plugin.
|
98
|
-
test_files:
|
99
|
-
|
100
|
-
- test/scoped_test.rb
|
101
|
-
- test/slugged_test.rb
|
134
|
+
test_files: []
|
135
|
+
|