friendly_id 4.0.2 → 4.0.3
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/.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
|
|