friendly_id 2.2.5 → 2.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -0
- data/{MIT-LICENSE → LICENSE} +0 -0
- data/README.rdoc +5 -5
- data/Rakefile +31 -42
- data/extras/README.txt +3 -0
- data/extras/template-gem.rb +26 -0
- data/extras/template-plugin.rb +28 -0
- data/lib/friendly_id.rb +2 -2
- data/lib/friendly_id/non_sluggable_class_methods.rb +5 -4
- data/lib/friendly_id/sluggable_class_methods.rb +1 -1
- data/lib/friendly_id/sluggable_instance_methods.rb +34 -18
- data/lib/friendly_id/tasks.rb +2 -2
- data/lib/friendly_id/version.rb +1 -1
- data/test/cached_slug_test.rb +0 -3
- data/test/custom_slug_normalizer_test.rb +9 -11
- data/test/non_slugged_test.rb +5 -7
- data/test/scoped_model_test.rb +18 -10
- data/test/slug_test.rb +2 -3
- data/test/slugged_model_test.rb +39 -33
- data/test/sti_test.rb +2 -4
- data/test/support/database.yml.postgres +6 -0
- data/test/support/database.yml.sqlite3 +2 -0
- data/test/support/models.rb +45 -0
- data/test/tasks_test.rb +5 -6
- data/test/test_helper.rb +85 -19
- metadata +23 -50
- data/test/contest.rb +0 -94
- data/test/models/book.rb +0 -2
- data/test/models/city.rb +0 -4
- data/test/models/country.rb +0 -4
- data/test/models/district.rb +0 -3
- data/test/models/event.rb +0 -3
- data/test/models/legacy_thing.rb +0 -4
- data/test/models/novel.rb +0 -3
- data/test/models/person.rb +0 -6
- data/test/models/post.rb +0 -6
- data/test/models/thing.rb +0 -6
- data/test/models/user.rb +0 -3
- data/test/schema.rb +0 -70
data/History.txt
CHANGED
@@ -1,8 +1,21 @@
|
|
1
|
+
== 2.2.6 2009-12-10
|
2
|
+
|
3
|
+
* 2 major fixes
|
4
|
+
* Made cached_slug automagic configuration occur outside of has_friendly_id. This was causing problems
|
5
|
+
in code where the class is loaded before ActiveRecord has established its connection.
|
6
|
+
* Fixes for scope feature with Postgres (Ben Woosley)
|
7
|
+
|
8
|
+
* 2 minor enhancements
|
9
|
+
* Migrated away from Hoe/Newgem for gem management.
|
10
|
+
* Made tests database-agnostic (Ben Woosley)
|
11
|
+
|
1
12
|
== 2.2.5 2009-11-30
|
13
|
+
|
2
14
|
* 1 minor fix
|
3
15
|
* Fixed typo which in config options (Steven Noble).
|
4
16
|
|
5
17
|
== 2.2.4 2009-11-12
|
18
|
+
|
6
19
|
* 1 minor fix
|
7
20
|
* Fixed typo in post-install message.
|
8
21
|
|
data/{MIT-LICENSE → LICENSE}
RENAMED
File without changes
|
data/README.rdoc
CHANGED
@@ -12,9 +12,8 @@ instead of:
|
|
12
12
|
|
13
13
|
http://example.com/states/4323454
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
Rubyforge[http://www.rubyforge.org].
|
15
|
+
You can always read the latest version of this document at the {friendly_id page on
|
16
|
+
rdoc.info}[http://rdoc.info/projects/norman/friendly_id].
|
18
17
|
|
19
18
|
=== Why?
|
20
19
|
|
@@ -294,8 +293,7 @@ discouraged:
|
|
294
293
|
== Setting it up
|
295
294
|
|
296
295
|
The current release works with Rails 2.2 and above, and is compatible with
|
297
|
-
Ruby 1.8 and 1.9.
|
298
|
-
an older version of FriendlyId. Here's how to set it up.
|
296
|
+
Ruby 1.8 and 1.9.
|
299
297
|
|
300
298
|
1) Install the Gem:
|
301
299
|
|
@@ -363,6 +361,7 @@ particular from the following people:
|
|
363
361
|
* Adam Cigánek
|
364
362
|
* Alistair Holt
|
365
363
|
* Andrew Loe III
|
364
|
+
* Ben Woosley
|
366
365
|
* Bence Nagy
|
367
366
|
* Bruno Michel
|
368
367
|
* Chris Nolan
|
@@ -378,6 +377,7 @@ particular from the following people:
|
|
378
377
|
* Rob Ingram
|
379
378
|
* Sean Abrahams
|
380
379
|
* Steve Luscher
|
380
|
+
* Steven Noble
|
381
381
|
* Tim Kadom
|
382
382
|
|
383
383
|
Copyright (c) 2008 Norman Clarke, Adrian Mugnolo and Emilio Tagua, released
|
data/Rakefile
CHANGED
@@ -1,46 +1,35 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
self.extra_dev_deps << ['newgem', ">= #{::Newgem::VERSION}"]
|
18
|
-
self.extra_dev_deps << ['sqlite3-ruby']
|
19
|
-
self.remote_rdoc_dir = ""
|
20
|
-
self.readme_file = "README.rdoc"
|
21
|
-
self.extra_rdoc_files = ["README.rdoc"]
|
22
|
-
self.post_install_message = <<-EOM
|
23
|
-
|
24
|
-
***********************************************************
|
25
|
-
|
26
|
-
If you are upgrading friendly_id, please run
|
27
|
-
|
28
|
-
./script/generate friendly_id --skip-migration
|
29
|
-
|
30
|
-
in your Rails application to ensure that you have the
|
31
|
-
latest friendly_id Rake tasks.
|
32
|
-
|
33
|
-
***********************************************************
|
34
|
-
|
35
|
-
EOM
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/clean'
|
6
|
+
|
7
|
+
CLEAN << "pkg" << "docs" << "coverage"
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
Rake::TestTask.new(:test) { |t| t.pattern = 'test/**/*_test.rb' }
|
12
|
+
Rake::GemPackageTask.new(eval(File.read("friendly_id.gemspec"))) { |pkg| }
|
13
|
+
Rake::RDocTask.new do |r|
|
14
|
+
r.rdoc_dir = "docs"
|
15
|
+
r.main = "README.rdoc"
|
16
|
+
r.rdoc_files.include "README.rdoc", "History.txt", "lib/**/*.rb"
|
36
17
|
end
|
37
18
|
|
38
|
-
|
19
|
+
begin
|
20
|
+
require "yard"
|
21
|
+
YARD::Rake::YardocTask.new do |t|
|
22
|
+
t.options = ["--output-dir=docs"]
|
23
|
+
end
|
24
|
+
rescue LoadError
|
25
|
+
end
|
39
26
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |r|
|
30
|
+
r.test_files = FileList['test/*_test.rb']
|
31
|
+
r.verbose = true
|
32
|
+
r.rcov_opts << "--exclude gems/*"
|
33
|
+
end
|
34
|
+
rescue LoadError
|
46
35
|
end
|
data/extras/README.txt
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
run "rm public/index.html"
|
2
|
+
gem "friendly_id"
|
3
|
+
gem "haml"
|
4
|
+
gem "will_paginate"
|
5
|
+
run "haml --rails ."
|
6
|
+
generate "friendly_id"
|
7
|
+
generate :haml_scaffold, "post title:string"
|
8
|
+
route "map.root :controller => 'posts', :action => 'index'"
|
9
|
+
rake "db:migrate"
|
10
|
+
rake "db:fixtures:load"
|
11
|
+
file 'app/models/post.rb',
|
12
|
+
%q{class Post < ActiveRecord::Base
|
13
|
+
has_friendly_id :title, :use_slug => true
|
14
|
+
end}
|
15
|
+
file 'test/fixtures/slugs.yml',
|
16
|
+
%q{
|
17
|
+
one:
|
18
|
+
name: mystring
|
19
|
+
sequence: 1
|
20
|
+
sluggable: one (Post)
|
21
|
+
|
22
|
+
two:
|
23
|
+
name: mystring
|
24
|
+
sequence: 2
|
25
|
+
sluggable: two (Post)
|
26
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
run "rm public/index.html"
|
2
|
+
inside 'vendor/plugins' do
|
3
|
+
run "git clone ../../../../ friendly_id"
|
4
|
+
end
|
5
|
+
gem "haml"
|
6
|
+
gem "will_paginate"
|
7
|
+
run "haml --rails ."
|
8
|
+
generate "friendly_id"
|
9
|
+
generate :haml_scaffold, "post title:string"
|
10
|
+
route "map.root :controller => 'posts', :action => 'index'"
|
11
|
+
rake "db:migrate"
|
12
|
+
rake "db:fixtures:load"
|
13
|
+
file 'app/models/post.rb',
|
14
|
+
%q{class Post < ActiveRecord::Base
|
15
|
+
has_friendly_id :title, :use_slug => true
|
16
|
+
end}
|
17
|
+
file 'test/fixtures/slugs.yml',
|
18
|
+
%q{
|
19
|
+
one:
|
20
|
+
name: mystring
|
21
|
+
sequence: 1
|
22
|
+
sluggable: one (Post)
|
23
|
+
|
24
|
+
two:
|
25
|
+
name: mystring
|
26
|
+
sequence: 2
|
27
|
+
sluggable: two (Post)
|
28
|
+
}
|
data/lib/friendly_id.rb
CHANGED
@@ -5,7 +5,7 @@ module FriendlyId::NonSluggableClassMethods
|
|
5
5
|
protected
|
6
6
|
|
7
7
|
def find_one(id, options) #:nodoc:#
|
8
|
-
if id.
|
8
|
+
if id.respond_to?(:to_str) && result = send("find_by_#{ friendly_id_options[:method] }", id.to_str, options)
|
9
9
|
result.send(:found_using_friendly_id=, true)
|
10
10
|
else
|
11
11
|
result = super id, options
|
@@ -15,9 +15,10 @@ module FriendlyId::NonSluggableClassMethods
|
|
15
15
|
|
16
16
|
def find_some(ids_and_names, options) #:nodoc:#
|
17
17
|
|
18
|
+
names, ids = ids_and_names.partition {|id_or_name| id_or_name.respond_to?(:to_str) && id_or_name.to_str }
|
18
19
|
results = with_scope :find => options do
|
19
|
-
find :all, :conditions => ["#{quoted_table_name}.#{primary_key} IN (?) OR #{friendly_id_options[:method]
|
20
|
-
|
20
|
+
find :all, :conditions => ["#{quoted_table_name}.#{primary_key} IN (?) OR #{friendly_id_options[:method]} IN (?)",
|
21
|
+
ids, names]
|
21
22
|
end
|
22
23
|
|
23
24
|
expected = expected_size(ids_and_names, options)
|
@@ -25,7 +26,7 @@ module FriendlyId::NonSluggableClassMethods
|
|
25
26
|
raise ActiveRecord::RecordNotFound, "Couldn't find all #{ name.pluralize } with IDs (#{ ids_and_names * ', ' }) AND #{ sanitize_sql options[:conditions] } (found #{ results.size } results, but was looking for #{ expected })"
|
26
27
|
end
|
27
28
|
|
28
|
-
results.each {|r| r.send(:found_using_friendly_id=, true) if
|
29
|
+
results.each {|r| r.send(:found_using_friendly_id=, true) if names.include?(r.friendly_id)}
|
29
30
|
|
30
31
|
results
|
31
32
|
|
@@ -6,6 +6,7 @@ module FriendlyId::SluggableClassMethods
|
|
6
6
|
def find_one(id_or_name, options) #:nodoc:#
|
7
7
|
|
8
8
|
scope = options.delete(:scope)
|
9
|
+
scope = scope.to_param if scope && scope.respond_to?(:to_param)
|
9
10
|
|
10
11
|
if id_or_name.is_a?(Integer) || id_or_name.kind_of?(ActiveRecord::Base)
|
11
12
|
return super(id_or_name, options)
|
@@ -23,7 +24,6 @@ module FriendlyId::SluggableClassMethods
|
|
23
24
|
}
|
24
25
|
|
25
26
|
result = with_scope(:find => find_options) { find_initial(options) }
|
26
|
-
|
27
27
|
if result
|
28
28
|
result.finder_slug_name = id_or_name
|
29
29
|
elsif id_or_name.to_i.to_s != id_or_name
|
@@ -1,18 +1,31 @@
|
|
1
1
|
module FriendlyId::SluggableInstanceMethods
|
2
2
|
|
3
3
|
def self.included(base)
|
4
|
-
base.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
if
|
9
|
-
|
4
|
+
base.class_eval do
|
5
|
+
has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
|
6
|
+
before_save :set_slug
|
7
|
+
after_save :set_slug_cache
|
8
|
+
# only protect the column if the class is not already using attributes_accessible
|
9
|
+
if !accessible_attributes
|
10
|
+
if friendly_id_options[:cache_column]
|
11
|
+
attr_protected friendly_id_options[:cache_column].to_sym
|
12
|
+
end
|
13
|
+
attr_protected :cached_slug
|
10
14
|
end
|
11
15
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
|
17
|
+
def base.cache_column
|
18
|
+
if defined?(@cache_column)
|
19
|
+
return @cache_column
|
20
|
+
elsif friendly_id_options[:cache_column]
|
21
|
+
@cache_column = friendly_id_options[:cache_column].to_sym
|
22
|
+
elsif columns.any? { |c| c.name == 'cached_slug' }
|
23
|
+
@cache_column = :cached_slug
|
24
|
+
else
|
25
|
+
@cache_column = nil
|
26
|
+
end
|
15
27
|
end
|
28
|
+
|
16
29
|
end
|
17
30
|
|
18
31
|
NUM_CHARS_RESERVED_FOR_FRIENDLY_ID_EXTENSION = 2
|
@@ -36,9 +49,7 @@ module FriendlyId::SluggableInstanceMethods
|
|
36
49
|
|
37
50
|
# Was the record found using an old friendly id?
|
38
51
|
def found_using_outdated_friendly_id?
|
39
|
-
if
|
40
|
-
return false if send(cache) == @finder_slug_name
|
41
|
-
end
|
52
|
+
return false if cache_column && send(cache_column) == @finder_slug_name
|
42
53
|
finder_slug.id != slug.id
|
43
54
|
end
|
44
55
|
|
@@ -73,10 +84,11 @@ module FriendlyId::SluggableInstanceMethods
|
|
73
84
|
|
74
85
|
# Returns the friendly id, or if none is available, the numeric id.
|
75
86
|
def to_param
|
76
|
-
if
|
77
|
-
|
87
|
+
if cache_column
|
88
|
+
read_attribute(cache_column) || id.to_s
|
89
|
+
else
|
90
|
+
slug ? slug.to_friendly_id : id.to_s
|
78
91
|
end
|
79
|
-
slug ? slug.to_friendly_id : id.to_s
|
80
92
|
end
|
81
93
|
|
82
94
|
# Get the processed string used as the basis of the friendly id.
|
@@ -105,6 +117,10 @@ module FriendlyId::SluggableInstanceMethods
|
|
105
117
|
|
106
118
|
private
|
107
119
|
|
120
|
+
def cache_column
|
121
|
+
self.class.cache_column
|
122
|
+
end
|
123
|
+
|
108
124
|
def finder_slug=(finder_slug)
|
109
125
|
@finder_slug_name = finder_slug.name
|
110
126
|
slug = finder_slug
|
@@ -130,14 +146,14 @@ private
|
|
130
146
|
end
|
131
147
|
# If we're renaming back to a previously used friendly_id, delete the
|
132
148
|
# slug so that we can recycle the name without having to use a sequence.
|
133
|
-
slugs.find(:all, :conditions => {:name => slug_text, :scope => scope}).each { |s| s.destroy }
|
149
|
+
slugs.find(:all, :conditions => {:name => slug_text, :scope => slug_attributes[:scope]}).each { |s| s.destroy }
|
134
150
|
slugs.build slug_attributes
|
135
151
|
end
|
136
152
|
end
|
137
153
|
|
138
154
|
def set_slug_cache
|
139
|
-
if
|
140
|
-
send "#{
|
155
|
+
if cache_column && send(cache_column) != slug.to_friendly_id
|
156
|
+
send "#{cache_column}=", slug.to_friendly_id
|
141
157
|
send :update_without_callbacks
|
142
158
|
end
|
143
159
|
end
|
data/lib/friendly_id/tasks.rb
CHANGED
@@ -19,8 +19,8 @@ module FriendlyId
|
|
19
19
|
klass = parse_class_name(klass)
|
20
20
|
validate_uses_slugs(klass)
|
21
21
|
Slug.destroy_all(["sluggable_type = ?", klass.to_s])
|
22
|
-
if klass.
|
23
|
-
klass.update_all("#{klass.
|
22
|
+
if klass.cache_column
|
23
|
+
klass.update_all("#{klass.cache_column} = NULL")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
data/lib/friendly_id/version.rb
CHANGED
data/test/cached_slug_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require File.dirname(__FILE__) + '/test_helper'
|
4
2
|
|
5
3
|
class CustomSlugNormalizerTest < Test::Unit::TestCase
|
@@ -7,29 +5,29 @@ class CustomSlugNormalizerTest < Test::Unit::TestCase
|
|
7
5
|
context "A slugged model using a custom slug generator" do
|
8
6
|
|
9
7
|
setup do
|
10
|
-
|
8
|
+
Person.friendly_id_options = FriendlyId::DEFAULT_OPTIONS.merge(:method => :name, :use_slug => true)
|
11
9
|
end
|
12
10
|
|
13
11
|
teardown do
|
14
|
-
|
12
|
+
Person.delete_all
|
15
13
|
Slug.delete_all
|
16
14
|
end
|
17
15
|
|
18
16
|
should "invoke the block code" do
|
19
|
-
|
20
|
-
assert_equal "
|
17
|
+
@person = Person.create!(:name => "Joe Schmoe")
|
18
|
+
assert_equal "JOE SCHMOE", @person.friendly_id
|
21
19
|
end
|
22
20
|
|
23
21
|
should "respect the max_length option" do
|
24
|
-
|
25
|
-
|
26
|
-
assert_equal "
|
22
|
+
Person.friendly_id_options = Person.friendly_id_options.merge(:max_length => 3)
|
23
|
+
@person = Person.create!(:name => "Joe Schmoe")
|
24
|
+
assert_equal "JOE", @person.friendly_id
|
27
25
|
end
|
28
26
|
|
29
27
|
should "respect the reserved option" do
|
30
|
-
|
28
|
+
Person.friendly_id_options = Person.friendly_id_options.merge(:reserved => ["JOE"])
|
31
29
|
assert_raises FriendlyId::SlugGenerationError do
|
32
|
-
|
30
|
+
Person.create!(:name => "Joe")
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
data/test/non_slugged_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require File.dirname(__FILE__) + '/test_helper'
|
4
2
|
|
5
3
|
class NonSluggedTest < Test::Unit::TestCase
|
@@ -7,7 +5,7 @@ class NonSluggedTest < Test::Unit::TestCase
|
|
7
5
|
context "A non-slugged model with default FriendlyId options" do
|
8
6
|
|
9
7
|
setup do
|
10
|
-
@user = User.create!(:
|
8
|
+
@user = User.create!(:name => "joe")
|
11
9
|
end
|
12
10
|
|
13
11
|
teardown do
|
@@ -52,7 +50,7 @@ class NonSluggedTest < Test::Unit::TestCase
|
|
52
50
|
end
|
53
51
|
|
54
52
|
should "not validate if the friendly_id text is reserved" do
|
55
|
-
user = User.new(:
|
53
|
+
user = User.new(:name => "new")
|
56
54
|
assert !user.valid?
|
57
55
|
end
|
58
56
|
|
@@ -61,7 +59,7 @@ class NonSluggedTest < Test::Unit::TestCase
|
|
61
59
|
end
|
62
60
|
|
63
61
|
should "return its id if the friendly_id is null" do
|
64
|
-
@user.
|
62
|
+
@user.name = nil
|
65
63
|
assert_equal @user.id.to_s, @user.to_param
|
66
64
|
end
|
67
65
|
|
@@ -69,7 +67,7 @@ class NonSluggedTest < Test::Unit::TestCase
|
|
69
67
|
context "when using an array as the find argument" do
|
70
68
|
|
71
69
|
setup do
|
72
|
-
@user2 = User.create(:
|
70
|
+
@user2 = User.create(:name => "jane")
|
73
71
|
end
|
74
72
|
|
75
73
|
should "return results" do
|
@@ -89,7 +87,7 @@ class NonSluggedTest < Test::Unit::TestCase
|
|
89
87
|
end
|
90
88
|
|
91
89
|
should "indicate if the results were found using a friendly_id" do
|
92
|
-
users = User.find([@user.id, @user2.friendly_id], :order => "
|
90
|
+
users = User.find([@user.id, @user2.friendly_id], :order => "name ASC")
|
93
91
|
assert users[0].found_using_friendly_id?
|
94
92
|
assert users[1].found_using_numeric_id?
|
95
93
|
end
|