nwp-friendly_id 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/History.txt +133 -0
  2. data/MIT-LICENSE +19 -0
  3. data/Manifest.txt +39 -0
  4. data/README.rdoc +343 -0
  5. data/Rakefile +49 -0
  6. data/config/website.yml +2 -0
  7. data/friendly_id.gemspec +45 -0
  8. data/generators/friendly_id/friendly_id_generator.rb +12 -0
  9. data/generators/friendly_id/templates/create_slugs.rb +18 -0
  10. data/generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb +11 -0
  11. data/generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb +19 -0
  12. data/init.rb +3 -0
  13. data/lib/friendly_id.rb +101 -0
  14. data/lib/friendly_id/helpers.rb +15 -0
  15. data/lib/friendly_id/non_sluggable_class_methods.rb +42 -0
  16. data/lib/friendly_id/non_sluggable_instance_methods.rb +43 -0
  17. data/lib/friendly_id/slug.rb +102 -0
  18. data/lib/friendly_id/sluggable_class_methods.rb +116 -0
  19. data/lib/friendly_id/sluggable_instance_methods.rb +115 -0
  20. data/lib/friendly_id/version.rb +10 -0
  21. data/lib/tasks/friendly_id.rake +50 -0
  22. data/lib/tasks/friendly_id.rb +1 -0
  23. data/test/contest.rb +94 -0
  24. data/test/custom_slug_normalizer_test.rb +35 -0
  25. data/test/models/book.rb +2 -0
  26. data/test/models/country.rb +4 -0
  27. data/test/models/event.rb +3 -0
  28. data/test/models/novel.rb +3 -0
  29. data/test/models/person.rb +6 -0
  30. data/test/models/post.rb +6 -0
  31. data/test/models/thing.rb +6 -0
  32. data/test/models/user.rb +3 -0
  33. data/test/non_slugged_test.rb +98 -0
  34. data/test/schema.rb +55 -0
  35. data/test/scoped_model_test.rb +53 -0
  36. data/test/slug_test.rb +106 -0
  37. data/test/slugged_model_test.rb +284 -0
  38. data/test/sti_test.rb +48 -0
  39. data/test/test_helper.rb +30 -0
  40. metadata +154 -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.