friendly_id 4.0.0.beta8 → 4.0.0.beta10
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/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.
|