norman-friendly_id 2.0.3 → 2.0.4
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/History.txt +5 -0
- data/Manifest.txt +5 -0
- data/README.rdoc +34 -5
- data/Rakefile +8 -0
- data/friendly_id.gemspec +4 -4
- data/lib/friendly_id/sluggable_class_methods.rb +1 -1
- data/lib/friendly_id/sluggable_instance_methods.rb +10 -6
- data/lib/friendly_id/version.rb +1 -1
- data/lib/friendly_id.rb +8 -4
- data/test/custom_slug_normalizer_test.rb +35 -0
- data/test/models/book.rb +2 -0
- data/test/models/novel.rb +3 -0
- data/test/models/thing.rb +6 -0
- data/test/schema.rb +7 -3
- data/test/sti_test.rb +48 -0
- data/test/test_helper.rb +1 -0
- metadata +9 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
|
@@ -20,13 +20,18 @@ lib/friendly_id/sluggable_instance_methods.rb
|
|
|
20
20
|
lib/friendly_id/version.rb
|
|
21
21
|
lib/tasks/friendly_id.rake
|
|
22
22
|
lib/tasks/friendly_id.rb
|
|
23
|
+
test/custom_slug_normalizer_test.rb
|
|
24
|
+
test/models/book.rb
|
|
23
25
|
test/models/country.rb
|
|
26
|
+
test/models/novel.rb
|
|
24
27
|
test/models/person.rb
|
|
25
28
|
test/models/post.rb
|
|
29
|
+
test/models/thing.rb
|
|
26
30
|
test/models/user.rb
|
|
27
31
|
test/non_slugged_test.rb
|
|
28
32
|
test/schema.rb
|
|
29
33
|
test/scoped_model_test.rb
|
|
30
34
|
test/slug_test.rb
|
|
31
35
|
test/slugged_model_test.rb
|
|
36
|
+
test/sti_test.rb
|
|
32
37
|
test/test_helper.rb
|
data/README.rdoc
CHANGED
|
@@ -136,9 +136,13 @@ Here's how to do it:
|
|
|
136
136
|
|
|
137
137
|
class Restaurant < ActiveRecord::Base
|
|
138
138
|
belongs_to :city
|
|
139
|
-
has_friendly_id :name, :use_slug => true, :reserved => ["
|
|
139
|
+
has_friendly_id :name, :use_slug => true, :reserved => ["my", "values"]
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
+
As of FriendlyId version 2.0.2, "new" and "index" are reseved by default. When
|
|
143
|
+
you attempt to store a reserved value, FriendlyId raises a
|
|
144
|
+
FriendlyId::SlugGenerationError.
|
|
145
|
+
|
|
142
146
|
|
|
143
147
|
=== Scoped Slugs
|
|
144
148
|
|
|
@@ -208,6 +212,33 @@ that uses a non-Roman writing system, your feedback would be most welcome.
|
|
|
208
212
|
@post.friendly_id # "友好编号在中国"
|
|
209
213
|
@post2 = Post.create(:title => "友好编号在中国")
|
|
210
214
|
@post2.friendly_id # "友好编号在中国--2"
|
|
215
|
+
|
|
216
|
+
=== Custom Slug Generation
|
|
217
|
+
|
|
218
|
+
While FriendlyId's slug generation options work for most people, you may need
|
|
219
|
+
something else. As of version 2.0.4 you can pass in your own custom slug
|
|
220
|
+
generation block:
|
|
221
|
+
|
|
222
|
+
require 'stringex'
|
|
223
|
+
class Post < ActiveRecord::Base
|
|
224
|
+
has_friendly_id :title, :use_slug => true do |text|
|
|
225
|
+
# User stringex to generate the friendly_id rather than the baked-in methods
|
|
226
|
+
text.to_url
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
...
|
|
231
|
+
|
|
232
|
+
@post = Post.create(:title => "tell your readers 你好")
|
|
233
|
+
@post.friendly_id # "tell-your-readers-ni-hao"
|
|
234
|
+
|
|
235
|
+
FriendlyId will still respect your settings for max length and reserved words,
|
|
236
|
+
but will use your block rather than the baked-in methods to normalize the
|
|
237
|
+
friendly_id text.
|
|
238
|
+
|
|
239
|
+
(As an aside, the stringex[http://github.com/rsl/stringex/tree/master] library
|
|
240
|
+
provides some very cool slugging functionality and is a great option for
|
|
241
|
+
apps using FriendlyId in either English or Chinese. Definitely check it out.)
|
|
211
242
|
|
|
212
243
|
== Getting it
|
|
213
244
|
|
|
@@ -228,7 +259,7 @@ which FriendlyId depends on:
|
|
|
228
259
|
|
|
229
260
|
== Setting it up
|
|
230
261
|
|
|
231
|
-
FriendlyId currently works with Rails 2.0.0
|
|
262
|
+
FriendlyId currently works with Rails 2.0.0 - 2.3.0. Here's how to set it up.
|
|
232
263
|
|
|
233
264
|
1) Install the Gem:
|
|
234
265
|
|
|
@@ -267,7 +298,7 @@ rake:friendly_id:remove_old_slugs MODEL=MyModelName DAYS=60
|
|
|
267
298
|
|
|
268
299
|
== Upgrading from an older version
|
|
269
300
|
|
|
270
|
-
If you installed an older version of FriendlyId and want to upgrade to 2.0,
|
|
301
|
+
If you installed an older version of FriendlyId and want to upgrade to 2.0.x,
|
|
271
302
|
follow these steps:
|
|
272
303
|
|
|
273
304
|
==== Install the friendly_id Gem:
|
|
@@ -297,8 +328,6 @@ Add this to the bottom of environment.rb:
|
|
|
297
328
|
./script generate friendly_id_20_upgrade
|
|
298
329
|
rake db:migrate
|
|
299
330
|
|
|
300
|
-
That's it!
|
|
301
|
-
|
|
302
331
|
== Hacking FriendlyId:
|
|
303
332
|
|
|
304
333
|
FriendlyId is {hosted on Github}[git://github.com/norman/friendly_id.git], and
|
data/Rakefile
CHANGED
|
@@ -42,3 +42,11 @@ def run_coverage(files)
|
|
|
42
42
|
puts cmd
|
|
43
43
|
sh cmd
|
|
44
44
|
end
|
|
45
|
+
|
|
46
|
+
desc 'Publish RDoc to RubyForge.'
|
|
47
|
+
task :publish_docs => [:clean, :docs] do
|
|
48
|
+
host = "compay@rubyforge.org"
|
|
49
|
+
remote_dir = "/var/www/gforge-projects/friendly-id"
|
|
50
|
+
local_dir = 'doc'
|
|
51
|
+
sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
|
|
52
|
+
end
|
data/friendly_id.gemspec
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = %q{friendly_id}
|
|
5
|
-
s.version = "2.0.
|
|
5
|
+
s.version = "2.0.4"
|
|
6
6
|
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
8
|
s.authors = ["Norman Clarke", "Adrian Mugnolo", "Emilio Tagua"]
|
|
9
|
-
s.date = %q{2009-02-
|
|
9
|
+
s.date = %q{2009-02-12}
|
|
10
10
|
s.description = %q{A comprehensive slugging and pretty-URL plugin for ActiveRecord.}
|
|
11
11
|
s.email = ["norman@randomba.org", "adrian@randomba.org", "miloops@gmail.com"]
|
|
12
12
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
|
13
|
-
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "config/website.yml", "friendly_id.gemspec", "generators/friendly_id/friendly_id_generator.rb", "generators/friendly_id/templates/create_slugs.rb", "generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb", "generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb", "init.rb", "lib/friendly_id.rb", "lib/friendly_id/helpers.rb", "lib/friendly_id/non_sluggable_class_methods.rb", "lib/friendly_id/non_sluggable_instance_methods.rb", "lib/friendly_id/slug.rb", "lib/friendly_id/sluggable_class_methods.rb", "lib/friendly_id/sluggable_instance_methods.rb", "lib/friendly_id/version.rb", "lib/tasks/friendly_id.rake", "lib/tasks/friendly_id.rb", "test/models/country.rb", "test/models/person.rb", "test/models/post.rb", "test/models/user.rb", "test/non_slugged_test.rb", "test/schema.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/slugged_model_test.rb", "test/test_helper.rb"]
|
|
13
|
+
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "config/website.yml", "friendly_id.gemspec", "generators/friendly_id/friendly_id_generator.rb", "generators/friendly_id/templates/create_slugs.rb", "generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb", "generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb", "init.rb", "lib/friendly_id.rb", "lib/friendly_id/helpers.rb", "lib/friendly_id/non_sluggable_class_methods.rb", "lib/friendly_id/non_sluggable_instance_methods.rb", "lib/friendly_id/slug.rb", "lib/friendly_id/sluggable_class_methods.rb", "lib/friendly_id/sluggable_instance_methods.rb", "lib/friendly_id/version.rb", "lib/tasks/friendly_id.rake", "lib/tasks/friendly_id.rb", "test/custom_slug_normalizer_test.rb", "test/models/book.rb", "test/models/country.rb", "test/models/novel.rb", "test/models/person.rb", "test/models/post.rb", "test/models/thing.rb", "test/models/user.rb", "test/non_slugged_test.rb", "test/schema.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/slugged_model_test.rb", "test/sti_test.rb", "test/test_helper.rb"]
|
|
14
14
|
s.has_rdoc = true
|
|
15
15
|
s.homepage = %q{http://friendly-id.rubyforge.org/}
|
|
16
16
|
s.rdoc_options = ["--main", "README.rdoc"]
|
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
|
18
18
|
s.rubyforge_project = %q{friendly-id}
|
|
19
19
|
s.rubygems_version = %q{1.3.1}
|
|
20
20
|
s.summary = %q{A comprehensive slugging and pretty-URL plugin for ActiveRecord.}
|
|
21
|
-
s.test_files = ["test/non_slugged_test.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/slugged_model_test.rb"]
|
|
21
|
+
s.test_files = ["test/custom_slug_normalizer_test.rb", "test/non_slugged_test.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/slugged_model_test.rb", "test/sti_test.rb"]
|
|
22
22
|
|
|
23
23
|
if s.respond_to? :specification_version then
|
|
24
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
@@ -56,13 +56,17 @@ module FriendlyId::SluggableInstanceMethods
|
|
|
56
56
|
# Get the processed string used as the basis of the friendly id.
|
|
57
57
|
def slug_text
|
|
58
58
|
base = send friendly_id_options[:column]
|
|
59
|
-
if self.
|
|
60
|
-
base =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
if self.slug_normalizer_block
|
|
60
|
+
base = self.slug_normalizer_block.call(base)
|
|
61
|
+
else
|
|
62
|
+
if self.friendly_id_options[:strip_diacritics]
|
|
63
|
+
base = Slug::strip_diacritics(base)
|
|
64
|
+
end
|
|
65
|
+
if self.friendly_id_options[:strip_non_ascii]
|
|
66
|
+
base = Slug::strip_non_ascii(base)
|
|
67
|
+
end
|
|
68
|
+
base = Slug::normalize(base)
|
|
64
69
|
end
|
|
65
|
-
base = Slug::normalize(base)
|
|
66
70
|
|
|
67
71
|
if base.length > friendly_id_options[:max_length]
|
|
68
72
|
base = base[0...friendly_id_options[:max_length]]
|
data/lib/friendly_id/version.rb
CHANGED
data/lib/friendly_id.rb
CHANGED
|
@@ -14,7 +14,7 @@ module FriendlyId
|
|
|
14
14
|
:strip_diacritics => false,
|
|
15
15
|
:strip_non_ascii => false,
|
|
16
16
|
:use_slug => false }.freeze
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
# Valid keys for has_friendly_id options.
|
|
19
19
|
VALID_FRIENDLY_ID_KEYS = [
|
|
20
20
|
:max_length,
|
|
@@ -24,7 +24,7 @@ module FriendlyId
|
|
|
24
24
|
:strip_diacritics,
|
|
25
25
|
:strip_non_ascii,
|
|
26
26
|
:use_slug ].freeze
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
# This error is raised when it's not possible to generate a unique slug.
|
|
29
29
|
class SlugGenerationError < StandardError ; end
|
|
30
30
|
|
|
@@ -42,11 +42,12 @@ module FriendlyId
|
|
|
42
42
|
# * <tt>:strip_non_ascii</tt> - Defaults to false. If true, it will all non-ascii ([^a-z0-9]) characters.
|
|
43
43
|
# * <tt>:reserved</tt> - Array of words that are reserved and can't be used as friendly_id's. For sluggable models, if such a word is used, it will be treated the same as if that slug was already taken (numeric extension will be appended). Defaults to ["new", "index"].
|
|
44
44
|
# * <tt>:reserved_message</tt> - The validation message that will be shown when a reserved word is used as a frindly_id. Defaults to '"%s" is reserved'.
|
|
45
|
-
def has_friendly_id(column, options = {})
|
|
45
|
+
def has_friendly_id(column, options = {}, &block)
|
|
46
46
|
options.assert_valid_keys VALID_FRIENDLY_ID_KEYS
|
|
47
47
|
options = DEFAULT_FRIENDLY_ID_OPTIONS.merge(options).merge(:column => column)
|
|
48
48
|
write_inheritable_attribute :friendly_id_options, options
|
|
49
49
|
class_inheritable_accessor :friendly_id_options
|
|
50
|
+
class_inheritable_reader :slug_normalizer_block
|
|
50
51
|
|
|
51
52
|
if options[:use_slug]
|
|
52
53
|
has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
|
|
@@ -55,6 +56,9 @@ module FriendlyId
|
|
|
55
56
|
extend SluggableClassMethods
|
|
56
57
|
include SluggableInstanceMethods
|
|
57
58
|
before_save :set_slug
|
|
59
|
+
if block_given?
|
|
60
|
+
write_inheritable_attribute :slug_normalizer_block, block
|
|
61
|
+
end
|
|
58
62
|
else
|
|
59
63
|
require 'friendly_id/non_sluggable_class_methods'
|
|
60
64
|
require 'friendly_id/non_sluggable_instance_methods'
|
|
@@ -63,7 +67,7 @@ module FriendlyId
|
|
|
63
67
|
validate_on_create :validate_friendly_id
|
|
64
68
|
end
|
|
65
69
|
end
|
|
66
|
-
|
|
70
|
+
|
|
67
71
|
end
|
|
68
72
|
|
|
69
73
|
class << self
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.dirname(__FILE__) + '/test_helper'
|
|
4
|
+
|
|
5
|
+
class CustomSlugNormalizerTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
context "A slugged model using a custom slug generator" do
|
|
8
|
+
|
|
9
|
+
setup do
|
|
10
|
+
Thing.friendly_id_options = FriendlyId::DEFAULT_FRIENDLY_ID_OPTIONS.merge(:column => :name, :use_slug => true)
|
|
11
|
+
Thing.delete_all
|
|
12
|
+
Slug.delete_all
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
should "invoke the block code" do
|
|
16
|
+
@thing = Thing.create!(:name => "test")
|
|
17
|
+
assert_equal "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", @thing.friendly_id
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "respect the max_length option" do
|
|
21
|
+
Thing.friendly_id_options = Thing.friendly_id_options.merge(:max_length => 10)
|
|
22
|
+
@thing = Thing.create!(:name => "test")
|
|
23
|
+
assert_equal "a94a8fe5cc", @thing.friendly_id
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
should "respect the reserved option" do
|
|
27
|
+
Thing.friendly_id_options = Thing.friendly_id_options.merge(:reserved => ["a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"])
|
|
28
|
+
assert_raises FriendlyId::SlugGenerationError do
|
|
29
|
+
Thing.create!(:name => "test")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
data/test/models/book.rb
ADDED
data/test/schema.rb
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
ActiveRecord::Schema.define(:version => 1) do
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
create_table "books", :force => true do |t|
|
|
4
4
|
t.column "title", "string"
|
|
5
5
|
t.column "type", "text"
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
create_table "things", :force => true do |t|
|
|
9
|
+
t.column "name", "string"
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
create_table "posts", :force => true do |t|
|
|
9
13
|
t.column "title", "string"
|
|
10
14
|
t.column "content", "text"
|
|
@@ -18,12 +22,12 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
|
18
22
|
t.column "created_at", "datetime"
|
|
19
23
|
t.column "updated_at", "datetime"
|
|
20
24
|
end
|
|
21
|
-
|
|
25
|
+
|
|
22
26
|
create_table "people", :force => true do |t|
|
|
23
27
|
t.column "name", "string"
|
|
24
28
|
t.column "country_id", "integer"
|
|
25
29
|
end
|
|
26
|
-
|
|
30
|
+
|
|
27
31
|
create_table "countries", :force => true do |t|
|
|
28
32
|
t.column "name", "string"
|
|
29
33
|
end
|
data/test/sti_test.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require File.dirname(__FILE__) + '/test_helper'
|
|
4
|
+
|
|
5
|
+
class SluggedModelTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
context "A slugged model using single table inheritance" do
|
|
8
|
+
|
|
9
|
+
setup do
|
|
10
|
+
Novel.friendly_id_options = FriendlyId::DEFAULT_FRIENDLY_ID_OPTIONS.merge(:column => :title, :use_slug => true)
|
|
11
|
+
Novel.delete_all
|
|
12
|
+
Slug.delete_all
|
|
13
|
+
@novel = Novel.new :title => "Test novel"
|
|
14
|
+
@novel.save!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
should "have a slug" do
|
|
18
|
+
assert_not_nil @novel.slug
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "found by its friendly id" do
|
|
22
|
+
|
|
23
|
+
setup do
|
|
24
|
+
@novel = Novel.find(@novel.friendly_id)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
should "not indicate that it has a better id" do
|
|
28
|
+
assert !@novel.has_better_id?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
context "found by its numeric id" do
|
|
35
|
+
|
|
36
|
+
setup do
|
|
37
|
+
@novel = Novel.find(@novel.id)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
should "indicate that it has a better id" do
|
|
41
|
+
assert @novel.has_better_id?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: norman-friendly_id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Norman Clarke
|
|
@@ -11,7 +11,7 @@ autorequire:
|
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
13
|
|
|
14
|
-
date: 2009-02-
|
|
14
|
+
date: 2009-02-12 00:00:00 -08:00
|
|
15
15
|
default_executable:
|
|
16
16
|
dependencies:
|
|
17
17
|
- !ruby/object:Gem::Dependency
|
|
@@ -104,15 +104,20 @@ files:
|
|
|
104
104
|
- lib/friendly_id/version.rb
|
|
105
105
|
- lib/tasks/friendly_id.rake
|
|
106
106
|
- lib/tasks/friendly_id.rb
|
|
107
|
+
- test/custom_slug_normalizer_test.rb
|
|
108
|
+
- test/models/book.rb
|
|
107
109
|
- test/models/country.rb
|
|
110
|
+
- test/models/novel.rb
|
|
108
111
|
- test/models/person.rb
|
|
109
112
|
- test/models/post.rb
|
|
113
|
+
- test/models/thing.rb
|
|
110
114
|
- test/models/user.rb
|
|
111
115
|
- test/non_slugged_test.rb
|
|
112
116
|
- test/schema.rb
|
|
113
117
|
- test/scoped_model_test.rb
|
|
114
118
|
- test/slug_test.rb
|
|
115
119
|
- test/slugged_model_test.rb
|
|
120
|
+
- test/sti_test.rb
|
|
116
121
|
- test/test_helper.rb
|
|
117
122
|
has_rdoc: true
|
|
118
123
|
homepage: http://friendly-id.rubyforge.org/
|
|
@@ -142,7 +147,9 @@ signing_key:
|
|
|
142
147
|
specification_version: 2
|
|
143
148
|
summary: A comprehensive slugging and pretty-URL plugin for ActiveRecord.
|
|
144
149
|
test_files:
|
|
150
|
+
- test/custom_slug_normalizer_test.rb
|
|
145
151
|
- test/non_slugged_test.rb
|
|
146
152
|
- test/scoped_model_test.rb
|
|
147
153
|
- test/slug_test.rb
|
|
148
154
|
- test/slugged_model_test.rb
|
|
155
|
+
- test/sti_test.rb
|