nateabbott-friendly_id 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +133 -0
- data/MIT-LICENSE +19 -0
- data/Manifest.txt +39 -0
- data/README.rdoc +343 -0
- data/Rakefile +49 -0
- data/config/website.yml +2 -0
- data/friendly_id.gemspec +45 -0
- data/generators/friendly_id/friendly_id_generator.rb +12 -0
- data/generators/friendly_id/templates/create_slugs.rb +18 -0
- data/generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb +11 -0
- data/generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb +19 -0
- data/init.rb +3 -0
- data/lib/friendly_id/helpers.rb +15 -0
- data/lib/friendly_id/non_sluggable_class_methods.rb +42 -0
- data/lib/friendly_id/non_sluggable_instance_methods.rb +43 -0
- data/lib/friendly_id/slug.rb +102 -0
- data/lib/friendly_id/sluggable_class_methods.rb +116 -0
- data/lib/friendly_id/sluggable_instance_methods.rb +116 -0
- data/lib/friendly_id/version.rb +10 -0
- data/lib/friendly_id.rb +101 -0
- data/lib/tasks/friendly_id.rake +50 -0
- data/lib/tasks/friendly_id.rb +1 -0
- data/test/contest.rb +94 -0
- data/test/custom_slug_normalizer_test.rb +35 -0
- data/test/models/book.rb +2 -0
- data/test/models/country.rb +4 -0
- data/test/models/event.rb +3 -0
- data/test/models/novel.rb +3 -0
- data/test/models/person.rb +6 -0
- data/test/models/post.rb +6 -0
- data/test/models/thing.rb +6 -0
- data/test/models/user.rb +3 -0
- data/test/non_slugged_test.rb +98 -0
- data/test/schema.rb +55 -0
- data/test/scoped_model_test.rb +53 -0
- data/test/slug_test.rb +106 -0
- data/test/slugged_model_test.rb +284 -0
- data/test/sti_test.rb +48 -0
- data/test/test_helper.rb +30 -0
- metadata +155 -0
data/History.txt
ADDED
@@ -0,0 +1,133 @@
|
|
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
|
+
|
26
|
+
== 2.0.4 2009-02-12
|
27
|
+
|
28
|
+
* 1 major enhancment:
|
29
|
+
* You can now pass in your own custom slug generation blocks while setting up friendly_id.
|
30
|
+
|
31
|
+
== 2.0.3 2009-02-11
|
32
|
+
|
33
|
+
* 1 minor enhancment:
|
34
|
+
* Fixed to_param returning an empty string for non-slugged models with a null friendly_id.
|
35
|
+
|
36
|
+
== 2.0.2 2009-02-09
|
37
|
+
|
38
|
+
* 2 major enhancements:
|
39
|
+
* Made FriendlyId depend only on ActiveRecord. It should now be possible to
|
40
|
+
use FriendlyId with Camping or any other codebase that uses AR.
|
41
|
+
* Overhauled creaky testing setup and switched to Shoulda.
|
42
|
+
|
43
|
+
* 1 minor enhancment:
|
44
|
+
* Made reserved words work for non-slugged models.
|
45
|
+
|
46
|
+
== 2.0.1 2009-01-19
|
47
|
+
|
48
|
+
* 1 minor enhancements:
|
49
|
+
* Fix infinite redirect bug when using .has_better_id? in your controllers (Sean Abrahams)
|
50
|
+
|
51
|
+
|
52
|
+
== 2.0.0 2009-01-03
|
53
|
+
|
54
|
+
* 5 major enhancements:
|
55
|
+
* Support for scoped slugs (Norman Clarke)
|
56
|
+
* Support for UTF-8 friendly_ids (Norman Clarke)
|
57
|
+
* Can now be installed via Ruby Gems, or as a Rails plugin (Norman Clarke)
|
58
|
+
* Improved handling of non-unique slugs (Norman Clarke and Adrian Mugnolo)
|
59
|
+
* 2 minor enhancements:
|
60
|
+
* Shoulda macro (Josh Nichols)
|
61
|
+
* Various small bugfixes, cleanups and refactorings
|
62
|
+
|
63
|
+
== 2008-12-01
|
64
|
+
|
65
|
+
* Fixed bug that may return invalid records having similar id/names and using MySQL. (Emilio Tagua)
|
66
|
+
* Fixed slug generation to increment only numeric extension without modifying the name on duplicated slugs. (Emilio Tagua)
|
67
|
+
|
68
|
+
== 2008-10-31
|
69
|
+
|
70
|
+
* Fixed compatibility with Rails 2.0.x. (Norman Clarke)
|
71
|
+
* friendly_id::make_slugs update records in chunks of 1000 to avoid running out of memory with large datasets. (Tim Kadom)
|
72
|
+
* Fixed logic error with slug name collisions. Thanks to Tim Kadom for reporting this bug.
|
73
|
+
|
74
|
+
== 2008-10-22
|
75
|
+
|
76
|
+
* Reverted use of UTF8Handler - was causing errors for some people (Bence Nagy)
|
77
|
+
* Corrected find in case if a friendly_id begins with number (Bence Nagy)
|
78
|
+
* Added ability to reserve words from slugs (Adam Cigánek)
|
79
|
+
|
80
|
+
== 2008-10-09
|
81
|
+
|
82
|
+
* Moved "require"" for iconv to init.rb (Florian Aßmann)
|
83
|
+
* Removed "require" for Unicode, use Rails' handler instead (Florian Aßmann)
|
84
|
+
* Replaced some magic numbers with constants (Florian Aßmann)
|
85
|
+
* Don't overwrite find, alias_method_chain find_one and find_some instead (Florian Aßmann)
|
86
|
+
* Slugs behave more like ids now (Florian Aßmann)
|
87
|
+
* Can find by mixture of ids and slugs (Florian Aßmann)
|
88
|
+
* Reformatted code and comments (Florian Aßmann)
|
89
|
+
* Added support for Edge Rails' Inflector::parameterize (Norman Clarke)
|
90
|
+
|
91
|
+
== 2008-08-25
|
92
|
+
|
93
|
+
* Moved strip_diacritics into Slug for easier reuse/better organization.
|
94
|
+
* Put class methods inside class << self block. (Norman Clarke)
|
95
|
+
|
96
|
+
* Small change to allow friendly_id to work better with STI. (David Ramalho)
|
97
|
+
|
98
|
+
== 2008-07-14
|
99
|
+
|
100
|
+
* Improved slug generation for friendly id's with apostrophes. (alistairholt)
|
101
|
+
* Added support for namespaced models in Rakefile. (David Ramalho)
|
102
|
+
|
103
|
+
== 2008-06-23
|
104
|
+
|
105
|
+
* Cached most recent slug to improve performance (Emilio Tagua).
|
106
|
+
|
107
|
+
== 2008-06-10
|
108
|
+
|
109
|
+
* Added ability to find friendly_ids by array (Emilio Tagua)
|
110
|
+
|
111
|
+
== 2008-05-15
|
112
|
+
|
113
|
+
* Made friendly_id raise an error if slug method returns a blank value.
|
114
|
+
|
115
|
+
== 2008-05-12
|
116
|
+
|
117
|
+
* Added experimental Github gemspec.
|
118
|
+
|
119
|
+
== 2008-04-18
|
120
|
+
|
121
|
+
* Improved slug name collision avoidance.
|
122
|
+
|
123
|
+
== 2008-03-13
|
124
|
+
|
125
|
+
* Added :dependent => :destroy to slug relation, as suggested by Emilio Tagua.
|
126
|
+
* Fixed error when renaming a slugged item back to a previously used name.
|
127
|
+
* Incorporated documentation changes suggested by Jesse Crouch and Chris Nolan.
|
128
|
+
|
129
|
+
== 2008-02-07
|
130
|
+
|
131
|
+
* Applied patches from blog commenter "suntzu" to fix problem with model values were being overwritten.
|
132
|
+
* Applied patch from Dan Blue to make friendly_id no longer ignore options on ActiveRecordBase#find.
|
133
|
+
* Added call to options.assert_valid_keys in has_friendly_id. Thanks to W. Andrew Loe III for pointing out that this was missing.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 Norman Clarke and Adrian Mugnolo.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/Manifest.txt
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
History.txt
|
2
|
+
MIT-LICENSE
|
3
|
+
Manifest.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
config/website.yml
|
7
|
+
friendly_id.gemspec
|
8
|
+
generators/friendly_id/friendly_id_generator.rb
|
9
|
+
generators/friendly_id/templates/create_slugs.rb
|
10
|
+
generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb
|
11
|
+
generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb
|
12
|
+
init.rb
|
13
|
+
lib/friendly_id.rb
|
14
|
+
lib/friendly_id/helpers.rb
|
15
|
+
lib/friendly_id/non_sluggable_class_methods.rb
|
16
|
+
lib/friendly_id/non_sluggable_instance_methods.rb
|
17
|
+
lib/friendly_id/slug.rb
|
18
|
+
lib/friendly_id/sluggable_class_methods.rb
|
19
|
+
lib/friendly_id/sluggable_instance_methods.rb
|
20
|
+
lib/friendly_id/version.rb
|
21
|
+
lib/tasks/friendly_id.rake
|
22
|
+
lib/tasks/friendly_id.rb
|
23
|
+
test/contest.rb
|
24
|
+
test/custom_slug_normalizer_test.rb
|
25
|
+
test/models/book.rb
|
26
|
+
test/models/country.rb
|
27
|
+
test/models/event.rb
|
28
|
+
test/models/novel.rb
|
29
|
+
test/models/person.rb
|
30
|
+
test/models/post.rb
|
31
|
+
test/models/thing.rb
|
32
|
+
test/models/user.rb
|
33
|
+
test/non_slugged_test.rb
|
34
|
+
test/schema.rb
|
35
|
+
test/scoped_model_test.rb
|
36
|
+
test/slug_test.rb
|
37
|
+
test/slugged_model_test.rb
|
38
|
+
test/sti_test.rb
|
39
|
+
test/test_helper.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,343 @@
|
|
1
|
+
= FriendlyId
|
2
|
+
|
3
|
+
FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
|
4
|
+
Ruby on Rails. It allows you to create pretty URL's and work with
|
5
|
+
human-friendly strings as if they were numeric ids for ActiveRecord models.
|
6
|
+
|
7
|
+
Using FriendlyId, it's easy to make your application use URL's like:
|
8
|
+
|
9
|
+
http://example.com/states/washington
|
10
|
+
|
11
|
+
instead of:
|
12
|
+
|
13
|
+
http://example.com/states/4323454
|
14
|
+
|
15
|
+
Want to find out more? Read on. The {most recent version of the FriendlyId
|
16
|
+
RDocs}[http://friendly-id.rubyforge.org] can always be found on
|
17
|
+
Rubyforge[http://www.rubyforge.org].
|
18
|
+
|
19
|
+
=== Why?
|
20
|
+
|
21
|
+
* Text-based id's look better
|
22
|
+
* They make URL's easier to remember.
|
23
|
+
* They give no hint about the number of records in your database.
|
24
|
+
* They are better for search engine optimization.
|
25
|
+
|
26
|
+
=== But...
|
27
|
+
|
28
|
+
* They can change, breaking your URL's and your SEO.
|
29
|
+
* It can be tricky to ensure they're always unique.
|
30
|
+
* They can become a pain to manage in large Rails applications.
|
31
|
+
* They can conflict with your application's namespace.
|
32
|
+
|
33
|
+
FriendlyId tries to offer you the all the advantages, and avoid or soften the
|
34
|
+
potential impact of the disadvantages.
|
35
|
+
|
36
|
+
== Typical Uses
|
37
|
+
|
38
|
+
=== User names ("non-slugged" models)
|
39
|
+
|
40
|
+
Usually users have unique user names stored in a column with a unique
|
41
|
+
constraint or index. In this case, all you need to do is add this to your
|
42
|
+
model:
|
43
|
+
|
44
|
+
has_friendly_id :login
|
45
|
+
|
46
|
+
and you can then write code like this:
|
47
|
+
|
48
|
+
@member = Member.find("joe") # the old Member.find(1) still works, too.
|
49
|
+
@member.to_param # returns "joe"
|
50
|
+
redirect_to @member # The URL would be /members/joe
|
51
|
+
|
52
|
+
=== Blog posts ("slugged" models)
|
53
|
+
|
54
|
+
Blog posts generally have titles which are distinctive but not necessarily
|
55
|
+
unique. In this and similar cases, FriendlyId provides a Slug model separate
|
56
|
+
from your Post model. The Slug model handles duplicate friendly_ids, as well
|
57
|
+
as versioning.
|
58
|
+
|
59
|
+
Your model code would look something like this:
|
60
|
+
|
61
|
+
has_friendly_id :title, :use_slug => true
|
62
|
+
|
63
|
+
and you can then write code like this:
|
64
|
+
|
65
|
+
@post = Post.find("new-version-released") # Post.find(1) still works, too
|
66
|
+
@post.to_param # returns "new-version-released"
|
67
|
+
redirect_to @post # The URL would be /posts/new-version-released
|
68
|
+
|
69
|
+
Now in your controllers, if you want to prevent people from accessing your
|
70
|
+
models by numeric id, you can detect whether they were found by the
|
71
|
+
friendly_id:
|
72
|
+
|
73
|
+
@post = Post.find(params[:id])
|
74
|
+
raise "some error" if !@post.found_using_friendly_id?
|
75
|
+
|
76
|
+
or, you can 301 redirect if the model was found by the numeric id if you don't
|
77
|
+
care about numeric access, but want the SEO value of the friendly_id:
|
78
|
+
|
79
|
+
@post = Post.find(params[:id])
|
80
|
+
redirect_to @post, :status => 301 if @post.has_better_id?
|
81
|
+
|
82
|
+
The "has_better_id?" method returns true if the model was found with the
|
83
|
+
numeric id, or with an outdated slug.
|
84
|
+
|
85
|
+
== Extra Features
|
86
|
+
|
87
|
+
=== Slug Versioning
|
88
|
+
|
89
|
+
FriendlyId will record changes to slugs so that you can tell when the model is
|
90
|
+
found with an older slug, or by the numeric id. This can be useful if you want
|
91
|
+
to do a 301 redirect to your updated URL.
|
92
|
+
|
93
|
+
class PostsController < ApplicationController
|
94
|
+
|
95
|
+
before_filter ensure_current_post_url, :only => :show
|
96
|
+
|
97
|
+
...
|
98
|
+
|
99
|
+
def ensure_current_post_url
|
100
|
+
redirect_to @post, :status => :moved_permanently if @post.has_better_id?
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
This is particularly useful when implementing FrindlyId on an existing
|
106
|
+
website that already has many URL's with the old numeric id listed on search
|
107
|
+
engines. When the search engine spiders crawl your site, they will
|
108
|
+
eventually pick up the new, more SEO-friendly URL's.
|
109
|
+
|
110
|
+
=== Non-unique Slug Names
|
111
|
+
|
112
|
+
FriendlyId will append a arbitrary number to the end of the id to keep it
|
113
|
+
unique if necessary:
|
114
|
+
|
115
|
+
/posts/new-version-released
|
116
|
+
/posts/new-version-released--2
|
117
|
+
/posts/new-version-released--3
|
118
|
+
...
|
119
|
+
etc.
|
120
|
+
|
121
|
+
Note that the number is preceeded by two dashes to distinguish it from the
|
122
|
+
rest of the slug. This is important to enable having slugs like:
|
123
|
+
|
124
|
+
/cars/peugeot-206
|
125
|
+
/cars/peugeot-206--2
|
126
|
+
|
127
|
+
=== Reserved Names
|
128
|
+
|
129
|
+
You can mark off some strings as reserved so that, for example, you don't end
|
130
|
+
up with this problem:
|
131
|
+
|
132
|
+
/users/joe-schmoe # A user chose "joe schmoe" as his user name - no worries.
|
133
|
+
/users/new # A user chose "new" as his user name, and now no one can sign up.
|
134
|
+
|
135
|
+
Here's how to do it:
|
136
|
+
|
137
|
+
class Restaurant < ActiveRecord::Base
|
138
|
+
belongs_to :city
|
139
|
+
has_friendly_id :name, :use_slug => true, :reserved => ["my", "values"]
|
140
|
+
end
|
141
|
+
|
142
|
+
As of FriendlyId version 2.0.2, "new" and "index" are reseved by default. When
|
143
|
+
you attempt to store a reserved value, FriendlyId raises a
|
144
|
+
FriendlyId::SlugGenerationError.
|
145
|
+
|
146
|
+
|
147
|
+
=== Scoped Slugs
|
148
|
+
|
149
|
+
FriendlyId can generate unique slugs within a given scope. For example:
|
150
|
+
|
151
|
+
class Restaurant < ActiveRecord::Base
|
152
|
+
belongs_to :city
|
153
|
+
has_friendly_id :name, :use_slug => true, :scope => :city
|
154
|
+
end
|
155
|
+
|
156
|
+
class City < ActiveRecord::Base
|
157
|
+
has_many :restaurants
|
158
|
+
has_friendly_id :name, :use_slug => true
|
159
|
+
end
|
160
|
+
|
161
|
+
http://example.org/cities/seattle/restaurants/joes-diner
|
162
|
+
http://example.org/cities/chicago/restaurants/joes-diner
|
163
|
+
|
164
|
+
Restaurant.find("joes-diner", :scope => "seattle") # returns 1 record
|
165
|
+
Restaurant.find("joes-diner", :scope => "chicago") # returns 1 record
|
166
|
+
Restaurant.find("joes-diner") # returns both records
|
167
|
+
|
168
|
+
|
169
|
+
The value for the :scope key in your model can be a custom method you define,
|
170
|
+
or the name of a relation. If it's the name of a relation, then the scope's
|
171
|
+
text value will be the result of calling <code>to_param</code> on the related
|
172
|
+
model record. In the example above, the city model also uses FriendlyId and so
|
173
|
+
its <code>to_param</code> method returns its friendly_id: chicago or seattle.
|
174
|
+
|
175
|
+
This feature is new in FriendlyId 2 and should be considered of experimental
|
176
|
+
quality. Please don't use this for code that needs to run on the Space
|
177
|
+
Shuttle.
|
178
|
+
|
179
|
+
=== Text Normalization
|
180
|
+
|
181
|
+
FriendlyId's slugging can strip diacritics from Western European characters,
|
182
|
+
so that you can have ASCII-only URL's; for example, conveting "ñøîéçü" to
|
183
|
+
"noiecu."
|
184
|
+
|
185
|
+
has_friendly_id :title, :use_slug => true, :strip_diacritics => true
|
186
|
+
|
187
|
+
If you are not using slugs, you'll have to do this manually for whatever value
|
188
|
+
you're using as the friendly_id.
|
189
|
+
|
190
|
+
=== Diacritic-sensitive normalization
|
191
|
+
|
192
|
+
FriendlyId can also normalize slug text while preserving accented characters, if
|
193
|
+
you prefer to leave them in your URL's:
|
194
|
+
|
195
|
+
has_friendly_id :title, :use_slug => true
|
196
|
+
...
|
197
|
+
@post = Post.create(:title => "¡Feliz Año!")
|
198
|
+
@post.friendly_id # "feliz-año"
|
199
|
+
|
200
|
+
=== Unicode URL's
|
201
|
+
|
202
|
+
FriendlyId can generate slugs in any language that can be written with
|
203
|
+
Unicode. It does its best to strip away punctuation regardless of the language
|
204
|
+
being used. Since the authors only speak English, Spanish, Portuguese and
|
205
|
+
German, this has not been extensively tested with anything like Chinese,
|
206
|
+
Russian, Greek, etc, but it "should work." If you're a speaker of a language
|
207
|
+
that uses a non-Roman writing system, your feedback would be most welcome.
|
208
|
+
|
209
|
+
has_friendly_id :title, :use_slug => true
|
210
|
+
...
|
211
|
+
@post = Post.create(:title => "友好编号在中国")
|
212
|
+
@post.friendly_id # "友好编号在中国"
|
213
|
+
@post2 = Post.create(:title => "友好编号在中国")
|
214
|
+
@post2.friendly_id # "友好编号在中国--2"
|
215
|
+
|
216
|
+
=== Custom Slug Generation
|
217
|
+
|
218
|
+
While FriendlyId's slug generation options work for most people, you may need
|
219
|
+
something else. As of version 2.0.4 you can pass in your own custom slug
|
220
|
+
generation block:
|
221
|
+
|
222
|
+
class Post < ActiveRecord::Base
|
223
|
+
has_friendly_id :title, :use_slug => true do |text|
|
224
|
+
MySlugGeneratorClass::my_slug_method(text)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
FriendlyId will still respect your settings for max length and reserved words,
|
229
|
+
but will use your block rather than the baked-in methods to normalize the
|
230
|
+
friendly_id text.
|
231
|
+
|
232
|
+
== Getting it
|
233
|
+
|
234
|
+
FriendlyId is best installed as a Ruby Gem:
|
235
|
+
|
236
|
+
gem install friendly_id
|
237
|
+
|
238
|
+
Alternatively, you can install it as a Rails plugin, though this is
|
239
|
+
discouraged:
|
240
|
+
|
241
|
+
./script/plugin install git://github.com/norman/friendly_id.git
|
242
|
+
|
243
|
+
== Setting it up
|
244
|
+
|
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.
|
248
|
+
|
249
|
+
1) Install the Gem:
|
250
|
+
|
251
|
+
sudo gem install friendly_id
|
252
|
+
cd my_app
|
253
|
+
script/generate friendly_id
|
254
|
+
rake db:migrate
|
255
|
+
|
256
|
+
2) Load FriendlyId in your app:
|
257
|
+
|
258
|
+
# Rails 2.1 and higher; add this to the gem section of environment.rb:
|
259
|
+
config.gem "friendly_id"
|
260
|
+
|
261
|
+
# Rails 2.0; this goes at the bottom of environment.rb
|
262
|
+
require 'friendly_id'
|
263
|
+
|
264
|
+
3) Add some code to your models:
|
265
|
+
|
266
|
+
class Post < ActiveRecord::Base
|
267
|
+
has_friendly_id :title, :use_slug => true
|
268
|
+
end
|
269
|
+
|
270
|
+
4) If you are using slugs, you can use a Rake task to generate slugs for your
|
271
|
+
existing records:
|
272
|
+
|
273
|
+
rake friendly_id:make_slugs MODEL=MyModelName
|
274
|
+
|
275
|
+
If you eventually want to expire old slugs every so often, or perhaps every
|
276
|
+
day via cron, you can do:
|
277
|
+
|
278
|
+
rake friendly_id:remove_old_slugs
|
279
|
+
|
280
|
+
The default is to remove dead slugs older than 45 days, but is configurable:
|
281
|
+
|
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.
|
294
|
+
|
295
|
+
== Upgrading from an older version
|
296
|
+
|
297
|
+
If you installed an older version of FriendlyId and want to upgrade to 2.0.x,
|
298
|
+
follow these steps:
|
299
|
+
|
300
|
+
==== Install the friendly_id Gem:
|
301
|
+
|
302
|
+
sudo gem install friendly_id
|
303
|
+
|
304
|
+
==== Add FriendlyId to environment.rb:
|
305
|
+
|
306
|
+
===== For Rails 2.1 and higher:
|
307
|
+
|
308
|
+
config.gem "friendly_id"
|
309
|
+
|
310
|
+
===== For Rails 2.0:
|
311
|
+
|
312
|
+
Add this to the bottom of environment.rb:
|
313
|
+
|
314
|
+
require 'friendly_id'
|
315
|
+
|
316
|
+
==== Remove the older version of FriendlyId:
|
317
|
+
|
318
|
+
git rm -rf vendor/plugins/friendly_id
|
319
|
+
svn delete vendor/plugins/friendly_id
|
320
|
+
# or whatever
|
321
|
+
|
322
|
+
==== Generate the upgrade migration and run it
|
323
|
+
|
324
|
+
./script/generate friendly_id_20_upgrade
|
325
|
+
rake db:migrate
|
326
|
+
|
327
|
+
== Hacking FriendlyId:
|
328
|
+
|
329
|
+
FriendlyId is {hosted on Github}[git://github.com/norman/friendly_id.git], and
|
330
|
+
we love pull requests. :-)
|
331
|
+
|
332
|
+
== Bugs:
|
333
|
+
|
334
|
+
Please report them on Lighthouse[http://randomba.lighthouseapp.com/projects/14675-friendly_id].
|
335
|
+
|
336
|
+
|
337
|
+
== Credits:
|
338
|
+
|
339
|
+
FriendlyId was created by {Norman Clarke}[mailto:norman@randomba.org],
|
340
|
+
{Adrian Mugnolo}[mailto:adrian@randomba.org], and {Emilio Tagua}[mailto:miloops@gmail.com].
|
341
|
+
|
342
|
+
Copyright (c) 2008 Norman Clarke, Adrian Mugnolo and Emilio Tagua, released
|
343
|
+
under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'newgem'
|
2
|
+
require 'lib/friendly_id/version'
|
3
|
+
|
4
|
+
$hoe = Hoe.new("friendly_id", FriendlyId::Version::STRING) do |p|
|
5
|
+
p.rubyforge_name = "friendly-id"
|
6
|
+
p.author = ['Norman Clarke', 'Adrian Mugnolo', 'Emilio Tagua']
|
7
|
+
p.email = ['norman@rubysouth.com', 'adrian@rubysouth.com', 'miloops@gmail.com']
|
8
|
+
p.summary = "A comprehensive slugging and pretty-URL plugin for ActiveRecord."
|
9
|
+
p.description = 'A comprehensive slugging and pretty-URL plugin for ActiveRecord.'
|
10
|
+
p.url = 'http://friendly-id.rubyforge.org/'
|
11
|
+
p.test_globs = ['test/**/*_test.rb']
|
12
|
+
p.extra_deps << ['activerecord', '>= 2.0.0']
|
13
|
+
p.extra_deps << ['activesupport', '>= 2.0.0']
|
14
|
+
p.extra_dev_deps << ['newgem', ">= #{::Newgem::VERSION}"]
|
15
|
+
p.extra_dev_deps << ['sqlite3-ruby']
|
16
|
+
p.remote_rdoc_dir = ""
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'newgem/tasks'
|
20
|
+
|
21
|
+
desc "Run RCov"
|
22
|
+
task :rcov do
|
23
|
+
run_coverage Dir["test/**/*_test.rb"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def run_coverage(files)
|
27
|
+
rm_f "coverage"
|
28
|
+
rm_f "coverage.data"
|
29
|
+
if files.length == 0
|
30
|
+
puts "No files were specified for testing"
|
31
|
+
return
|
32
|
+
end
|
33
|
+
files = files.join(" ")
|
34
|
+
# if RUBY_PLATFORM =~ /darwin/
|
35
|
+
# exclude = '--exclude "gems/"'
|
36
|
+
# else
|
37
|
+
# exclude = '--exclude "rubygems"'
|
38
|
+
# end
|
39
|
+
rcov = ENV["RCOV"] ? ENV["RCOV"] : "rcov"
|
40
|
+
sh "#{rcov} -Ilib:test --sort coverage --text-report #{files}"
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'Publish RDoc to RubyForge.'
|
44
|
+
task :publish_docs => [:clean, :docs] do
|
45
|
+
host = "compay@rubyforge.org"
|
46
|
+
remote_dir = "/var/www/gforge-projects/friendly-id"
|
47
|
+
local_dir = 'doc'
|
48
|
+
sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
|
49
|
+
end
|
data/config/website.yml
ADDED
data/friendly_id.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{friendly_id}
|
5
|
+
s.version = "2.1.4"
|
6
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
7
|
+
s.authors = ["Norman Clarke", "Adrian Mugnolo", "Emilio Tagua", "Nate Abbott"]
|
8
|
+
s.date = %q{2009-06-03}
|
9
|
+
s.description = %q{A comprehensive slugging and pretty-URL plugin for ActiveRecord.}
|
10
|
+
s.email = ["norman@rubysouth.com", "adrian@rubysouth.com", "miloops@gmail.com", "nate@everlater.com"]
|
11
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
|
12
|
+
s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "config/website.yml", "friendly_id.gemspec", "generators/friendly_id/friendly_id_generator.rb", "generators/friendly_id/templates/create_slugs.rb", "generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb", "generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb", "init.rb", "lib/friendly_id.rb", "lib/friendly_id/helpers.rb", "lib/friendly_id/non_sluggable_class_methods.rb", "lib/friendly_id/non_sluggable_instance_methods.rb", "lib/friendly_id/slug.rb", "lib/friendly_id/sluggable_class_methods.rb", "lib/friendly_id/sluggable_instance_methods.rb", "lib/friendly_id/version.rb", "lib/tasks/friendly_id.rake", "lib/tasks/friendly_id.rb", "test/contest.rb", "test/custom_slug_normalizer_test.rb", "test/models/book.rb", "test/models/country.rb", "test/models/event.rb", "test/models/novel.rb", "test/models/person.rb", "test/models/post.rb", "test/models/thing.rb", "test/models/user.rb", "test/non_slugged_test.rb", "test/schema.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/slugged_model_test.rb", "test/sti_test.rb", "test/test_helper.rb"]
|
13
|
+
s.homepage = %q{http://friendly-id.rubyforge.org/}
|
14
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.rubyforge_project = %q{nate_friendly-id}
|
17
|
+
s.rubygems_version = %q{1.3.3}
|
18
|
+
s.summary = %q{A comprehensive slugging and pretty-URL plugin for ActiveRecord.}
|
19
|
+
s.test_files = ["test/custom_slug_normalizer_test.rb", "test/non_slugged_test.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/slugged_model_test.rb", "test/sti_test.rb"]
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 2.0.0"])
|
27
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.0.0"])
|
28
|
+
s.add_development_dependency(%q<newgem>, [">= 1.4.1"])
|
29
|
+
s.add_development_dependency(%q<sqlite3-ruby>, [">= 0"])
|
30
|
+
s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<activerecord>, [">= 2.0.0"])
|
33
|
+
s.add_dependency(%q<activesupport>, [">= 2.0.0"])
|
34
|
+
s.add_dependency(%q<newgem>, [">= 1.4.1"])
|
35
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
36
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
37
|
+
end
|
38
|
+
else
|
39
|
+
s.add_dependency(%q<activerecord>, [">= 2.0.0"])
|
40
|
+
s.add_dependency(%q<activesupport>, [">= 2.0.0"])
|
41
|
+
s.add_dependency(%q<newgem>, [">= 1.4.1"])
|
42
|
+
s.add_dependency(%q<sqlite3-ruby>, [">= 0"])
|
43
|
+
s.add_dependency(%q<hoe>, [">= 1.8.0"])
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class FriendlyIdGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
unless options[:skip_migration]
|
5
|
+
m.migration_template(
|
6
|
+
'create_slugs.rb', 'db/migrate', :migration_file_name => 'create_slugs'
|
7
|
+
)
|
8
|
+
m.file "/../../../lib/tasks/friendly_id.rake", "lib/tasks/friendly_id.rake"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateSlugs < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :slugs do |t|
|
4
|
+
t.string :name
|
5
|
+
t.integer :sluggable_id
|
6
|
+
t.integer :sequence, :null => false, :default => 1
|
7
|
+
t.string :sluggable_type, :limit => 40
|
8
|
+
t.string :scope, :limit => 40
|
9
|
+
t.datetime :created_at
|
10
|
+
end
|
11
|
+
add_index :slugs, [:name, :sluggable_type, :scope, :sequence], :unique => true
|
12
|
+
add_index :slugs, :sluggable_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :slugs
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class FriendlyId20UpgradeGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
unless options[:skip_migration]
|
5
|
+
m.migration_template(
|
6
|
+
'upgrade_friendly_id_to_20.rb', 'db/migrate', :migration_file_name => 'upgrade_friendly_id_to_20'
|
7
|
+
)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|