friendly_id 4.0.2 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -2
- data/.yardopts +1 -0
- data/Changelog.md +7 -0
- data/Guide.rdoc +60 -7
- data/Rakefile +16 -8
- data/lib/friendly_id.rb +6 -1
- data/lib/friendly_id/base.rb +42 -14
- data/lib/friendly_id/configuration.rb +8 -7
- data/lib/friendly_id/globalize.rb +11 -7
- data/lib/friendly_id/history.rb +7 -7
- data/lib/friendly_id/simple_i18n.rb +7 -3
- data/lib/friendly_id/slug.rb +5 -0
- data/lib/friendly_id/slug_generator.rb +5 -2
- data/test/base_test.rb +15 -1
- data/test/configuration_test.rb +20 -1
- data/test/core_test.rb +1 -1
- data/test/generator_test.rb +1 -2
- data/test/helper.rb +0 -4
- data/test/history_test.rb +15 -1
- data/test/i18n_test.rb +1 -1
- data/test/object_utils_test.rb +1 -1
- data/test/reserved_test.rb +1 -1
- data/test/schema.rb +1 -0
- data/test/scoped_test.rb +1 -1
- data/test/shared.rb +1 -1
- data/test/slugged_test.rb +21 -1
- data/test/sti_test.rb +25 -5
- metadata +20 -20
data/.travis.yml
CHANGED
data/.yardopts
CHANGED
data/Changelog.md
CHANGED
@@ -6,6 +6,13 @@ suggestions, ideas and improvements to FriendlyId.
|
|
6
6
|
* Table of Contents
|
7
7
|
{:toc}
|
8
8
|
|
9
|
+
## 4.0.3 (2012-03-14)
|
10
|
+
|
11
|
+
* Fix escape for '%' and '_' on SQLite (Norman Clarke and Sergey Petrunin)
|
12
|
+
* Allow FriendlyId to be extended or included (Norman Clarke)
|
13
|
+
* Allow Configuration#use to accept a Module (Norman Clarke)
|
14
|
+
* Fix bugs with History module + STI (Norman Clarke and Sergey Petrunin)
|
15
|
+
|
9
16
|
## 4.0.2 (2012-03-12)
|
10
17
|
|
11
18
|
* Improved conflict handling and performance in History module (Erik Ogan and Thomas Shafer)
|
data/Guide.rdoc
CHANGED
@@ -38,12 +38,13 @@ with numeric ids:
|
|
38
38
|
|
39
39
|
== Setting Up FriendlyId in Your Model
|
40
40
|
|
41
|
-
To use FriendlyId in your ActiveRecord models, you must first extend
|
42
|
-
FriendlyId module, then invoke the
|
43
|
-
method to configure your desired
|
41
|
+
To use FriendlyId in your ActiveRecord models, you must first either extend or
|
42
|
+
include the FriendlyId module (it makes no difference), then invoke the
|
43
|
+
{FriendlyId::Base#friendly_id friendly_id} method to configure your desired
|
44
|
+
options:
|
44
45
|
|
45
46
|
class Foo < ActiveRecord::Base
|
46
|
-
|
47
|
+
include FriendlyId
|
47
48
|
friendly_id :bar, :use => [:slugged, :simple_i18n]
|
48
49
|
end
|
49
50
|
|
@@ -401,7 +402,7 @@ an example of one way to set this up:
|
|
401
402
|
http://example.org/cities/chicago/restaurants/joes-diner
|
402
403
|
|
403
404
|
|
404
|
-
== Simple I18n
|
405
|
+
== Translating Slugs Using Simple I18n
|
405
406
|
|
406
407
|
The {FriendlyId::SimpleI18n SimpleI18n} module adds very basic i18n support to
|
407
408
|
FriendlyId.
|
@@ -409,8 +410,12 @@ FriendlyId.
|
|
409
410
|
In order to use this module, your model must have a slug column for each locale.
|
410
411
|
By default FriendlyId looks for columns named, for example, "slug_en",
|
411
412
|
"slug_es", etc. The first part of the name can be configured by passing the
|
412
|
-
+:slug_column+ option if you choose. Note that
|
413
|
-
|
413
|
+
+:slug_column+ option if you choose. Note that the column for the default locale
|
414
|
+
must also include the locale in its name.
|
415
|
+
|
416
|
+
This module is most suitable to applications that need to support few locales.
|
417
|
+
If you need to support two or more locales, you may wish to use the
|
418
|
+
{FriendlyId::Globalize Globalize} module instead.
|
414
419
|
|
415
420
|
=== Example migration
|
416
421
|
|
@@ -462,6 +467,54 @@ current locale:
|
|
462
467
|
end
|
463
468
|
|
464
469
|
|
470
|
+
== Translating Slugs Using Globalize
|
471
|
+
|
472
|
+
The {FriendlyId::Globalize Globalize} module lets you use
|
473
|
+
Globalize[https://github.com/svenfuchs/globalize3] to translate slugs. This
|
474
|
+
module is most suitable for applications that need to be localized to many
|
475
|
+
languages. If your application only needs to be localized to one or two
|
476
|
+
languages, you may wish to consider the {FriendlyId::SimpleI18n SimpleI18n}
|
477
|
+
module.
|
478
|
+
|
479
|
+
In order to use this module, your model must have a slug column and set the
|
480
|
+
field +slug+ as translable with Globalize:
|
481
|
+
|
482
|
+
class Post < ActiveRecord::Base
|
483
|
+
translates :title, :slug
|
484
|
+
extend FriendlyId
|
485
|
+
friendly_id :title, :use => :globalize
|
486
|
+
end
|
487
|
+
|
488
|
+
=== Finds
|
489
|
+
|
490
|
+
Finds will take the current locale into consideration:
|
491
|
+
|
492
|
+
I18n.locale = :it
|
493
|
+
Post.find("guerre-stellari")
|
494
|
+
I18n.locale = :en
|
495
|
+
Post.find("star-wars")
|
496
|
+
|
497
|
+
To find a slug by an explicit locale, perform the find inside a block
|
498
|
+
passed to I18n's +with_locale+ method:
|
499
|
+
|
500
|
+
I18n.with_locale(:it) do
|
501
|
+
Post.find("guerre-stellari")
|
502
|
+
end
|
503
|
+
|
504
|
+
=== Creating Records
|
505
|
+
|
506
|
+
When new records are created, the slug is generated for the current locale only.
|
507
|
+
|
508
|
+
=== Translating Slugs
|
509
|
+
|
510
|
+
To translate an existing record's friendly_id, simply change the locale and
|
511
|
+
assign a value to the +slug+ field:
|
512
|
+
|
513
|
+
I18n.with_locale(:it) do
|
514
|
+
post.slug = "guerre-stellari"
|
515
|
+
end
|
516
|
+
|
517
|
+
|
465
518
|
== Reserved Words
|
466
519
|
|
467
520
|
The {FriendlyId::Reserved Reserved} module adds the ability to exlude a list of
|
data/Rakefile
CHANGED
@@ -3,7 +3,14 @@ require "rake/testtask"
|
|
3
3
|
|
4
4
|
task :default => :test
|
5
5
|
|
6
|
+
task :load_path do
|
7
|
+
%w(lib test).each do |path|
|
8
|
+
$LOAD_PATH.unshift(File.expand_path("../#{path}", __FILE__))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
6
12
|
Rake::TestTask.new do |t|
|
13
|
+
t.libs << "test"
|
7
14
|
t.test_files = FileList['test/*_test.rb']
|
8
15
|
t.verbose = true
|
9
16
|
end
|
@@ -21,7 +28,7 @@ task :yard => :guide do
|
|
21
28
|
puts %x{bundle exec yard}
|
22
29
|
end
|
23
30
|
|
24
|
-
task :bench do
|
31
|
+
task :bench => :load_path do
|
25
32
|
require File.expand_path("../bench", __FILE__)
|
26
33
|
end
|
27
34
|
|
@@ -40,6 +47,7 @@ task :guide do
|
|
40
47
|
buffer << read_comments("lib/friendly_id/history.rb")
|
41
48
|
buffer << read_comments("lib/friendly_id/scoped.rb")
|
42
49
|
buffer << read_comments("lib/friendly_id/simple_i18n.rb")
|
50
|
+
buffer << read_comments("lib/friendly_id/globalize.rb")
|
43
51
|
buffer << read_comments("lib/friendly_id/reserved.rb")
|
44
52
|
|
45
53
|
File.open("Guide.rdoc", "w") do |file|
|
@@ -55,7 +63,7 @@ namespace :test do
|
|
55
63
|
dir = File.expand_path("../test", __FILE__)
|
56
64
|
Dir["#{dir}/*_test.rb"].each do |test|
|
57
65
|
puts "Running #{test}:"
|
58
|
-
puts %x{ruby #{test}}
|
66
|
+
puts %x{ruby -Ilib -Itest #{test}}
|
59
67
|
end
|
60
68
|
end
|
61
69
|
end
|
@@ -63,8 +71,8 @@ end
|
|
63
71
|
namespace :db do
|
64
72
|
|
65
73
|
desc "Create the database"
|
66
|
-
task :create do
|
67
|
-
require
|
74
|
+
task :create => :load_path do
|
75
|
+
require "helper"
|
68
76
|
driver = FriendlyId::Test::Database.driver
|
69
77
|
config = FriendlyId::Test::Database.config[driver]
|
70
78
|
commands = {
|
@@ -75,8 +83,8 @@ namespace :db do
|
|
75
83
|
end
|
76
84
|
|
77
85
|
desc "Create the database"
|
78
|
-
task :drop do
|
79
|
-
require
|
86
|
+
task :drop => :load_path do
|
87
|
+
require "helper"
|
80
88
|
driver = FriendlyId::Test::Database.driver
|
81
89
|
config = FriendlyId::Test::Database.config[driver]
|
82
90
|
commands = {
|
@@ -87,8 +95,8 @@ namespace :db do
|
|
87
95
|
end
|
88
96
|
|
89
97
|
desc "Set up the database schema"
|
90
|
-
task :up do
|
91
|
-
require
|
98
|
+
task :up => :load_path do
|
99
|
+
require "helper"
|
92
100
|
FriendlyId::Test::Schema.up
|
93
101
|
end
|
94
102
|
|
data/lib/friendly_id.rb
CHANGED
@@ -45,7 +45,7 @@ with numeric ids:
|
|
45
45
|
module FriendlyId
|
46
46
|
|
47
47
|
# The current version.
|
48
|
-
VERSION = "4.0.
|
48
|
+
VERSION = "4.0.3"
|
49
49
|
|
50
50
|
@mutex = Mutex.new
|
51
51
|
|
@@ -90,6 +90,11 @@ module FriendlyId
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
# Allow developers to `include` FriendlyId or `extend` it.
|
94
|
+
def self.included(model_class)
|
95
|
+
model_class.extend self
|
96
|
+
end
|
97
|
+
|
93
98
|
# Set global defaults for all models using FriendlyId.
|
94
99
|
#
|
95
100
|
# The default defaults are to use the +:reserved+ module and nothing else.
|
data/lib/friendly_id/base.rb
CHANGED
@@ -3,12 +3,13 @@ module FriendlyId
|
|
3
3
|
|
4
4
|
== Setting Up FriendlyId in Your Model
|
5
5
|
|
6
|
-
To use FriendlyId in your ActiveRecord models, you must first extend
|
7
|
-
FriendlyId module, then invoke the
|
8
|
-
method to configure your desired
|
6
|
+
To use FriendlyId in your ActiveRecord models, you must first either extend or
|
7
|
+
include the FriendlyId module (it makes no difference), then invoke the
|
8
|
+
{FriendlyId::Base#friendly_id friendly_id} method to configure your desired
|
9
|
+
options:
|
9
10
|
|
10
11
|
class Foo < ActiveRecord::Base
|
11
|
-
|
12
|
+
include FriendlyId
|
12
13
|
friendly_id :bar, :use => [:slugged, :simple_i18n]
|
13
14
|
end
|
14
15
|
|
@@ -129,10 +130,34 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
129
130
|
# end
|
130
131
|
# end
|
131
132
|
#
|
132
|
-
#
|
133
|
-
#
|
133
|
+
# === Including Your Own Modules
|
134
|
+
#
|
135
|
+
# Because :use can accept a name or a Module, {FriendlyId.defaults defaults}
|
136
|
+
# can be a convenient place to set up behavior common to all classes using
|
137
|
+
# FriendlyId. You can include any module, or more conveniently, define one
|
138
|
+
# on-the-fly. For example, let's say you want to make
|
139
|
+
# Babosa[http://github.com/norman/babosa] the default slugging library in
|
140
|
+
# place of Active Support, and transliterate all slugs from Russian Cyrillic
|
141
|
+
# to ASCII:
|
142
|
+
#
|
143
|
+
# require "babosa"
|
144
|
+
#
|
145
|
+
# FriendlyId.defaults do |config|
|
146
|
+
# config.base = :name
|
147
|
+
# config.use :slugged
|
148
|
+
# config.use Module.new {
|
149
|
+
# def normalize_friendly_id(text)
|
150
|
+
# text.to_slug.normalize(:transliterations => [:russian, :latin])
|
151
|
+
# end
|
152
|
+
# }
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
#
|
156
|
+
# @option options [Symbol,Module] :use The addon or name of an addon to use.
|
157
|
+
# By default, FriendlyId provides {FriendlyId::Slugged :slugged},
|
134
158
|
# {FriendlyId::History :history}, {FriendlyId::Reserved :reserved}, and
|
135
|
-
# {FriendlyId::Scoped :scoped}
|
159
|
+
# {FriendlyId::Scoped :scoped}, {FriendlyId::SimpleI18n :simple_i18n},
|
160
|
+
# and {FriendlyId::Globalize :globalize}.
|
136
161
|
#
|
137
162
|
# @option options [Array] :reserved_words Available when using +:reserved+,
|
138
163
|
# which is loaded by default. Sets an array of words banned for use as
|
@@ -161,21 +186,24 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
161
186
|
#
|
162
187
|
# @yieldparam config The model class's {FriendlyId::Configuration friendly_id_config}.
|
163
188
|
def friendly_id(base = nil, options = {}, &block)
|
164
|
-
yield
|
165
|
-
|
166
|
-
|
189
|
+
yield friendly_id_config if block_given?
|
190
|
+
friendly_id_config.use options.delete :use
|
191
|
+
friendly_id_config.send :set, base ? options.merge(:base => base) : options
|
167
192
|
before_save {|rec| rec.instance_eval {@current_friendly_id = friendly_id}}
|
168
193
|
include Model
|
169
194
|
end
|
170
195
|
|
171
196
|
# Returns the model class's {FriendlyId::Configuration friendly_id_config}.
|
172
197
|
# @note In the case of Single Table Inheritance (STI), this method will
|
173
|
-
# duplicate the parent class's FriendlyId::Configuration
|
174
|
-
# access. If you're concerned about thread safety, then be sure
|
175
|
-
# {#friendly_id} in your class for each model.
|
198
|
+
# duplicate the parent class's FriendlyId::Configuration and relation class
|
199
|
+
# on first access. If you're concerned about thread safety, then be sure
|
200
|
+
# to invoke {#friendly_id} in your class for each model.
|
176
201
|
def friendly_id_config
|
177
202
|
@friendly_id_config or begin
|
178
|
-
|
203
|
+
@friendly_id_config = base_class.friendly_id_config.dup.tap do |config|
|
204
|
+
config.model_class = self
|
205
|
+
@relation_class = base_class.send(:relation_class)
|
206
|
+
end
|
179
207
|
end
|
180
208
|
end
|
181
209
|
|
@@ -32,7 +32,7 @@ module FriendlyId
|
|
32
32
|
|
33
33
|
# The model class that this configuration belongs to.
|
34
34
|
# @return ActiveRecord::Base
|
35
|
-
|
35
|
+
attr_accessor :model_class
|
36
36
|
|
37
37
|
def initialize(model_class, values = nil)
|
38
38
|
@model_class = model_class
|
@@ -51,13 +51,14 @@ module FriendlyId
|
|
51
51
|
# extend FriendlyId
|
52
52
|
# friendly_id :name, :use => :slugged
|
53
53
|
# end
|
54
|
-
# @param [#to_s] *modules Arguments should be
|
55
|
-
# correspond with the name of a module inside the FriendlyId
|
56
|
-
# default FriendlyId provides +:slugged+, +:history+,
|
54
|
+
# @param [#to_s,Module] *modules Arguments should be Modules, or symbols or
|
55
|
+
# strings that correspond with the name of a module inside the FriendlyId
|
56
|
+
# namespace. By default FriendlyId provides +:slugged+, +:history+,
|
57
|
+
# +:simple_i18n+, +:globalize+, and +:scoped+.
|
57
58
|
def use(*modules)
|
58
|
-
modules.to_a.flatten.compact.map do |
|
59
|
-
mod = FriendlyId.const_get(
|
60
|
-
model_class.send(:include, mod)
|
59
|
+
modules.to_a.flatten.compact.map do |object|
|
60
|
+
mod = object.kind_of?(Module) ? object : FriendlyId.const_get(object.to_s.classify)
|
61
|
+
model_class.send(:include, mod)
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
@@ -4,13 +4,17 @@ module FriendlyId
|
|
4
4
|
|
5
5
|
=begin
|
6
6
|
|
7
|
-
==
|
7
|
+
== Translating Slugs Using Globalize
|
8
8
|
|
9
|
-
The {FriendlyId::Globalize Globalize} module
|
10
|
-
Globalize
|
9
|
+
The {FriendlyId::Globalize Globalize} module lets you use
|
10
|
+
Globalize[https://github.com/svenfuchs/globalize3] to translate slugs. This
|
11
|
+
module is most suitable for applications that need to be localized to many
|
12
|
+
languages. If your application only needs to be localized to one or two
|
13
|
+
languages, you may wish to consider the {FriendlyId::SimpleI18n SimpleI18n}
|
14
|
+
module.
|
11
15
|
|
12
16
|
In order to use this module, your model must have a slug column and set the
|
13
|
-
field +slug+ translable with Globalize:
|
17
|
+
field +slug+ as translable with Globalize:
|
14
18
|
|
15
19
|
class Post < ActiveRecord::Base
|
16
20
|
translates :title, :slug
|
@@ -20,7 +24,7 @@ field +slug+ translable with Globalize:
|
|
20
24
|
|
21
25
|
=== Finds
|
22
26
|
|
23
|
-
Finds will take
|
27
|
+
Finds will take the current locale into consideration:
|
24
28
|
|
25
29
|
I18n.locale = :it
|
26
30
|
Post.find("guerre-stellari")
|
@@ -40,8 +44,8 @@ When new records are created, the slug is generated for the current locale only.
|
|
40
44
|
|
41
45
|
=== Translating Slugs
|
42
46
|
|
43
|
-
To translate an existing record's friendly_id, simply change locale and
|
44
|
-
+slug+ field:
|
47
|
+
To translate an existing record's friendly_id, simply change the locale and
|
48
|
+
assign a value to the +slug+ field:
|
45
49
|
|
46
50
|
I18n.with_locale(:it) do
|
47
51
|
post.slug = "guerre-stellari"
|
data/lib/friendly_id/history.rb
CHANGED
@@ -74,12 +74,15 @@ method.
|
|
74
74
|
private
|
75
75
|
|
76
76
|
def create_slug
|
77
|
+
return unless friendly_id
|
77
78
|
return if slugs.first.try(:slug) == friendly_id
|
78
79
|
# Allow reversion back to a previously used slug
|
79
80
|
relation = slugs.where(:slug => friendly_id)
|
80
81
|
result = relation.select("id").lock(true).all
|
81
82
|
relation.delete_all unless result.empty?
|
82
|
-
slugs.create!
|
83
|
+
slugs.create! do |record|
|
84
|
+
record.slug = friendly_id
|
85
|
+
end
|
83
86
|
end
|
84
87
|
|
85
88
|
# Adds a finder that explictly uses slugs from the slug table.
|
@@ -106,7 +109,7 @@ method.
|
|
106
109
|
# Accepts a slug, and yields a corresponding sluggable_id into the block.
|
107
110
|
def with_old_friendly_id(slug, &block)
|
108
111
|
sql = "SELECT sluggable_id FROM #{Slug.quoted_table_name} WHERE sluggable_type = %s AND slug = %s"
|
109
|
-
sql = sql % [@klass.base_class.
|
112
|
+
sql = sql % [@klass.base_class.to_s, slug].map {|x| connection.quote(x)}
|
110
113
|
sluggable_id = connection.select_values(sql).first
|
111
114
|
yield sluggable_id if sluggable_id
|
112
115
|
end
|
@@ -117,17 +120,14 @@ method.
|
|
117
120
|
module SlugGenerator
|
118
121
|
|
119
122
|
private
|
120
|
-
def last_in_sequence
|
121
|
-
@_last_in_sequence ||= extract_sequence_from_slug(conflict.slug)
|
122
|
-
end
|
123
123
|
|
124
124
|
def conflicts
|
125
|
-
sluggable_class = friendly_id_config.model_class
|
125
|
+
sluggable_class = friendly_id_config.model_class.base_class
|
126
126
|
pkey = sluggable_class.primary_key
|
127
127
|
value = sluggable.send pkey
|
128
128
|
|
129
129
|
scope = Slug.where("slug = ? OR slug LIKE ?", normalized, wildcard)
|
130
|
-
scope = scope.where(:sluggable_type => sluggable_class.
|
130
|
+
scope = scope.where(:sluggable_type => sluggable_class.to_s)
|
131
131
|
scope = scope.where("sluggable_id <> ?", value) unless sluggable.new_record?
|
132
132
|
scope.order("LENGTH(slug) DESC, slug DESC")
|
133
133
|
end
|
@@ -4,7 +4,7 @@ module FriendlyId
|
|
4
4
|
|
5
5
|
=begin
|
6
6
|
|
7
|
-
== Simple I18n
|
7
|
+
== Translating Slugs Using Simple I18n
|
8
8
|
|
9
9
|
The {FriendlyId::SimpleI18n SimpleI18n} module adds very basic i18n support to
|
10
10
|
FriendlyId.
|
@@ -12,8 +12,12 @@ FriendlyId.
|
|
12
12
|
In order to use this module, your model must have a slug column for each locale.
|
13
13
|
By default FriendlyId looks for columns named, for example, "slug_en",
|
14
14
|
"slug_es", etc. The first part of the name can be configured by passing the
|
15
|
-
+:slug_column+ option if you choose. Note that
|
16
|
-
|
15
|
+
+:slug_column+ option if you choose. Note that the column for the default locale
|
16
|
+
must also include the locale in its name.
|
17
|
+
|
18
|
+
This module is most suitable to applications that need to support few locales.
|
19
|
+
If you need to support two or more locales, you may wish to use the
|
20
|
+
{FriendlyId::Globalize Globalize} module instead.
|
17
21
|
|
18
22
|
=== Example migration
|
19
23
|
|
data/lib/friendly_id/slug.rb
CHANGED
@@ -51,11 +51,14 @@ module FriendlyId
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def conflicts
|
54
|
-
sluggable_class = friendly_id_config.model_class
|
54
|
+
sluggable_class = friendly_id_config.model_class.base_class
|
55
55
|
|
56
56
|
pkey = sluggable_class.primary_key
|
57
57
|
value = sluggable.send pkey
|
58
|
-
|
58
|
+
base = "#{column} = ? OR #{column} LIKE ?"
|
59
|
+
# Awful hack for SQLite3, which does not pick up '\' as the escape character without this.
|
60
|
+
base << "ESCAPE '\\'" if sluggable.connection.adapter_name =~ /sqlite/i
|
61
|
+
scope = sluggable_class.unscoped.where(base, normalized, wildcard)
|
59
62
|
scope = scope.where("#{pkey} <> ?", value) unless sluggable.new_record?
|
60
63
|
scope = scope.order("LENGTH(#{column}) DESC, #{column} DESC")
|
61
64
|
end
|
data/test/base_test.rb
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
class CoreTest < MiniTest::Unit::TestCase
|
4
4
|
include FriendlyId::Test
|
5
5
|
|
6
|
+
test "friendly_id can be added using 'extend'" do
|
7
|
+
klass = Class.new(ActiveRecord::Base) do
|
8
|
+
extend FriendlyId
|
9
|
+
end
|
10
|
+
assert klass.respond_to? :friendly_id
|
11
|
+
end
|
12
|
+
|
13
|
+
test "friendly_id can be added using 'include'" do
|
14
|
+
klass = Class.new(ActiveRecord::Base) do
|
15
|
+
include FriendlyId
|
16
|
+
end
|
17
|
+
assert klass.respond_to? :friendly_id
|
18
|
+
end
|
19
|
+
|
6
20
|
test "friendly_id should accept a base and a hash" do
|
7
21
|
klass = Class.new(ActiveRecord::Base) do
|
8
22
|
self.abstract_class = true
|
data/test/configuration_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
class ConfigurationTest < MiniTest::Unit::TestCase
|
4
4
|
|
@@ -26,4 +26,23 @@ class ConfigurationTest < MiniTest::Unit::TestCase
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
test "#use should accept a name that resolves to a module" do
|
30
|
+
refute @model_class < FriendlyId::Slugged
|
31
|
+
@model_class.class_eval do
|
32
|
+
extend FriendlyId
|
33
|
+
friendly_id :hello, :use => :slugged
|
34
|
+
end
|
35
|
+
assert @model_class < FriendlyId::Slugged
|
36
|
+
end
|
37
|
+
|
38
|
+
test "#use should accept a module" do
|
39
|
+
my_module = Module.new
|
40
|
+
refute @model_class < my_module
|
41
|
+
@model_class.class_eval do
|
42
|
+
extend FriendlyId
|
43
|
+
friendly_id :hello, :use => my_module
|
44
|
+
end
|
45
|
+
assert @model_class < my_module
|
46
|
+
end
|
47
|
+
|
29
48
|
end
|
data/test/core_test.rb
CHANGED
data/test/generator_test.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/history_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
class Manual < ActiveRecord::Base
|
4
4
|
extend FriendlyId
|
@@ -133,3 +133,17 @@ class HistoryTest < MiniTest::Unit::TestCase
|
|
133
133
|
end
|
134
134
|
|
135
135
|
end
|
136
|
+
|
137
|
+
class HistoryTestWithSti < HistoryTest
|
138
|
+
class Journalist < ActiveRecord::Base
|
139
|
+
extend FriendlyId
|
140
|
+
friendly_id :name, :use => [:slugged, :history]
|
141
|
+
end
|
142
|
+
|
143
|
+
class Editorialist < Journalist
|
144
|
+
end
|
145
|
+
|
146
|
+
def model_class
|
147
|
+
Editorialist
|
148
|
+
end
|
149
|
+
end
|
data/test/i18n_test.rb
CHANGED
data/test/object_utils_test.rb
CHANGED
data/test/reserved_test.rb
CHANGED
data/test/schema.rb
CHANGED
@@ -32,6 +32,7 @@ module FriendlyId
|
|
32
32
|
add_column :novels, :novelist_id, :integer
|
33
33
|
add_column :novels, :publisher_id, :integer
|
34
34
|
remove_index :novels, :slug
|
35
|
+
add_index :novels, [:slug, :publisher_id, :novelist_id], :unique => true
|
35
36
|
|
36
37
|
# This will be used to test column name quoting
|
37
38
|
add_column :journalists, "strange name", :string
|
data/test/scoped_test.rb
CHANGED
data/test/shared.rb
CHANGED
data/test/slugged_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
class Journalist < ActiveRecord::Base
|
4
4
|
extend FriendlyId
|
@@ -202,6 +202,26 @@ class SluggedRegressionsTest < MiniTest::Unit::TestCase
|
|
202
202
|
end
|
203
203
|
end
|
204
204
|
|
205
|
+
class UnderscoreAsSequenceSeparatorRegressionTest < MiniTest::Unit::TestCase
|
206
|
+
include FriendlyId::Test
|
207
|
+
|
208
|
+
class Manual < ActiveRecord::Base
|
209
|
+
extend FriendlyId
|
210
|
+
friendly_id :name, :use => :slugged, :sequence_separator => "_"
|
211
|
+
end
|
212
|
+
|
213
|
+
test "should not create duplicate slugs" do
|
214
|
+
3.times do
|
215
|
+
begin
|
216
|
+
assert Manual.create! :name => "foo"
|
217
|
+
rescue
|
218
|
+
flunk "Tried to insert duplicate slug"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
205
225
|
# https://github.com/norman/friendly_id/issues/148
|
206
226
|
class FailedValidationAfterUpdateRegressionTest < MiniTest::Unit::TestCase
|
207
227
|
include FriendlyId::Test
|
data/test/sti_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
class StiTest < MiniTest::Unit::TestCase
|
4
4
|
|
@@ -30,6 +30,10 @@ class StiTest < MiniTest::Unit::TestCase
|
|
30
30
|
assert_equal :bar, klass.friendly_id_config.slug_column
|
31
31
|
end
|
32
32
|
|
33
|
+
test "the configuration's model_class should be the class, not the base_class" do
|
34
|
+
assert_equal model_class, model_class.friendly_id_config.model_class
|
35
|
+
end
|
36
|
+
|
33
37
|
test "friendly_id should accept a block with single table inheritance" do
|
34
38
|
abstract_klass = Class.new(ActiveRecord::Base) do
|
35
39
|
def self.table_exists?; false end
|
@@ -47,11 +51,27 @@ class StiTest < MiniTest::Unit::TestCase
|
|
47
51
|
end
|
48
52
|
|
49
53
|
test "friendly_id slugs should not clash with eachother" do
|
50
|
-
|
51
|
-
|
54
|
+
transaction do
|
55
|
+
journalist = model_class.base_class.create! :name => 'foo bar'
|
56
|
+
editoralist = model_class.create! :name => 'foo bar'
|
52
57
|
|
53
|
-
|
54
|
-
|
58
|
+
assert_equal 'foo-bar', journalist.slug
|
59
|
+
assert_equal 'foo-bar--2', editoralist.slug
|
60
|
+
end
|
55
61
|
end
|
56
62
|
|
57
63
|
end
|
64
|
+
|
65
|
+
class StiTestWithHistory < StiTest
|
66
|
+
class Journalist < ActiveRecord::Base
|
67
|
+
extend FriendlyId
|
68
|
+
friendly_id :name, :use => [:slugged, :history]
|
69
|
+
end
|
70
|
+
|
71
|
+
class Editorialist < Journalist
|
72
|
+
end
|
73
|
+
|
74
|
+
def model_class
|
75
|
+
Editorialist
|
76
|
+
end
|
77
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friendly_id
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
16
|
-
requirement: &
|
16
|
+
requirement: &70135168764860 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.2.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70135168764860
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activerecord
|
27
|
-
requirement: &
|
27
|
+
requirement: &70135168764100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 3.2.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70135168764100
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: minitest
|
38
|
-
requirement: &
|
38
|
+
requirement: &70135168763460 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70135168763460
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: mocha
|
49
|
-
requirement: &
|
49
|
+
requirement: &70135171790060 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70135171790060
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: maruku
|
60
|
-
requirement: &
|
60
|
+
requirement: &70135171789640 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70135171789640
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
|
-
requirement: &
|
71
|
+
requirement: &70135171789220 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70135171789220
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: i18n
|
82
|
-
requirement: &
|
82
|
+
requirement: &70135171788800 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70135171788800
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: ffaker
|
93
|
-
requirement: &
|
93
|
+
requirement: &70135171788380 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70135171788380
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: simplecov
|
104
|
-
requirement: &
|
104
|
+
requirement: &70135171787960 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70135171787960
|
113
113
|
description: ! 'FriendlyId is the "Swiss Army bulldozer" of slugging and permalink
|
114
114
|
plugins for
|
115
115
|
|