friendly_id 4.0.0.beta8 → 4.0.0.beta10
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +46 -6
- data/friendly_id.gemspec +1 -0
- data/gemfiles/Gemfile.rails-3.0.rb +1 -1
- data/gemfiles/Gemfile.rails-3.0.rb.lock +7 -7
- data/gemfiles/Gemfile.rails-3.1.rb +1 -1
- data/gemfiles/Gemfile.rails-3.1.rb.lock +12 -12
- data/lib/friendly_id.rb +2 -1
- data/lib/friendly_id/configuration.rb +1 -1
- data/lib/friendly_id/history.rb +2 -2
- data/lib/friendly_id/i18n.rb +85 -0
- data/lib/friendly_id/reserved.rb +2 -2
- data/lib/friendly_id/scoped.rb +1 -1
- data/lib/friendly_id/slug_sequencer.rb +7 -10
- data/lib/friendly_id/slugged.rb +4 -3
- data/test/compatibility/ancestry/ancestry_test.rb +34 -0
- data/test/i18n_test.rb +101 -0
- data/test/schema.rb +5 -0
- data/test/shared.rb +11 -0
- data/test/slugged_test.rb +34 -1
- metadata +32 -19
data/README.md
CHANGED
@@ -29,6 +29,12 @@ upgrading, please [read the
|
|
29
29
|
docs](http://norman.github.com/friendly_id/file.WhatsNew.html) to see what's
|
30
30
|
new.
|
31
31
|
|
32
|
+
## Docs
|
33
|
+
|
34
|
+
The current docs can always be found
|
35
|
+
[here](http://rubydoc.info/github/norman/friendly_id/master/frames).
|
36
|
+
|
37
|
+
|
32
38
|
## Rails Quickstart
|
33
39
|
|
34
40
|
gem install friendly_id
|
@@ -39,7 +45,6 @@ new.
|
|
39
45
|
|
40
46
|
gem "friendly_id", "~> 4.0.0.beta8"
|
41
47
|
|
42
|
-
|
43
48
|
rails generate scaffold user name:string slug:string
|
44
49
|
|
45
50
|
# edit db/migrate/*_create_users.rb
|
@@ -59,10 +64,11 @@ new.
|
|
59
64
|
|
60
65
|
GET http://localhost:3000/users/joe-schmoe
|
61
66
|
|
62
|
-
|
67
|
+
# If you're adding FriendlyId to an existing app and need
|
68
|
+
# to generate slugs for existing users, do this from the
|
69
|
+
# console, runner, or add a Rake task:
|
70
|
+
User.all.map(&:save)
|
63
71
|
|
64
|
-
The current docs can be found
|
65
|
-
[here](http://norman.github.com/friendly_id/)
|
66
72
|
|
67
73
|
## Benchmarks
|
68
74
|
|
@@ -79,22 +85,56 @@ If you have a bug to report, please include the following information:
|
|
79
85
|
|
80
86
|
* **Version information for FriendlyId, Rails and Ruby.**
|
81
87
|
* Stack trace and error message.
|
82
|
-
|
88
|
+
* Any snippets of relevant model, view or controller code that shows how you
|
83
89
|
are using FriendlyId.
|
84
90
|
|
85
91
|
If you are able to, it helps even more if you can fork FriendlyId on Github,
|
86
92
|
and add a test that reproduces the error you are experiencing.
|
87
93
|
|
88
|
-
## Credits
|
94
|
+
## Thanks and Credits
|
89
95
|
|
90
96
|
FriendlyId was originally created by Norman Clarke and Adrian Mugnolo, with
|
91
97
|
significant help early in its life by Emilio Tagua. I'm deeply gratful for the
|
92
98
|
generous contributions over the years from [many
|
93
99
|
volunteers](https://github.com/norman/friendly_id/contributors).
|
94
100
|
|
101
|
+
Part of the inspiration to rework FriendlyId came from Darcy Laycock's library
|
102
|
+
[Slugged](https://github.com/Sutto/slugged), which he was inspired to create
|
103
|
+
because of frustrations he experienced while using FriendlyId 3.x. Seeing a
|
104
|
+
smart programmer become frustrated with my code was enough of a kick in the
|
105
|
+
butt to make me want to improve this library significantly.
|
106
|
+
|
107
|
+
Many thanks to him for providing valid, real criticism while still being a cool
|
108
|
+
about it. I definitely recommend you check out his library if for some reason
|
109
|
+
FriendlyId doesn't do it for you.
|
110
|
+
|
111
|
+
Thanks also to Loren Segal and Nick Plante for YARD and the
|
112
|
+
[rubydoc.info](http://rubydoc.info/) website which FriendlyId uses for
|
113
|
+
documentation.
|
114
|
+
|
95
115
|
Lastly, FriendlyId uses [Travis](http://travis-ci.org/) for continuous
|
96
116
|
integration. It's an excellent, free service created by a whole bunch of [good
|
97
117
|
people](https://github.com/travis-ci) - if you're not already using it, you
|
98
118
|
should be!
|
99
119
|
|
120
|
+
## License
|
121
|
+
|
100
122
|
Copyright (c) 2008-2011 Norman Clarke, released under the MIT license.
|
123
|
+
|
124
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
125
|
+
this software and associated documentation files (the "Software"), to deal in
|
126
|
+
the Software without restriction, including without limitation the rights to
|
127
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
128
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
129
|
+
so, subject to the following conditions:
|
130
|
+
|
131
|
+
The above copyright notice and this permission notice shall be included in all
|
132
|
+
copies or substantial portions of the Software.
|
133
|
+
|
134
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
135
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
136
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
137
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
138
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
139
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
140
|
+
SOFTWARE.
|
data/friendly_id.gemspec
CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_development_dependency "ffaker", "~> 1.8.0"
|
23
23
|
s.add_development_dependency "maruku", "~> 0.6.0"
|
24
24
|
s.add_development_dependency "yard", "~> 0.7.2"
|
25
|
+
s.add_development_dependency "i18n", "~> 0.5.0"
|
25
26
|
|
26
27
|
s.description = <<-EOM
|
27
28
|
FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
|
@@ -1,13 +1,13 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.0.
|
5
|
-
activesupport (= 3.0.
|
4
|
+
activemodel (3.0.10)
|
5
|
+
activesupport (= 3.0.10)
|
6
6
|
builder (~> 2.1.2)
|
7
7
|
i18n (~> 0.5.0)
|
8
|
-
activerecord (3.0.
|
9
|
-
activemodel (= 3.0.
|
10
|
-
activesupport (= 3.0.
|
8
|
+
activerecord (3.0.10)
|
9
|
+
activemodel (= 3.0.10)
|
10
|
+
activesupport (= 3.0.10)
|
11
11
|
arel (~> 2.0.10)
|
12
12
|
tzinfo (~> 0.3.23)
|
13
13
|
activerecord-jdbc-adapter (1.1.3)
|
@@ -20,7 +20,7 @@ GEM
|
|
20
20
|
activerecord-jdbcsqlite3-adapter (1.1.3)
|
21
21
|
activerecord-jdbc-adapter (= 1.1.3)
|
22
22
|
jdbc-sqlite3 (~> 3.7.0)
|
23
|
-
activesupport (3.0.
|
23
|
+
activesupport (3.0.10)
|
24
24
|
arel (2.0.10)
|
25
25
|
builder (2.1.2)
|
26
26
|
i18n (0.5.0)
|
@@ -40,7 +40,7 @@ PLATFORMS
|
|
40
40
|
ruby
|
41
41
|
|
42
42
|
DEPENDENCIES
|
43
|
-
activerecord (= 3.0.
|
43
|
+
activerecord (= 3.0.10)
|
44
44
|
activerecord-jdbcmysql-adapter
|
45
45
|
activerecord-jdbcpostgresql-adapter
|
46
46
|
activerecord-jdbcsqlite3-adapter
|
@@ -1,15 +1,15 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.1.0
|
5
|
-
activesupport (= 3.1.0
|
6
|
-
bcrypt-ruby (~>
|
4
|
+
activemodel (3.1.0)
|
5
|
+
activesupport (= 3.1.0)
|
6
|
+
bcrypt-ruby (~> 3.0.0)
|
7
7
|
builder (~> 3.0.0)
|
8
8
|
i18n (~> 0.6)
|
9
|
-
activerecord (3.1.0
|
10
|
-
activemodel (= 3.1.0
|
11
|
-
activesupport (= 3.1.0
|
12
|
-
arel (~> 2.1
|
9
|
+
activerecord (3.1.0)
|
10
|
+
activemodel (= 3.1.0)
|
11
|
+
activesupport (= 3.1.0)
|
12
|
+
arel (~> 2.2.1)
|
13
13
|
tzinfo (~> 0.3.29)
|
14
14
|
activerecord-jdbc-adapter (1.1.3)
|
15
15
|
activerecord-jdbcmysql-adapter (1.1.3)
|
@@ -21,11 +21,11 @@ GEM
|
|
21
21
|
activerecord-jdbcsqlite3-adapter (1.1.3)
|
22
22
|
activerecord-jdbc-adapter (= 1.1.3)
|
23
23
|
jdbc-sqlite3 (~> 3.7.0)
|
24
|
-
activesupport (3.1.0
|
24
|
+
activesupport (3.1.0)
|
25
25
|
multi_json (~> 1.0)
|
26
|
-
arel (2.1
|
27
|
-
bcrypt-ruby (
|
28
|
-
bcrypt-ruby (
|
26
|
+
arel (2.2.1)
|
27
|
+
bcrypt-ruby (3.0.0)
|
28
|
+
bcrypt-ruby (3.0.0-java)
|
29
29
|
builder (3.0.0)
|
30
30
|
i18n (0.6.0)
|
31
31
|
jdbc-mysql (5.1.13)
|
@@ -45,7 +45,7 @@ PLATFORMS
|
|
45
45
|
ruby
|
46
46
|
|
47
47
|
DEPENDENCIES
|
48
|
-
activerecord (~> 3.1.0
|
48
|
+
activerecord (~> 3.1.0)
|
49
49
|
activerecord-jdbcmysql-adapter
|
50
50
|
activerecord-jdbcpostgresql-adapter
|
51
51
|
activerecord-jdbcsqlite3-adapter
|
data/lib/friendly_id.rb
CHANGED
@@ -81,11 +81,12 @@ In general, use slugs by default unless you know for sure you don't need them.
|
|
81
81
|
module FriendlyId
|
82
82
|
|
83
83
|
# The current version.
|
84
|
-
VERSION = "4.0.0.
|
84
|
+
VERSION = "4.0.0.beta10"
|
85
85
|
|
86
86
|
@mutex = Mutex.new
|
87
87
|
|
88
88
|
autoload :History, "friendly_id/history"
|
89
|
+
autoload :I18n, "friendly_id/i18n"
|
89
90
|
autoload :Reserved, "friendly_id/reserved"
|
90
91
|
autoload :Scoped, "friendly_id/scoped"
|
91
92
|
autoload :Slugged, "friendly_id/slugged"
|
@@ -53,7 +53,7 @@ module FriendlyId
|
|
53
53
|
# end
|
54
54
|
# @param [#to_s] *modules Arguments should be a symbols or strings that
|
55
55
|
# correspond with the name of a module inside the FriendlyId namespace. By
|
56
|
-
# default FriendlyId provides +:slugged+, +:history+ and +:scoped+.
|
56
|
+
# default FriendlyId provides +:slugged+, +:history+, +:i18n+ and +:scoped+.
|
57
57
|
def use(*modules)
|
58
58
|
modules.to_a.flatten.compact.map do |name|
|
59
59
|
mod = FriendlyId.const_get(name.to_s.classify)
|
data/lib/friendly_id/history.rb
CHANGED
@@ -63,9 +63,9 @@ method.
|
|
63
63
|
klass.instance_eval do
|
64
64
|
raise "FriendlyId::History is incompatibe with FriendlyId::Scoped" if self < Scoped
|
65
65
|
@friendly_id_config.use :slugged
|
66
|
-
has_many :slugs, :as => :sluggable, :dependent => :destroy, :class_name =>
|
66
|
+
has_many :slugs, :as => :sluggable, :dependent => :destroy, :class_name => Slug.to_s
|
67
67
|
before_save :build_slug, :if => lambda {|r| r.slug_sequencer.slug_changed?}
|
68
|
-
scope :with_friendly_id, lambda {|id| includes(:slugs).where("
|
68
|
+
scope :with_friendly_id, lambda {|id| includes(:slugs).where("#{Slug.table_name}.slug" => id)}
|
69
69
|
extend Finder
|
70
70
|
end
|
71
71
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "i18n"
|
2
|
+
|
3
|
+
module FriendlyId
|
4
|
+
|
5
|
+
=begin
|
6
|
+
This module adds very basic i18n support to FriendlyId.
|
7
|
+
|
8
|
+
In order to use this module, your model must have a slug column for each locale.
|
9
|
+
The slug column for your default locale should, however, still be named "slug".
|
10
|
+
An i18n module that uses external slugs and doesn't require a column for each
|
11
|
+
locale is planned, but has not been created yet.
|
12
|
+
|
13
|
+
== Example migration
|
14
|
+
|
15
|
+
def self.up
|
16
|
+
create_table :posts do |t|
|
17
|
+
t.string :title
|
18
|
+
t.string :slug
|
19
|
+
t.string :slug_es
|
20
|
+
t.text :body
|
21
|
+
end
|
22
|
+
add_index :posts, :slug
|
23
|
+
add_index :posts, :slug_es
|
24
|
+
end
|
25
|
+
|
26
|
+
== Finds
|
27
|
+
|
28
|
+
Finds will take into consideration the current locale:
|
29
|
+
|
30
|
+
I18n.locale = :es
|
31
|
+
Post.find("la-guerra-de-las-galaxas")
|
32
|
+
I18n.locale = :en
|
33
|
+
Post.find("star-wars")
|
34
|
+
|
35
|
+
To find a slug by an explicit locale, perform the find inside a block
|
36
|
+
passed to I18n's +with_locale+ method:
|
37
|
+
|
38
|
+
I18n.with_locale(:es) do
|
39
|
+
Post.find("la-guerra-de-las-galaxas")
|
40
|
+
end
|
41
|
+
|
42
|
+
== Creating Records
|
43
|
+
|
44
|
+
When new records are created, the slug is generated for the current locale only.
|
45
|
+
|
46
|
+
== Translating Slugs
|
47
|
+
|
48
|
+
To translate an existing record's friendly_id, use {#set_friendly_id}. This will
|
49
|
+
ensure that the slug you add is properly escaped, transliterated and sequenced:
|
50
|
+
|
51
|
+
post = Post.create :name => "Star Wars"
|
52
|
+
post.set_friendly_id("La guerra de las galaxas", :es)
|
53
|
+
|
54
|
+
If you don't pass in a locale argument, FriendlyId::I18n will just use the
|
55
|
+
current locale:
|
56
|
+
|
57
|
+
I18n.with_locale(:es) do
|
58
|
+
post.set_friendly_id("la-guerra-de-las-galaxas")
|
59
|
+
end
|
60
|
+
=end
|
61
|
+
module I18n
|
62
|
+
def self.included(model_class)
|
63
|
+
model_class.instance_eval do
|
64
|
+
friendly_id_config.use :slugged
|
65
|
+
friendly_id_config.class.send :include, Configuration
|
66
|
+
include Model
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module Model
|
71
|
+
def set_friendly_id(text, locale = nil)
|
72
|
+
::I18n.with_locale(locale || ::I18n.current_locale) do
|
73
|
+
slug = slug_sequencer(normalize_friendly_id(text)).generate
|
74
|
+
send "#{friendly_id_config.slug_column}=", slug
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module Configuration
|
80
|
+
def slug_column
|
81
|
+
::I18n.locale == ::I18n.default_locale ? super : [super, "_", ::I18n.locale].join
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/lib/friendly_id/reserved.rb
CHANGED
@@ -34,7 +34,7 @@ is included. You can configure this globally by using {FriendlyId.defaults Frien
|
|
34
34
|
def base=(base)
|
35
35
|
super
|
36
36
|
reserved_words = model_class.friendly_id_config.reserved_words
|
37
|
-
model_class.validates_exclusion_of
|
37
|
+
model_class.validates_exclusion_of :friendly_id, :in => reserved_words
|
38
38
|
end
|
39
39
|
|
40
40
|
# An array of words forbidden as slugs.
|
@@ -43,4 +43,4 @@ is included. You can configure this globally by using {FriendlyId.defaults Frien
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
end
|
46
|
+
end
|
data/lib/friendly_id/scoped.rb
CHANGED
@@ -124,7 +124,7 @@ an example of one way to set this up:
|
|
124
124
|
|
125
125
|
def conflict
|
126
126
|
column = friendly_id_config.scope_column
|
127
|
-
conflicts.where(
|
127
|
+
conflicts.where(column => sluggable.send(column)).first
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
@@ -2,15 +2,16 @@ module FriendlyId
|
|
2
2
|
# This class offers functionality to check slug strings for uniqueness and,
|
3
3
|
# if necessary, append a sequence to ensure it.
|
4
4
|
class SlugSequencer
|
5
|
-
attr_reader :sluggable
|
5
|
+
attr_reader :sluggable, :normalized
|
6
6
|
|
7
|
-
def initialize(sluggable)
|
8
|
-
@sluggable
|
7
|
+
def initialize(sluggable, normalized)
|
8
|
+
@sluggable = sluggable
|
9
|
+
@normalized = normalized
|
9
10
|
end
|
10
11
|
|
11
12
|
# Given a slug, get the next available slug in the sequence.
|
12
13
|
def next
|
13
|
-
sequence = conflict.
|
14
|
+
sequence = conflict.to_param.split(separator)[1].to_i
|
14
15
|
next_sequence = sequence == 0 ? 2 : sequence.next
|
15
16
|
"#{normalized}#{separator}#{next_sequence}"
|
16
17
|
end
|
@@ -37,7 +38,7 @@ module FriendlyId
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def column
|
40
|
-
sluggable.connection.quote_column_name friendly_id_config.
|
41
|
+
sluggable.connection.quote_column_name friendly_id_config.slug_column
|
41
42
|
end
|
42
43
|
|
43
44
|
def conflict?
|
@@ -54,7 +55,7 @@ module FriendlyId
|
|
54
55
|
def conflicts
|
55
56
|
pkey = sluggable.class.primary_key
|
56
57
|
value = sluggable.send pkey
|
57
|
-
scope = sluggable.class.where("#{column} = ? OR #{column} LIKE ?", normalized, wildcard)
|
58
|
+
scope = sluggable.class.unscoped.where("#{column} = ? OR #{column} LIKE ?", normalized, wildcard)
|
58
59
|
scope = scope.where("#{pkey} <> ?", value) unless sluggable.new_record?
|
59
60
|
scope = scope.order("LENGTH(#{column}) DESC, #{column} DESC")
|
60
61
|
end
|
@@ -67,10 +68,6 @@ module FriendlyId
|
|
67
68
|
sluggable.new_record?
|
68
69
|
end
|
69
70
|
|
70
|
-
def normalized
|
71
|
-
@normalized ||= sluggable.normalize_friendly_id(base)
|
72
|
-
end
|
73
|
-
|
74
71
|
def separator
|
75
72
|
friendly_id_config.sequence_separator
|
76
73
|
end
|
data/lib/friendly_id/slugged.rb
CHANGED
@@ -148,7 +148,7 @@ This functionality was in fact taken from earlier versions of FriendlyId.
|
|
148
148
|
# "#{name} from #{location}"
|
149
149
|
# end
|
150
150
|
#
|
151
|
-
# # Use default slug, but
|
151
|
+
# # Use default slug, but upper case and with underscores
|
152
152
|
# def normalize_friendly_id(string)
|
153
153
|
# super.upcase.gsub("-", "_")
|
154
154
|
# end
|
@@ -172,8 +172,9 @@ This functionality was in fact taken from earlier versions of FriendlyId.
|
|
172
172
|
# Gets a new instance of the configured slug sequencing class.
|
173
173
|
#
|
174
174
|
# @see FriendlyId::SlugSequencer
|
175
|
-
def slug_sequencer
|
176
|
-
friendly_id_config.
|
175
|
+
def slug_sequencer(normalized = nil)
|
176
|
+
normalized ||= normalize_friendly_id(send(friendly_id_config.base))
|
177
|
+
friendly_id_config.slug_sequencer_class.new(self, normalized)
|
177
178
|
end
|
178
179
|
|
179
180
|
# Sets the slug.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path("../../../helper", __FILE__)
|
2
|
+
|
3
|
+
require "ancestry"
|
4
|
+
|
5
|
+
ActiveRecord::Migration.create_table("things") do |t|
|
6
|
+
t.string :name
|
7
|
+
t.string :slug
|
8
|
+
t.string :ancestry
|
9
|
+
end
|
10
|
+
ActiveRecord::Migration.add_index :things, :ancestry
|
11
|
+
|
12
|
+
class Thing < ActiveRecord::Base
|
13
|
+
extend FriendlyId
|
14
|
+
friendly_id do |config|
|
15
|
+
config.use :slugged
|
16
|
+
config.use :scoped
|
17
|
+
config.base = :name
|
18
|
+
config.scope = :ancestry
|
19
|
+
end
|
20
|
+
has_ancestry
|
21
|
+
end
|
22
|
+
|
23
|
+
class AncestryTest < MiniTest::Unit::TestCase
|
24
|
+
include FriendlyId::Test
|
25
|
+
|
26
|
+
test "should sequence slugs when scoped by ancestry" do
|
27
|
+
3.times.inject([]) do |memo, _|
|
28
|
+
memo << Thing.create!(:name => "a", :parent => memo.last)
|
29
|
+
end.each do |thing|
|
30
|
+
assert_equal "a", thing.friendly_id
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
data/test/i18n_test.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.expand_path("../helper.rb", __FILE__)
|
2
|
+
|
3
|
+
class I18nTest < MiniTest::Unit::TestCase
|
4
|
+
include FriendlyId::Test
|
5
|
+
|
6
|
+
I18n = ::I18n
|
7
|
+
|
8
|
+
class Journalist < ActiveRecord::Base
|
9
|
+
extend FriendlyId
|
10
|
+
friendly_id :name, :use => :i18n
|
11
|
+
end
|
12
|
+
|
13
|
+
test "friendly_id should return a the current locale's slug" do
|
14
|
+
journalist = Journalist.new(:name => "John Doe")
|
15
|
+
journalist.slug_es = "juan-fulano"
|
16
|
+
journalist.valid?
|
17
|
+
I18n.with_locale(I18n.default_locale) do
|
18
|
+
assert_equal "john-doe", journalist.friendly_id
|
19
|
+
end
|
20
|
+
I18n.with_locale(:es) do
|
21
|
+
assert_equal "juan-fulano", journalist.friendly_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should create record with slug in column for the current locale" do
|
26
|
+
I18n.with_locale(I18n.default_locale) do
|
27
|
+
journalist = Journalist.new(:name => "John Doe")
|
28
|
+
journalist.valid?
|
29
|
+
assert_equal "john-doe", journalist.slug
|
30
|
+
assert_nil journalist.slug_es
|
31
|
+
end
|
32
|
+
I18n.with_locale(:es) do
|
33
|
+
journalist = Journalist.new(:name => "John Doe")
|
34
|
+
journalist.valid?
|
35
|
+
assert_equal "john-doe", journalist.slug_es
|
36
|
+
assert_nil journalist.slug
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
test "to_param should return the numeric id when there's no slug for the current locale" do
|
41
|
+
transaction do
|
42
|
+
journalist = Journalist.new(:name => "Juan Fulano")
|
43
|
+
I18n.with_locale(:es) do
|
44
|
+
journalist.save!
|
45
|
+
assert_equal "juan-fulano", journalist.to_param
|
46
|
+
end
|
47
|
+
assert_equal journalist.id.to_s, journalist.to_param
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
test "should set friendly id for locale" do
|
52
|
+
transaction do
|
53
|
+
journalist = Journalist.create!(:name => "John Smith")
|
54
|
+
journalist.set_friendly_id("Juan Fulano", :es)
|
55
|
+
journalist.save!
|
56
|
+
assert_equal "john-smith", journalist.to_param
|
57
|
+
I18n.with_locale(:es) do
|
58
|
+
assert_equal "juan-fulano", journalist.to_param
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
test "should sequence localized slugs" do
|
64
|
+
transaction do
|
65
|
+
journalist = Journalist.create!(:name => "John Smith")
|
66
|
+
I18n.with_locale(:es) do
|
67
|
+
Journalist.create!(:name => "Juan Fulano")
|
68
|
+
end
|
69
|
+
journalist.set_friendly_id("Juan Fulano", :es)
|
70
|
+
journalist.save!
|
71
|
+
assert_equal "john-smith", journalist.to_param
|
72
|
+
I18n.with_locale(:es) do
|
73
|
+
assert_equal "juan-fulano--2", journalist.to_param
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class ConfigurationTest < MiniTest::Unit::TestCase
|
79
|
+
test "should add locale to slug column for a non-default locale" do
|
80
|
+
I18n.with_locale :es do
|
81
|
+
assert_equal "slug_es", Journalist.friendly_id_config.slug_column
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
test "should add locale to non-default slug column and non-default locale" do
|
86
|
+
model_class = Class.new(ActiveRecord::Base) do
|
87
|
+
extend FriendlyId
|
88
|
+
friendly_id :name, :use => :i18n, :slug_column => :foo
|
89
|
+
end
|
90
|
+
I18n.with_locale :es do
|
91
|
+
assert_equal "foo_es", model_class.friendly_id_config.slug_column
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
test "should not add locale to slug column for default locale" do
|
96
|
+
I18n.with_locale(I18n.default_locale) do
|
97
|
+
assert_equal "slug", Journalist.friendly_id_config.slug_column
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/test/schema.rb
CHANGED
@@ -37,6 +37,11 @@ module FriendlyId
|
|
37
37
|
|
38
38
|
# This will be used to test STI
|
39
39
|
add_column :journalists, "type", :string
|
40
|
+
|
41
|
+
# These will be used to test i18n
|
42
|
+
add_column :journalists, "slug_es", :string
|
43
|
+
add_column :journalists, "slug_de", :string
|
44
|
+
|
40
45
|
@done = true
|
41
46
|
end
|
42
47
|
|
data/test/shared.rb
CHANGED
@@ -40,6 +40,17 @@ module FriendlyId
|
|
40
40
|
assert record2.friendly_id.match(/2\z/)
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
test "should create slug on save if the slug is nil" do
|
45
|
+
with_instance_of model_class do |record|
|
46
|
+
record.slug = nil
|
47
|
+
record.save!
|
48
|
+
assert_nil record.slug
|
49
|
+
record.save
|
50
|
+
refute_nil record.slug
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
43
54
|
end
|
44
55
|
|
45
56
|
module Core
|
data/test/slugged_test.rb
CHANGED
@@ -16,6 +16,15 @@ class SluggedTest < MiniTest::Unit::TestCase
|
|
16
16
|
def model_class
|
17
17
|
Journalist
|
18
18
|
end
|
19
|
+
|
20
|
+
test "should not allow reserved words in resulting slug" do
|
21
|
+
["new", "New", "NEW"].each do |word|
|
22
|
+
transaction do
|
23
|
+
assert_raises(ActiveRecord::RecordInvalid) {model_class.create! :name => word}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
19
28
|
end
|
20
29
|
|
21
30
|
class SlugSequencerTest < MiniTest::Unit::TestCase
|
@@ -65,6 +74,30 @@ class SlugSeparatorTest < MiniTest::Unit::TestCase
|
|
65
74
|
end
|
66
75
|
end
|
67
76
|
|
77
|
+
class DefaultScopeTest < MiniTest::Unit::TestCase
|
78
|
+
|
79
|
+
include FriendlyId::Test
|
80
|
+
|
81
|
+
class Journalist < ActiveRecord::Base
|
82
|
+
extend FriendlyId
|
83
|
+
friendly_id :name, :use => :slugged
|
84
|
+
default_scope :order => 'id ASC', :conditions => { :active => true }
|
85
|
+
end
|
86
|
+
|
87
|
+
test "friendly_id should correctly sequence a default_scoped ordered table" do
|
88
|
+
transaction do
|
89
|
+
3.times { assert Journalist.create :name => "a", :active => true }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
test "friendly_id should correctly sequence a default_scoped scoped table" do
|
94
|
+
transaction do
|
95
|
+
assert Journalist.create :name => "a", :active => false
|
96
|
+
assert Journalist.create :name => "a", :active => true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
68
101
|
class SluggedRegressionsTest < MiniTest::Unit::TestCase
|
69
102
|
include FriendlyId::Test
|
70
103
|
|
@@ -80,4 +113,4 @@ class SluggedRegressionsTest < MiniTest::Unit::TestCase
|
|
80
113
|
end
|
81
114
|
end
|
82
115
|
end
|
83
|
-
end
|
116
|
+
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.0.
|
4
|
+
version: 4.0.0.beta10
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-08-
|
13
|
-
default_executable:
|
12
|
+
date: 2011-08-31 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: activerecord
|
17
|
-
requirement: &
|
16
|
+
requirement: &70208447070040 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ~>
|
@@ -22,10 +21,10 @@ dependencies:
|
|
22
21
|
version: '3.0'
|
23
22
|
type: :development
|
24
23
|
prerelease: false
|
25
|
-
version_requirements: *
|
24
|
+
version_requirements: *70208447070040
|
26
25
|
- !ruby/object:Gem::Dependency
|
27
26
|
name: sqlite3
|
28
|
-
requirement: &
|
27
|
+
requirement: &70208447069380 !ruby/object:Gem::Requirement
|
29
28
|
none: false
|
30
29
|
requirements:
|
31
30
|
- - ~>
|
@@ -33,10 +32,10 @@ dependencies:
|
|
33
32
|
version: '1.3'
|
34
33
|
type: :development
|
35
34
|
prerelease: false
|
36
|
-
version_requirements: *
|
35
|
+
version_requirements: *70208447069380
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
37
|
name: minitest
|
39
|
-
requirement: &
|
38
|
+
requirement: &70208447068760 !ruby/object:Gem::Requirement
|
40
39
|
none: false
|
41
40
|
requirements:
|
42
41
|
- - ~>
|
@@ -44,10 +43,10 @@ dependencies:
|
|
44
43
|
version: 2.4.0
|
45
44
|
type: :development
|
46
45
|
prerelease: false
|
47
|
-
version_requirements: *
|
46
|
+
version_requirements: *70208447068760
|
48
47
|
- !ruby/object:Gem::Dependency
|
49
48
|
name: mocha
|
50
|
-
requirement: &
|
49
|
+
requirement: &70208447068060 !ruby/object:Gem::Requirement
|
51
50
|
none: false
|
52
51
|
requirements:
|
53
52
|
- - ~>
|
@@ -55,10 +54,10 @@ dependencies:
|
|
55
54
|
version: 0.9.12
|
56
55
|
type: :development
|
57
56
|
prerelease: false
|
58
|
-
version_requirements: *
|
57
|
+
version_requirements: *70208447068060
|
59
58
|
- !ruby/object:Gem::Dependency
|
60
59
|
name: ffaker
|
61
|
-
requirement: &
|
60
|
+
requirement: &70208447067380 !ruby/object:Gem::Requirement
|
62
61
|
none: false
|
63
62
|
requirements:
|
64
63
|
- - ~>
|
@@ -66,10 +65,10 @@ dependencies:
|
|
66
65
|
version: 1.8.0
|
67
66
|
type: :development
|
68
67
|
prerelease: false
|
69
|
-
version_requirements: *
|
68
|
+
version_requirements: *70208447067380
|
70
69
|
- !ruby/object:Gem::Dependency
|
71
70
|
name: maruku
|
72
|
-
requirement: &
|
71
|
+
requirement: &70208447066800 !ruby/object:Gem::Requirement
|
73
72
|
none: false
|
74
73
|
requirements:
|
75
74
|
- - ~>
|
@@ -77,10 +76,10 @@ dependencies:
|
|
77
76
|
version: 0.6.0
|
78
77
|
type: :development
|
79
78
|
prerelease: false
|
80
|
-
version_requirements: *
|
79
|
+
version_requirements: *70208447066800
|
81
80
|
- !ruby/object:Gem::Dependency
|
82
81
|
name: yard
|
83
|
-
requirement: &
|
82
|
+
requirement: &70208447066100 !ruby/object:Gem::Requirement
|
84
83
|
none: false
|
85
84
|
requirements:
|
86
85
|
- - ~>
|
@@ -88,7 +87,18 @@ dependencies:
|
|
88
87
|
version: 0.7.2
|
89
88
|
type: :development
|
90
89
|
prerelease: false
|
91
|
-
version_requirements: *
|
90
|
+
version_requirements: *70208447066100
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: i18n
|
93
|
+
requirement: &70208447065460 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.5.0
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70208447065460
|
92
102
|
description: ! 'FriendlyId is the "Swiss Army bulldozer" of slugging and permalink
|
93
103
|
plugins for
|
94
104
|
|
@@ -124,6 +134,7 @@ files:
|
|
124
134
|
- lib/friendly_id/configuration.rb
|
125
135
|
- lib/friendly_id/finder_methods.rb
|
126
136
|
- lib/friendly_id/history.rb
|
137
|
+
- lib/friendly_id/i18n.rb
|
127
138
|
- lib/friendly_id/migration.rb
|
128
139
|
- lib/friendly_id/model.rb
|
129
140
|
- lib/friendly_id/object_utils.rb
|
@@ -134,11 +145,14 @@ files:
|
|
134
145
|
- lib/friendly_id/slugged.rb
|
135
146
|
- lib/generators/friendly_id_generator.rb
|
136
147
|
- test/base_test.rb
|
148
|
+
- test/compatibility/ancestry/Gemfile
|
149
|
+
- test/compatibility/ancestry/ancestry_test.rb
|
137
150
|
- test/configuration_test.rb
|
138
151
|
- test/core_test.rb
|
139
152
|
- test/databases.yml
|
140
153
|
- test/helper.rb
|
141
154
|
- test/history_test.rb
|
155
|
+
- test/i18n_test.rb
|
142
156
|
- test/object_utils_test.rb
|
143
157
|
- test/reserved_test.rb
|
144
158
|
- test/schema.rb
|
@@ -146,7 +160,6 @@ files:
|
|
146
160
|
- test/shared.rb
|
147
161
|
- test/slugged_test.rb
|
148
162
|
- test/sti_test.rb
|
149
|
-
has_rdoc: true
|
150
163
|
homepage: http://norman.github.com/friendly_id
|
151
164
|
licenses: []
|
152
165
|
post_install_message: ! 'NOTE: FriendlyId 4.x breaks compatibility with 3.x. If you''re
|
@@ -176,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
189
|
version: 1.3.1
|
177
190
|
requirements: []
|
178
191
|
rubyforge_project: friendly_id
|
179
|
-
rubygems_version: 1.6
|
192
|
+
rubygems_version: 1.8.6
|
180
193
|
signing_key:
|
181
194
|
specification_version: 3
|
182
195
|
summary: A comprehensive slugging and pretty-URL plugin.
|