rakutenusa-friendly_id 2.0.7 → 2.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +25 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +20 -24
- data/VERSION.yml +2 -2
- data/lib/friendly_id.rb +15 -1
- data/lib/friendly_id/helpers.rb +2 -0
- data/lib/friendly_id/non_sluggable_class_methods.rb +2 -0
- data/lib/friendly_id/non_sluggable_instance_methods.rb +2 -0
- data/lib/friendly_id/slug.rb +34 -23
- data/lib/friendly_id/sluggable_class_methods.rb +5 -3
- data/lib/friendly_id/sluggable_instance_methods.rb +2 -0
- data/lib/friendly_id/version.rb +4 -2
- data/lib/tasks/friendly_id.rake +2 -0
- data/test/contest.rb +94 -0
- data/test/models/event.rb +3 -0
- data/test/models/post.rb +3 -0
- data/test/non_slugged_test.rb +2 -0
- data/test/schema.rb +8 -0
- data/test/scoped_model_test.rb +2 -0
- data/test/slug_test.rb +2 -2
- data/test/slugged_model_test.rb +25 -4
- data/test/sti_test.rb +4 -4
- data/test/test_helper.rb +8 -14
- metadata +17 -22
- data/Rakefile +0 -47
data/History.txt
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
== 2.1.3 2009-06-03
|
2
|
+
|
3
|
+
* 1 minor enhancement:
|
4
|
+
* Always call #to_s on slug_text to allow objects such as DateTimes to be used for the friendly_id text. (reported by Jon Ng)
|
5
|
+
|
6
|
+
== 2.1.2 2009-05-21
|
7
|
+
|
8
|
+
* 2 minor enhancements:
|
9
|
+
* Non-slugged models now validate the friendly_id on save as well as create (Joe Van Dyk).
|
10
|
+
* Replaced Shoulda with Contest.
|
11
|
+
|
12
|
+
== 2.1.1 2009-03-25
|
13
|
+
|
14
|
+
* 2 minor enhancements:
|
15
|
+
* Fixed bug with find_some; if a record has old slugs, find_some will no longer return
|
16
|
+
multiple copies of that record when finding by numerical ID. (Steve Luscher)
|
17
|
+
* Fixed bug with find_some: you can now find_some with an array of numerical IDs without
|
18
|
+
an error being thrown. (Steve Luscher)
|
19
|
+
|
20
|
+
== 2.1.0 2009-03-25
|
21
|
+
|
22
|
+
* 2 major enhancements:
|
23
|
+
* Ruby 1.9 compatibility.
|
24
|
+
* Removed dependency on ancient Unicode gem.
|
25
|
+
|
1
26
|
== 2.0.4 2009-02-12
|
2
27
|
|
3
28
|
* 1 major enhancment:
|
data/Manifest.txt
CHANGED
@@ -20,9 +20,11 @@ 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/contest.rb
|
23
24
|
test/custom_slug_normalizer_test.rb
|
24
25
|
test/models/book.rb
|
25
26
|
test/models/country.rb
|
27
|
+
test/models/event.rb
|
26
28
|
test/models/novel.rb
|
27
29
|
test/models/person.rb
|
28
30
|
test/models/post.rb
|
data/README.rdoc
CHANGED
@@ -219,30 +219,19 @@ While FriendlyId's slug generation options work for most people, you may need
|
|
219
219
|
something else. As of version 2.0.4 you can pass in your own custom slug
|
220
220
|
generation block:
|
221
221
|
|
222
|
-
require 'stringex'
|
223
222
|
class Post < ActiveRecord::Base
|
224
223
|
has_friendly_id :title, :use_slug => true do |text|
|
225
|
-
|
226
|
-
text.to_url
|
224
|
+
MySlugGeneratorClass::my_slug_method(text)
|
227
225
|
end
|
228
226
|
end
|
229
227
|
|
230
|
-
...
|
231
|
-
|
232
|
-
@post = Post.create(:title => "tell your readers 你好")
|
233
|
-
@post.friendly_id # "tell-your-readers-ni-hao"
|
234
|
-
|
235
228
|
FriendlyId will still respect your settings for max length and reserved words,
|
236
229
|
but will use your block rather than the baked-in methods to normalize the
|
237
230
|
friendly_id text.
|
238
231
|
|
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.)
|
242
|
-
|
243
232
|
== Getting it
|
244
233
|
|
245
|
-
FriendlyId is installed as a Ruby Gem:
|
234
|
+
FriendlyId is best installed as a Ruby Gem:
|
246
235
|
|
247
236
|
gem install friendly_id
|
248
237
|
|
@@ -251,15 +240,11 @@ discouraged:
|
|
251
240
|
|
252
241
|
./script/plugin install git://github.com/norman/friendly_id.git
|
253
242
|
|
254
|
-
If you are installing as a plugin, make sure you have installed the unicode gem,
|
255
|
-
which FriendlyId depends on:
|
256
|
-
|
257
|
-
gem install unicode
|
258
|
-
|
259
|
-
|
260
243
|
== Setting it up
|
261
244
|
|
262
|
-
|
245
|
+
The current release works with Rails 2.2 and above, and is compatible with
|
246
|
+
Ruby 1.8 and 1.9. If you need support for Rails 2.0 - 2.1, you need to install
|
247
|
+
an older version of FriendlyId. Here's how to set it up.
|
263
248
|
|
264
249
|
1) Install the Gem:
|
265
250
|
|
@@ -285,16 +270,27 @@ FriendlyId currently works with Rails 2.0.0 - 2.3.0. Here's how to set it up.
|
|
285
270
|
4) If you are using slugs, you can use a Rake task to generate slugs for your
|
286
271
|
existing records:
|
287
272
|
|
288
|
-
friendly_id:make_slugs MODEL=MyModelName
|
273
|
+
rake friendly_id:make_slugs MODEL=MyModelName
|
289
274
|
|
290
275
|
If you eventually want to expire old slugs every so often, or perhaps every
|
291
276
|
day via cron, you can do:
|
292
277
|
|
293
|
-
rake
|
278
|
+
rake friendly_id:remove_old_slugs
|
294
279
|
|
295
280
|
The default is to remove dead slugs older than 45 days, but is configurable:
|
296
281
|
|
297
|
-
rake
|
282
|
+
rake friendly_id:remove_old_slugs MODEL=MyModelName DAYS=60
|
283
|
+
|
284
|
+
== Installing an older version
|
285
|
+
|
286
|
+
If you are still on Rails 2.1 or lower, please install version 2.0.4:
|
287
|
+
|
288
|
+
gem install friendly_id --version 2.0.4
|
289
|
+
|
290
|
+
Note that this version depends on the Unicode gem, which doesn't compile on
|
291
|
+
Windows and is incompatible with Ruby 1.9. It also can't be installed on
|
292
|
+
Heroku. If these are problems, you'll need to update your application to Rails
|
293
|
+
2.2 or higher and use the current release of FriendlyId.
|
298
294
|
|
299
295
|
== Upgrading from an older version
|
300
296
|
|
@@ -325,7 +321,7 @@ Add this to the bottom of environment.rb:
|
|
325
321
|
|
326
322
|
==== Generate the upgrade migration and run it
|
327
323
|
|
328
|
-
./script
|
324
|
+
./script/generate friendly_id_20_upgrade
|
329
325
|
rake db:migrate
|
330
326
|
|
331
327
|
== Hacking FriendlyId:
|
data/VERSION.yml
CHANGED
data/lib/friendly_id.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'friendly_id/helpers'
|
2
4
|
require 'friendly_id/slug'
|
3
5
|
|
@@ -45,6 +47,18 @@ module FriendlyId
|
|
45
47
|
# * <tt>:strip_non_ascii</tt> - Defaults to false. If true, it will all non-ascii ([^a-z0-9]) characters.
|
46
48
|
# * <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"].
|
47
49
|
# * <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'.
|
50
|
+
#
|
51
|
+
# You can also optionally pass a block if you want to use your own custom
|
52
|
+
# slugnormalization routines rather than the default ones that come with
|
53
|
+
# friendly_id:
|
54
|
+
#
|
55
|
+
# require 'stringex'
|
56
|
+
# class Post < ActiveRecord::Base
|
57
|
+
# has_friendly_id :title, :use_slug => true do |text|
|
58
|
+
# # Use stringex to generate the friendly_id rather than the baked-in methods
|
59
|
+
# text.to_url
|
60
|
+
# end
|
61
|
+
# end
|
48
62
|
def has_friendly_id(column, options = {}, &block)
|
49
63
|
options.assert_valid_keys VALID_FRIENDLY_ID_KEYS
|
50
64
|
options = DEFAULT_FRIENDLY_ID_OPTIONS.merge(options).merge(:column => column)
|
@@ -67,7 +81,7 @@ module FriendlyId
|
|
67
81
|
require 'friendly_id/non_sluggable_instance_methods'
|
68
82
|
extend NonSluggableClassMethods
|
69
83
|
include NonSluggableInstanceMethods
|
70
|
-
|
84
|
+
validate :validate_friendly_id
|
71
85
|
end
|
72
86
|
end
|
73
87
|
|
data/lib/friendly_id/helpers.rb
CHANGED
data/lib/friendly_id/slug.rb
CHANGED
@@ -1,9 +1,23 @@
|
|
1
|
-
|
1
|
+
#encoding: utf-8
|
2
|
+
|
2
3
|
# A Slug is a unique, human-friendly identifier for an ActiveRecord.
|
3
4
|
class Slug < ActiveRecord::Base
|
4
5
|
|
5
6
|
belongs_to :sluggable, :polymorphic => true
|
6
7
|
before_save :check_for_blank_name, :set_sequence
|
8
|
+
|
9
|
+
|
10
|
+
ASCII_APPROXIMATIONS = {
|
11
|
+
198 => "AE",
|
12
|
+
208 => "D",
|
13
|
+
216 => "O",
|
14
|
+
222 => "Th",
|
15
|
+
223 => "ss",
|
16
|
+
230 => "ae",
|
17
|
+
240 => "d",
|
18
|
+
248 => "o",
|
19
|
+
254 => "th"
|
20
|
+
}.freeze
|
7
21
|
|
8
22
|
class << self
|
9
23
|
|
@@ -13,30 +27,22 @@ class Slug < ActiveRecord::Base
|
|
13
27
|
#
|
14
28
|
# slug.normalize('This... is an example!') # => "this-is-an-example"
|
15
29
|
#
|
16
|
-
# Note that
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
# for instance replacing Icelandic's "thorn" character with "y" rather
|
22
|
-
# than "d." This might be pedantic, but I don't want to piss off the
|
23
|
-
# Vikings. The last time anyone pissed them off, they uleashed a wave of
|
24
|
-
# terror in Europe unlike anything ever seen before or after. I'm not
|
25
|
-
# taking any chances.
|
30
|
+
# Note that the Unicode handling in ActiveSupport may fail to process some
|
31
|
+
# characters from Polish, Icelandic and other languages. If your
|
32
|
+
# application uses these languages, check {out this
|
33
|
+
# article}[http://link-coming-soon.com] for information on how to get
|
34
|
+
# better urls in your application.
|
26
35
|
def normalize(slug_text)
|
27
36
|
return "" if slug_text.nil? || slug_text == ""
|
28
|
-
|
29
|
-
|
30
|
-
# For some reason Spanish ¡ and ¿ are not detected as non-word
|
31
|
-
# characters. Bug in Ruby?
|
32
|
-
gsub(/[\W|¡|¿]/u, ' ').
|
37
|
+
ActiveSupport::Multibyte.proxy_class.new(slug_text.to_s).normalize(:kc).
|
38
|
+
gsub(/[\W]/u, ' ').
|
33
39
|
strip.
|
34
40
|
gsub(/\s+/u, '-').
|
35
41
|
gsub(/-\z/u, '').
|
36
42
|
downcase.
|
37
43
|
to_s
|
38
44
|
end
|
39
|
-
|
45
|
+
|
40
46
|
def parse(friendly_id)
|
41
47
|
name, sequence = friendly_id.split('--')
|
42
48
|
sequence ||= "1"
|
@@ -46,8 +52,17 @@ class Slug < ActiveRecord::Base
|
|
46
52
|
# Remove diacritics (accents, umlauts, etc.) from the string. Borrowed
|
47
53
|
# from "The Ruby Way."
|
48
54
|
def strip_diacritics(string)
|
49
|
-
|
55
|
+
ActiveSupport::Multibyte.proxy_class.new(string).normalize(:kd).unpack('U*').inject([]) { |a, u|
|
56
|
+
if ASCII_APPROXIMATIONS[u]
|
57
|
+
a += ASCII_APPROXIMATIONS[u].unpack('U*')
|
58
|
+
elsif (u < 0x300 || u > 0x036F)
|
59
|
+
a << u
|
60
|
+
end
|
61
|
+
a
|
62
|
+
}.pack('U*')
|
50
63
|
end
|
64
|
+
|
65
|
+
|
51
66
|
|
52
67
|
# Remove non-ascii characters from the string.
|
53
68
|
def strip_non_ascii(string)
|
@@ -56,10 +71,6 @@ class Slug < ActiveRecord::Base
|
|
56
71
|
|
57
72
|
private
|
58
73
|
|
59
|
-
def chars_func
|
60
|
-
"".respond_to?(:mb_chars) ? :mb_chars : :chars
|
61
|
-
end
|
62
|
-
|
63
74
|
end
|
64
75
|
|
65
76
|
# Whether or not this slug is the most recent of its owner's slugs.
|
@@ -75,7 +86,7 @@ class Slug < ActiveRecord::Base
|
|
75
86
|
|
76
87
|
# Raise a FriendlyId::SlugGenerationError if the slug name is blank.
|
77
88
|
def check_for_blank_name #:nodoc:#
|
78
|
-
if name
|
89
|
+
if name.blank?
|
79
90
|
raise FriendlyId::SlugGenerationError.new("The slug text is blank.")
|
80
91
|
end
|
81
92
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module FriendlyId::SluggableClassMethods
|
2
4
|
|
3
5
|
include FriendlyId::Helpers
|
@@ -63,7 +65,7 @@ module FriendlyId::SluggableClassMethods
|
|
63
65
|
find_options[:conditions] = "#{quoted_table_name}.#{primary_key} IN (#{ids.empty? ? 'NULL' : ids.join(',')}) "
|
64
66
|
find_options[:conditions] << "OR slugs.id IN (#{slugs.to_s(:db)})"
|
65
67
|
|
66
|
-
results = with_scope(:find => find_options) { find_every(options) }
|
68
|
+
results = with_scope(:find => find_options) { find_every(options) }.uniq
|
67
69
|
|
68
70
|
expected = expected_size(ids_and_names, options)
|
69
71
|
if results.size != expected
|
@@ -97,7 +99,7 @@ module FriendlyId::SluggableClassMethods
|
|
97
99
|
slugs = []
|
98
100
|
ids = []
|
99
101
|
ids_and_names.each do |id_or_name|
|
100
|
-
name, sequence = Slug.parse id_or_name
|
102
|
+
name, sequence = Slug.parse id_or_name.to_s
|
101
103
|
slug = Slug.find(:first, :conditions => {
|
102
104
|
:name => name,
|
103
105
|
:scope => scope,
|
@@ -106,7 +108,7 @@ module FriendlyId::SluggableClassMethods
|
|
106
108
|
})
|
107
109
|
# If the slug was found, add it to the array for later use. If not, and
|
108
110
|
# the id_or_name is a number, assume that it is a regular record id.
|
109
|
-
slug ? slugs << slug : (ids << id_or_name if id_or_name =~ /\A\d*\z/)
|
111
|
+
slug ? slugs << slug : (ids << id_or_name if id_or_name.to_s =~ /\A\d*\z/)
|
110
112
|
end
|
111
113
|
return slugs, ids
|
112
114
|
end
|
data/lib/friendly_id/version.rb
CHANGED
data/lib/tasks/friendly_id.rake
CHANGED
data/test/contest.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# License
|
2
|
+
# -------
|
3
|
+
#
|
4
|
+
# Contest is copyright (c) 2009 Damian Janowski and Michel Martens for
|
5
|
+
# Citrusbyte
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person
|
8
|
+
# obtaining a copy of this software and associated documentation
|
9
|
+
# files (the "Software"), to deal in the Software without
|
10
|
+
# restriction, including without limitation the rights to use,
|
11
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12
|
+
# copies of the Software, and to permit persons to whom the
|
13
|
+
# Software is furnished to do so, subject to the following
|
14
|
+
# conditions:
|
15
|
+
#
|
16
|
+
# The above copyright notice and this permission notice shall be
|
17
|
+
# included in all copies or substantial portions of the Software.
|
18
|
+
#
|
19
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
21
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
23
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
24
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
25
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
26
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
27
|
+
require "test/unit"
|
28
|
+
|
29
|
+
# Test::Unit loads a default test if the suite is empty, whose purpose is to
|
30
|
+
# fail. Since having empty contexts is a common practice, we decided to
|
31
|
+
# overwrite TestSuite#empty? in order to allow them. Having a failure when no
|
32
|
+
# tests have been defined seems counter-intuitive.
|
33
|
+
class Test::Unit::TestSuite
|
34
|
+
def empty?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Contest adds +teardown+, +test+ and +context+ as class methods, and the
|
40
|
+
# instance methods +setup+ and +teardown+ now iterate on the corresponding
|
41
|
+
# blocks. Note that all setup and teardown blocks must be defined with the
|
42
|
+
# block syntax. Adding setup or teardown instance methods defeats the purpose
|
43
|
+
# of this library.
|
44
|
+
class Test::Unit::TestCase
|
45
|
+
def self.setup(&block)
|
46
|
+
define_method :setup do
|
47
|
+
super(&block)
|
48
|
+
instance_eval(&block)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.teardown(&block)
|
53
|
+
define_method :teardown do
|
54
|
+
instance_eval(&block)
|
55
|
+
super(&block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.context(name, &block)
|
60
|
+
subclass = Class.new(self)
|
61
|
+
remove_tests(subclass)
|
62
|
+
subclass.class_eval(&block)
|
63
|
+
const_set(context_name(name), subclass)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.test(name, &block)
|
67
|
+
define_method(test_name(name), &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
class << self
|
71
|
+
alias_method :should, :test
|
72
|
+
alias_method :describe, :context
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def self.context_name(name)
|
78
|
+
"Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.test_name(name)
|
82
|
+
"test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.sanitize_name(name)
|
86
|
+
name.gsub(/\W+/, ' ').strip
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.remove_tests(subclass)
|
90
|
+
subclass.public_instance_methods.grep(/^test_/).each do |meth|
|
91
|
+
subclass.send(:undef_method, meth.to_sym)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/test/models/post.rb
CHANGED
data/test/non_slugged_test.rb
CHANGED
data/test/schema.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
ActiveRecord::Schema.define(:version => 1) do
|
2
4
|
|
3
5
|
create_table "books", :force => true do |t|
|
@@ -12,6 +14,7 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
12
14
|
create_table "posts", :force => true do |t|
|
13
15
|
t.column "title", "string"
|
14
16
|
t.column "content", "text"
|
17
|
+
t.column "published", "boolean", :default => false
|
15
18
|
t.column "created_at", "datetime"
|
16
19
|
t.column "updated_at", "datetime"
|
17
20
|
end
|
@@ -32,6 +35,11 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
32
35
|
t.column "name", "string"
|
33
36
|
end
|
34
37
|
|
38
|
+
create_table "events", :force => true do |t|
|
39
|
+
t.column "name", "string"
|
40
|
+
t.column "event_date", "datetime"
|
41
|
+
end
|
42
|
+
|
35
43
|
create_table "slugs", :force => true do |t|
|
36
44
|
t.column "name", "string"
|
37
45
|
t.column "sluggable_id", "integer"
|
data/test/scoped_model_test.rb
CHANGED
data/test/slug_test.rb
CHANGED
@@ -39,8 +39,8 @@ class SlugTest < Test::Unit::TestCase
|
|
39
39
|
input = "ÀÁÂÃÄÅÆÇÈÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"
|
40
40
|
output = Slug::strip_diacritics(input).split(//)
|
41
41
|
expected = "AAAAAAAECEEEIIIIDNOOOOOOUUUUYThssaaaaaaaeceeeeiiiidnoooooouuuuythy".split(//)
|
42
|
-
output.
|
43
|
-
assert_equal
|
42
|
+
output.each_index do |i|
|
43
|
+
assert_equal expected[i], output[i]
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
data/test/slugged_model_test.rb
CHANGED
@@ -11,7 +11,7 @@ class SluggedModelTest < Test::Unit::TestCase
|
|
11
11
|
Post.delete_all
|
12
12
|
Person.delete_all
|
13
13
|
Slug.delete_all
|
14
|
-
@post = Post.new :title => "Test post", :content => "Test content"
|
14
|
+
@post = Post.new :title => "Test post", :content => "Test content", :published => true
|
15
15
|
@post.save!
|
16
16
|
end
|
17
17
|
|
@@ -86,6 +86,10 @@ class SluggedModelTest < Test::Unit::TestCase
|
|
86
86
|
assert_match(/--2\z/, @post2.friendly_id)
|
87
87
|
end
|
88
88
|
|
89
|
+
should "allow datetime columns to be used as slugs" do
|
90
|
+
assert Event.create(:name => "Test", :event_date => DateTime.now)
|
91
|
+
end
|
92
|
+
|
89
93
|
should "not strip diacritics" do
|
90
94
|
@post = Post.new(:title => "¡Feliz año!")
|
91
95
|
assert_match(/#{'ñ'}/, @post.slug_text)
|
@@ -95,7 +99,7 @@ class SluggedModelTest < Test::Unit::TestCase
|
|
95
99
|
@post = Post.new(:title => "katakana: ゲコゴサザシジ")
|
96
100
|
assert_equal "katakana-ゲコゴサザシジ", @post.slug_text
|
97
101
|
end
|
98
|
-
|
102
|
+
|
99
103
|
should "allow the same friendly_id across models" do
|
100
104
|
@person = Person.create!(:name => @post.title)
|
101
105
|
assert_equal @person.friendly_id, @post.friendly_id
|
@@ -237,12 +241,29 @@ class SluggedModelTest < Test::Unit::TestCase
|
|
237
241
|
context "when using an array as the find argument" do
|
238
242
|
|
239
243
|
setup do
|
240
|
-
@post2 = Post.create!(:title => "another post", :content => "more content")
|
244
|
+
@post2 = Post.create!(:title => "another post", :content => "more content", :published => true)
|
245
|
+
end
|
246
|
+
|
247
|
+
should "return results when passed an array of non-friendly ids" do
|
248
|
+
assert_equal 2, Post.find([@post.id, @post2.id]).size
|
241
249
|
end
|
242
250
|
|
243
|
-
should "return results" do
|
251
|
+
should "return results when passed an array of friendly ids" do
|
244
252
|
assert_equal 2, Post.find([@post.friendly_id, @post2.friendly_id]).size
|
245
253
|
end
|
254
|
+
|
255
|
+
should "return results when searching using a named scope" do
|
256
|
+
assert_equal 2, Post.published.find([@post.id, @post2.id]).size
|
257
|
+
end
|
258
|
+
|
259
|
+
should "return results when passed a mixed array of friendly and non-friendly ids" do
|
260
|
+
assert_equal 2, Post.find([@post.friendly_id, @post2.id]).size
|
261
|
+
end
|
262
|
+
|
263
|
+
should "return results when passed an array of non-friendly ids, of which one represents a record with multiple slugs" do
|
264
|
+
@post2.update_attributes(:title => 'another post [updated]')
|
265
|
+
assert_equal 2, Post.find([@post.id, @post2.id]).size
|
266
|
+
end
|
246
267
|
|
247
268
|
should "indicate that the results were found using a friendly_id" do
|
248
269
|
@posts = Post.find [@post.friendly_id, @post2.friendly_id]
|
data/test/sti_test.rb
CHANGED
@@ -17,9 +17,9 @@ class SluggedModelTest < Test::Unit::TestCase
|
|
17
17
|
should "have a slug" do
|
18
18
|
assert_not_nil @novel.slug
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
context "found by its friendly id" do
|
22
|
-
|
22
|
+
|
23
23
|
setup do
|
24
24
|
@novel = Novel.find(@novel.friendly_id)
|
25
25
|
end
|
@@ -29,10 +29,10 @@ class SluggedModelTest < Test::Unit::TestCase
|
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
|
34
34
|
context "found by its numeric id" do
|
35
|
-
|
35
|
+
|
36
36
|
setup do
|
37
37
|
@novel = Novel.find(@novel.id)
|
38
38
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
4
|
$:.unshift(File.dirname(__FILE__))
|
3
|
-
$
|
4
|
-
|
5
|
+
$KCODE = 'UTF8' if RUBY_VERSION < '1.9'
|
6
|
+
$VERBOSE = false
|
5
7
|
require 'test/unit'
|
6
|
-
require '
|
8
|
+
require 'contest'
|
7
9
|
# You can use "rake test AR_VERSION=2.0.5" to test against 2.0.5, for example.
|
8
10
|
# The default is to use the latest installed ActiveRecord.
|
9
11
|
if ENV["AR_VERSION"]
|
10
12
|
gem 'activerecord', "#{ENV["AR_VERSION"]}"
|
13
|
+
gem 'activesupport', "#{ENV["AR_VERSION"]}"
|
11
14
|
end
|
12
15
|
require 'active_record'
|
13
|
-
|
16
|
+
require 'active_support'
|
14
17
|
require 'friendly_id'
|
15
18
|
require 'models/post'
|
16
19
|
require 'models/person'
|
@@ -19,16 +22,7 @@ require 'models/country'
|
|
19
22
|
require 'models/book'
|
20
23
|
require 'models/novel'
|
21
24
|
require 'models/thing'
|
22
|
-
|
23
|
-
# Borrowed from ActiveSupport
|
24
|
-
def silence_stream(stream)
|
25
|
-
old_stream = stream.dup
|
26
|
-
stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
|
27
|
-
stream.sync = true
|
28
|
-
yield
|
29
|
-
ensure
|
30
|
-
stream.reopen(old_stream)
|
31
|
-
end
|
25
|
+
require 'models/event'
|
32
26
|
|
33
27
|
ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => ":memory:"
|
34
28
|
silence_stream(STDOUT) do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rakutenusa-friendly_id
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- RakutenUSA
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-07-08 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -19,19 +19,22 @@ executables: []
|
|
19
19
|
|
20
20
|
extensions: []
|
21
21
|
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
24
|
files:
|
25
25
|
- History.txt
|
26
26
|
- Manifest.txt
|
27
27
|
- README.rdoc
|
28
|
-
- Rakefile
|
29
28
|
- VERSION.yml
|
29
|
+
- generators/friendly_id
|
30
30
|
- generators/friendly_id/friendly_id_generator.rb
|
31
|
+
- generators/friendly_id/templates
|
31
32
|
- generators/friendly_id/templates/create_slugs.rb
|
33
|
+
- generators/friendly_id_20_upgrade
|
32
34
|
- generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb
|
35
|
+
- generators/friendly_id_20_upgrade/templates
|
33
36
|
- generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb
|
34
|
-
- lib/friendly_id
|
37
|
+
- lib/friendly_id
|
35
38
|
- lib/friendly_id/helpers.rb
|
36
39
|
- lib/friendly_id/non_sluggable_class_methods.rb
|
37
40
|
- lib/friendly_id/non_sluggable_instance_methods.rb
|
@@ -39,11 +42,16 @@ files:
|
|
39
42
|
- lib/friendly_id/sluggable_class_methods.rb
|
40
43
|
- lib/friendly_id/sluggable_instance_methods.rb
|
41
44
|
- lib/friendly_id/version.rb
|
45
|
+
- lib/friendly_id.rb
|
46
|
+
- lib/tasks
|
42
47
|
- lib/tasks/friendly_id.rake
|
43
48
|
- lib/tasks/friendly_id.rb
|
49
|
+
- test/contest.rb
|
44
50
|
- test/custom_slug_normalizer_test.rb
|
51
|
+
- test/models
|
45
52
|
- test/models/book.rb
|
46
53
|
- test/models/country.rb
|
54
|
+
- test/models/event.rb
|
47
55
|
- test/models/novel.rb
|
48
56
|
- test/models/person.rb
|
49
57
|
- test/models/post.rb
|
@@ -60,6 +68,7 @@ has_rdoc: true
|
|
60
68
|
homepage: http://github.com/rakutenusa/friendly_id
|
61
69
|
post_install_message:
|
62
70
|
rdoc_options:
|
71
|
+
- --inline-source
|
63
72
|
- --charset=UTF-8
|
64
73
|
require_paths:
|
65
74
|
- lib
|
@@ -82,19 +91,5 @@ rubygems_version: 1.2.0
|
|
82
91
|
signing_key:
|
83
92
|
specification_version: 2
|
84
93
|
summary: TODO
|
85
|
-
test_files:
|
86
|
-
|
87
|
-
- test/models/book.rb
|
88
|
-
- test/models/country.rb
|
89
|
-
- test/models/novel.rb
|
90
|
-
- test/models/person.rb
|
91
|
-
- test/models/post.rb
|
92
|
-
- test/models/thing.rb
|
93
|
-
- test/models/user.rb
|
94
|
-
- test/non_slugged_test.rb
|
95
|
-
- test/schema.rb
|
96
|
-
- test/scoped_model_test.rb
|
97
|
-
- test/slug_test.rb
|
98
|
-
- test/slugged_model_test.rb
|
99
|
-
- test/sti_test.rb
|
100
|
-
- test/test_helper.rb
|
94
|
+
test_files: []
|
95
|
+
|
data/Rakefile
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'lib/friendly_id/version'
|
2
|
-
|
3
|
-
desc "Run RCov"
|
4
|
-
task :rcov do
|
5
|
-
run_coverage Dir["test/**/*_test.rb"]
|
6
|
-
end
|
7
|
-
|
8
|
-
def run_coverage(files)
|
9
|
-
rm_f "coverage"
|
10
|
-
rm_f "coverage.data"
|
11
|
-
if files.length == 0
|
12
|
-
puts "No files were specified for testing"
|
13
|
-
return
|
14
|
-
end
|
15
|
-
files = files.join(" ")
|
16
|
-
if PLATFORM =~ /darwin/
|
17
|
-
exclude = '--exclude "gems/"'
|
18
|
-
else
|
19
|
-
exclude = '--exclude "rubygems"'
|
20
|
-
end
|
21
|
-
rcov = "rcov -Ilib:test --sort coverage --text-report #{exclude} --no-validator-links"
|
22
|
-
cmd = "#{rcov} #{files}"
|
23
|
-
puts cmd
|
24
|
-
sh cmd
|
25
|
-
end
|
26
|
-
|
27
|
-
desc 'Publish RDoc to RubyForge.'
|
28
|
-
task :publish_docs => [:clean, :docs] do
|
29
|
-
host = "compay@rubyforge.org"
|
30
|
-
remote_dir = "/var/www/gforge-projects/friendly-id"
|
31
|
-
local_dir = 'doc'
|
32
|
-
sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
|
33
|
-
end
|
34
|
-
|
35
|
-
begin
|
36
|
-
require 'jeweler'
|
37
|
-
Jeweler::Tasks.new do |gemspec|
|
38
|
-
gemspec.name = "friendly_id"
|
39
|
-
gemspec.summary = "TODO"
|
40
|
-
gemspec.email = "dev@rakutenusa.com"
|
41
|
-
gemspec.homepage = "http://github.com/rakutenusa/friendly_id"
|
42
|
-
gemspec.description = "TODO"
|
43
|
-
gemspec.authors = ["RakutenUSA"]
|
44
|
-
end
|
45
|
-
rescue LoadError
|
46
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
47
|
-
end
|