friendly_id 5.0.0.alpha.1 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +2 -1
- data/CONTRIBUTING.md +36 -0
- data/Changelog.md +14 -7
- data/{Guide.rdoc → Guide.md} +172 -155
- data/README.md +9 -8
- data/Rakefile +2 -3
- data/bench.rb +5 -3
- data/friendly_id.gemspec +9 -8
- data/lib/friendly_id.rb +7 -8
- data/lib/friendly_id/base.rb +31 -17
- data/lib/friendly_id/candidates.rb +4 -0
- data/lib/friendly_id/configuration.rb +4 -4
- data/lib/friendly_id/finders.rb +51 -0
- data/lib/friendly_id/history.rb +28 -18
- data/lib/friendly_id/object_utils.rb +7 -7
- data/lib/friendly_id/reserved.rb +3 -3
- data/lib/friendly_id/scoped.rb +19 -19
- data/lib/friendly_id/simple_i18n.rb +28 -28
- data/lib/friendly_id/slugged.rb +122 -101
- data/lib/friendly_id/version.rb +2 -2
- data/test/shared.rb +8 -0
- data/test/slugged_test.rb +1 -1
- metadata +19 -5
- data/WhatsNew.md +0 -3
- data/lib/friendly_id/scopes.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a7d80631aa03de549650e0cc84c04108204af5c
|
4
|
+
data.tar.gz: c868670182414c4846e8c4a94aa34d680f78c1a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 203a56c05ef6d18ab3ba8b9de406749a55689d25fb3776b744986c753bcd0a174ffe8f364521f5cca9255b7f196feea76f5fd94bde48c63d8bc4fb2e9a3f8ce9
|
7
|
+
data.tar.gz: 195f31cb8264650bb0b9922dc436575fa3ba33c4c0ecb8f4f2efb2c62033131f11e93d9ba9fff3c710b67bcd0dd96c5601e06a6b5cb9678e72b8abab6b985d2a
|
data/.yardopts
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# FriendlyId
|
2
|
+
|
3
|
+
## Getting Help
|
4
|
+
|
5
|
+
Before opening a new issue, please search the existing issues to see if your
|
6
|
+
question has been answered before.
|
7
|
+
|
8
|
+
Please also take a look at the extensive documentation, especially the Guide.
|
9
|
+
|
10
|
+
## FAQ
|
11
|
+
|
12
|
+
Here are the answers to some common questions.
|
13
|
+
|
14
|
+
### I'm using Rails 4...
|
15
|
+
|
16
|
+
Then you **must** use FriendlyId 5, which is currently available in the master
|
17
|
+
branch of the repository, and will be released to Rubygems soon.
|
18
|
+
|
19
|
+
### How do I set up my routes for FriendlyId?
|
20
|
+
|
21
|
+
Exactly like in any other Rails app. FriendlyId doesn't change any routing
|
22
|
+
functionality, it only changes the ids that are shown in your routes.
|
23
|
+
|
24
|
+
TIP: Make your app work the way you want to with numeric id's. Then add
|
25
|
+
FriendlyId later.
|
26
|
+
|
27
|
+
### I'm seeing `undefined method `friendly_id'`
|
28
|
+
|
29
|
+
You probably just added the friendly_id gem. Run `bundle` and restart your
|
30
|
+
Rails app.
|
31
|
+
|
32
|
+
### I'm seeing `uninitialized constant FriendlyId`
|
33
|
+
|
34
|
+
You probably just added the friendly_id gem. Run `bundle` and restart your
|
35
|
+
Rails app.
|
36
|
+
|
data/Changelog.md
CHANGED
@@ -3,16 +3,23 @@
|
|
3
3
|
We would like to think our many {file:Contributors contributors} for
|
4
4
|
suggestions, ideas and improvements to FriendlyId.
|
5
5
|
|
6
|
-
|
7
|
-
{:toc}
|
6
|
+
## 5.0.0.beta1 (2013-08-10)
|
8
7
|
|
9
|
-
|
8
|
+
* Support for Rails 4.
|
9
|
+
* Made the :scoped and :history modules compatible with each other (Andre Duffeck).
|
10
|
+
* Removed class-level finders in favor of `friendly` scope (Norman Clarke).
|
11
|
+
* Implemented "candidates" support (Norman Clarke).
|
12
|
+
* Slug "sequences" are now GUIDs rather than numbers (Norman Clarke).
|
13
|
+
* `find` no longer falls back to super unless id is fully numeric string (Norman Clarke).
|
14
|
+
* Default sequence separator is now '-' rather than '--'.
|
15
|
+
* Support for Globalize has been removed until Globalize supports Rails 4.
|
16
|
+
* Removed upport for Ruby < 1.9.3 and Rails < 4.0.
|
10
17
|
|
11
|
-
Made the :scoped and :history modules compatible with each other (Andre Duffeck)
|
12
18
|
|
13
|
-
## 4.0.10 (
|
19
|
+
## 4.0.10 (2013-08-10)
|
14
20
|
|
15
|
-
* Fixed table prefixes/suffixes being ignored (Jesse Farless)
|
21
|
+
* Fixed table prefixes/suffixes being ignored (Jesse Farless).
|
22
|
+
* Fixed sequence generation for slugs containing numbers (Adam Carroll).
|
16
23
|
|
17
24
|
## 4.0.9 (2012-10-31)
|
18
25
|
|
@@ -38,7 +45,7 @@ Made the :scoped and :history modules compatible with each other (Andre Duffeck)
|
|
38
45
|
|
39
46
|
## 4.0.7 (2012-06-06)
|
40
47
|
|
41
|
-
* to_param just calls super when no
|
48
|
+
* to_param just calls super when no friendly id is present, to keep the model's
|
42
49
|
default behavior. (Andrew White)
|
43
50
|
|
44
51
|
* FriendlyId can now properly sequence slugs that end in numbers even when a
|
data/{Guide.rdoc → Guide.md}
RENAMED
@@ -1,7 +1,6 @@
|
|
1
|
-
#encoding: utf-8
|
2
1
|
|
3
2
|
|
4
|
-
|
3
|
+
## About FriendlyId
|
5
4
|
|
6
5
|
FriendlyId is an add-on to Ruby's Active Record that allows you to replace ids
|
7
6
|
in your URLs with strings:
|
@@ -15,28 +14,27 @@ in your URLs with strings:
|
|
15
14
|
It requires few changes to your application code and offers flexibility,
|
16
15
|
performance and a well-documented codebase.
|
17
16
|
|
18
|
-
|
17
|
+
### Core Concepts
|
19
18
|
|
20
|
-
|
19
|
+
#### Slugs
|
21
20
|
|
22
|
-
The concept of
|
23
|
-
the heart of FriendlyId.
|
21
|
+
The concept of *slugs* is at the heart of FriendlyId.
|
24
22
|
|
25
23
|
A slug is the part of a URL which identifies a page using human-readable
|
26
24
|
keywords, rather than an opaque identifier such as a numeric id. This can make
|
27
25
|
your application more friendly both for users and search engine.
|
28
26
|
|
29
|
-
|
27
|
+
#### Finders: Slugs Act Like Numeric IDs
|
30
28
|
|
31
29
|
To the extent possible, FriendlyId lets you treat text-based identifiers like
|
32
30
|
normal IDs. This means that you can perform finds with slugs just like you do
|
33
31
|
with numeric ids:
|
34
32
|
|
35
33
|
Person.find(82542335)
|
36
|
-
Person.find("joe")
|
34
|
+
Person.friendly.find("joe")
|
37
35
|
|
38
36
|
|
39
|
-
|
37
|
+
## Setting Up FriendlyId in Your Model
|
40
38
|
|
41
39
|
To use FriendlyId in your ActiveRecord models, you must first either extend or
|
42
40
|
include the FriendlyId module (it makes no difference), then invoke the
|
@@ -53,7 +51,7 @@ addons it should use. See the documentation for this method for a list of all
|
|
53
51
|
available addons, or skim through the rest of the docs to get a high-level
|
54
52
|
overview.
|
55
53
|
|
56
|
-
|
54
|
+
### The Default Setup: Simple Models
|
57
55
|
|
58
56
|
The simplest way to use FriendlyId is with a model that has a uniquely indexed
|
59
57
|
column with no spaces or special characters, and that is seldom or never
|
@@ -65,9 +63,9 @@ updated. The most common example of this is a user name:
|
|
65
63
|
validates_format_of :login, :with => /\A[a-z0-9]+\z/i
|
66
64
|
end
|
67
65
|
|
68
|
-
@user = User.find "joe" # the old User.find(1) still works, too
|
69
|
-
@user.to_param
|
70
|
-
redirect_to @user
|
66
|
+
@user = User.friendly.find "joe" # the old User.find(1) still works, too
|
67
|
+
@user.to_param # returns "joe"
|
68
|
+
redirect_to @user # the URL will be /users/joe
|
71
69
|
|
72
70
|
In this case, FriendlyId assumes you want to use the column as-is; it will never
|
73
71
|
modify the value of the column, and your application should ensure that the
|
@@ -78,7 +76,7 @@ value is unique and admissible in a URL:
|
|
78
76
|
friendly_id :name
|
79
77
|
end
|
80
78
|
|
81
|
-
@city.find "Viña del Mar"
|
79
|
+
@city.friendly.find "Viña del Mar"
|
82
80
|
redirect_to @city # the URL will be /cities/Viña%20del%20Mar
|
83
81
|
|
84
82
|
Writing the code to process an arbitrary string into a good identifier for use
|
@@ -86,7 +84,7 @@ in a URL can be repetitive and surprisingly tricky, so for this reason it's
|
|
86
84
|
often better and easier to use {FriendlyId::Slugged slugs}.
|
87
85
|
|
88
86
|
|
89
|
-
|
87
|
+
## Slugged Models
|
90
88
|
|
91
89
|
FriendlyId can use a separate column to store slugs for models which require
|
92
90
|
some text processing.
|
@@ -111,13 +109,13 @@ To activate the slugging functionality, use the {FriendlyId::Slugged} module.
|
|
111
109
|
|
112
110
|
FriendlyId will generate slugs from a method or column that you specify, and
|
113
111
|
store them in a field in your model. By default, this field must be named
|
114
|
-
|
112
|
+
`:slug`, though you may change this using the
|
115
113
|
{FriendlyId::Slugged::Configuration#slug_column slug_column} configuration
|
116
114
|
option. You should add an index to this column, and in most cases, make it
|
117
115
|
unique. You may also wish to constrain it to NOT NULL, but this depends on your
|
118
116
|
app's behavior and requirements.
|
119
117
|
|
120
|
-
|
118
|
+
### Example Setup
|
121
119
|
|
122
120
|
# your model
|
123
121
|
class Post < ActiveRecord::Base
|
@@ -143,119 +141,144 @@ app's behavior and requirements.
|
|
143
141
|
end
|
144
142
|
end
|
145
143
|
|
146
|
-
|
144
|
+
### Working With Slugs
|
147
145
|
|
148
|
-
|
146
|
+
#### Formatting
|
149
147
|
|
150
148
|
By default, FriendlyId uses Active Support's
|
151
|
-
paramaterize
|
149
|
+
[paramaterize](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize)
|
152
150
|
method to create slugs. This method will intelligently replace spaces with
|
153
151
|
dashes, and Unicode Latin characters with ASCII approximations:
|
154
152
|
|
155
|
-
|
156
|
-
|
153
|
+
movie = Movie.create! :title => "Der Preis fürs Überleben"
|
154
|
+
movie.slug #=> "der-preis-furs-uberleben"
|
157
155
|
|
158
|
-
|
156
|
+
#### Column or Method?
|
159
157
|
|
160
|
-
|
161
|
-
|
158
|
+
FriendlyId always uses a method as the basis of the slug text - not a column. It
|
159
|
+
first glance, this may sound confusing, but remember that Active Record provides
|
160
|
+
methods for each column in a model's associated table, and that's what
|
161
|
+
FriendlyId uses.
|
162
162
|
|
163
|
-
|
164
|
-
car2 = Car.create :title => "Peugot 206"
|
163
|
+
Here's an example of a class that uses a custom method to generate the slug:
|
165
164
|
|
166
|
-
|
167
|
-
|
165
|
+
class Person < ActiveRecord::Base
|
166
|
+
friendly_id :name_and_location
|
167
|
+
def name_and_location
|
168
|
+
"#{name} from #{location}"
|
169
|
+
end
|
170
|
+
end
|
168
171
|
|
169
|
-
|
172
|
+
bob = Person.create! :name => "Bob Smith", :location => "New York City"
|
173
|
+
bob.friendly_id #=> "bob-smith-from-new-york-city"
|
170
174
|
|
171
|
-
|
175
|
+
FriendlyId refers to this internally as the "base" method.
|
172
176
|
|
173
|
-
|
174
|
-
sequence_separator} configuration option.
|
177
|
+
#### Uniqueness
|
175
178
|
|
176
|
-
|
179
|
+
When you try to insert a record that would generate a duplicate friendly id,
|
180
|
+
FriendlyId will append a UUID to the generated slug to ensure uniqueness:
|
177
181
|
|
178
|
-
|
179
|
-
|
180
|
-
methods for each column in a model's associated table, and that's what
|
181
|
-
FriendlyId uses.
|
182
|
+
car = Car.create :title => "Peugot 206"
|
183
|
+
car2 = Car.create :title => "Peugot 206"
|
182
184
|
|
183
|
-
|
185
|
+
car.friendly_id #=> "peugot-206"
|
186
|
+
car2.friendly_id #=> "peugot-206-f9f3789a-daec-4156-af1d-fab81aa16ee5"
|
184
187
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
188
|
+
Previous versions of FriendlyId appended a numeric sequence a to make slugs
|
189
|
+
unique, but this was removed to simplify using FriendlyId in concurrent code.
|
190
|
+
|
191
|
+
#### Candidates
|
192
|
+
|
193
|
+
Since UUIDs are ugly, FriendlyId provides a "slug candidates" functionality to
|
194
|
+
let you specify alternate slugs to use in the event the one you want to use is
|
195
|
+
already taken. For example:
|
196
|
+
|
197
|
+
class Restaurant < ActiveRecord::Base
|
198
|
+
extend FriendlyId
|
199
|
+
friendly_id :slug_candidates, use: :slugged
|
200
|
+
|
201
|
+
# Try building a slug based on the following fields in
|
202
|
+
# increasing order of specificity.
|
203
|
+
def slug_candidates
|
204
|
+
[
|
205
|
+
:name,
|
206
|
+
[:name, :city],
|
207
|
+
[:name, :street, :city],
|
208
|
+
[:name, :street_number, :street, :city]
|
209
|
+
]
|
210
|
+
end
|
189
211
|
end
|
190
|
-
end
|
191
212
|
|
192
|
-
|
193
|
-
|
213
|
+
r1 = Restaurant.create! name: 'Plaza Diner', city: 'New Paltz'
|
214
|
+
r2 = Restaurant.create! name: 'Plaza Diner', city: 'Kingston'
|
194
215
|
|
195
|
-
|
216
|
+
r1.friendly_id #=> 'plaza-diner'
|
217
|
+
r2.friendly_id #=> 'plaza-diner-kingston'
|
196
218
|
|
197
|
-
|
198
|
-
|
219
|
+
To use candidates, make your FriendlyId base method return an array. The
|
220
|
+
method need not be named `slug_candidates`; it can be anything you want. The
|
221
|
+
array may contain any combination of symbols, strings, procs or lambdas and
|
222
|
+
will be evaluated lazily and in order. If you include symbols, FriendlyId will
|
223
|
+
invoke a method on your model class with the same name. Strings will be
|
224
|
+
interpreted literally. Procs and lambdas will be called and their return values
|
225
|
+
used as the basis of the friendly id. If none of the candidates can generate a
|
226
|
+
unique slug, then FriendlyId will append a UUID to the first candidate as a
|
227
|
+
last resort.
|
199
228
|
|
200
|
-
|
229
|
+
#### Sequence Separator
|
201
230
|
|
202
|
-
|
203
|
-
control whether new friendly ids are created when a model is updated. For
|
204
|
-
example, if you only want to generate slugs once and then treat them as
|
205
|
-
read-only:
|
231
|
+
By default, FriendlyId uses a dash to separate the slug from a sequence.
|
206
232
|
|
207
|
-
|
208
|
-
|
209
|
-
friendly_id :title, :use => :slugged
|
233
|
+
You can change this with the {FriendlyId::Slugged::Configuration#sequence_separator
|
234
|
+
sequence_separator} configuration option.
|
210
235
|
|
211
|
-
|
212
|
-
new_record?
|
213
|
-
end
|
214
|
-
end
|
236
|
+
#### Providing Your Own Slug Processing Method
|
215
237
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
post.save!
|
220
|
-
post.slug #=> "hello-world"
|
238
|
+
You can override {FriendlyId::Slugged#normalize_friendly_id} in your model for
|
239
|
+
total control over the slug format. It will be invoked for any generated slug,
|
240
|
+
whether for a single slug or for slug candidates.
|
221
241
|
|
222
|
-
|
242
|
+
#### Deciding When to Generate New Slugs
|
223
243
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
locale when replacing Latin characters:
|
244
|
+
Previous versions of FriendlyId provided a method named
|
245
|
+
`should_generate_new_friendly_id?` which you could override to control when new
|
246
|
+
slugs were generated.
|
228
247
|
|
229
|
-
|
230
|
-
|
231
|
-
i18n:
|
232
|
-
transliterate:
|
233
|
-
rule:
|
234
|
-
ü: "ue"
|
235
|
-
ö: "oe"
|
236
|
-
etc...
|
248
|
+
As of FriendlyId 5.0, slugs are only generated when the `slug` field is nil. If
|
249
|
+
you want a slug to be regenerated, you must explicity set the field to nil:
|
237
250
|
|
238
|
-
|
239
|
-
|
251
|
+
restaurant.friendly_id # joes-diner
|
252
|
+
restaurant.name = "The Plaza Diner"
|
253
|
+
restaurant.save!
|
254
|
+
restaurant.friendly_id # joes-diner
|
255
|
+
restaurant.slug = nil
|
256
|
+
restaurant.save!
|
257
|
+
restaurant.friendly_id # the-plaza-diner
|
240
258
|
|
241
|
-
This functionality was in fact taken from earlier versions of FriendlyId.
|
242
259
|
|
243
|
-
|
260
|
+
#### Locale-specific Transliterations
|
244
261
|
|
245
|
-
|
262
|
+
Active Support's `parameterize` uses
|
263
|
+
[transliterate](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-transliterate),
|
264
|
+
which in turn can use I18n's transliteration rules to consider the current
|
265
|
+
locale when replacing Latin characters:
|
246
266
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
267
|
+
# config/locales/de.yml
|
268
|
+
de:
|
269
|
+
i18n:
|
270
|
+
transliterate:
|
271
|
+
rule:
|
272
|
+
ü: "ue"
|
273
|
+
ö: "oe"
|
274
|
+
etc...
|
251
275
|
|
252
|
-
|
276
|
+
movie = Movie.create! :title => "Der Preis fürs Überleben"
|
277
|
+
movie.slug #=> "der-preis-fuers-ueberleben"
|
253
278
|
|
254
|
-
|
255
|
-
* Use explicit finders like +find_by_id+ to always find by the numeric id, or
|
256
|
-
+find_by_slug+ to always find using the friendly id.
|
279
|
+
This functionality was in fact taken from earlier versions of FriendlyId.
|
257
280
|
|
258
|
-
|
281
|
+
#### Gotchas: Common Problems
|
259
282
|
|
260
283
|
FriendlyId uses a before_validation callback to generate and set the slug. This
|
261
284
|
means that if you create two model instances before saving them, it's possible
|
@@ -266,15 +289,11 @@ attributes creates more than one record for a model that uses friendly_id. The
|
|
266
289
|
second, in concurrent code, either in threads or multiple processes.
|
267
290
|
|
268
291
|
To solve the nested attributes issue, I recommend simply avoiding them when
|
269
|
-
creating more than one nested record for a model that uses FriendlyId. See
|
270
|
-
Github issue
|
271
|
-
|
272
|
-
To solve the concurrency issue, I recommend locking the model's table against
|
273
|
-
inserts while when saving the record. See {this Github
|
274
|
-
issue}[https://github.com/FriendlyId/friendly_id/issues/180] for discussion.
|
292
|
+
creating more than one nested record for a model that uses FriendlyId. See [this
|
293
|
+
Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
|
275
294
|
|
276
295
|
|
277
|
-
|
296
|
+
## History: Avoiding 404's When Slugs Change
|
278
297
|
|
279
298
|
FriendlyId's {FriendlyId::History History} module adds the ability to store a
|
280
299
|
log of a model's slugs, so that when its friendly id changes, it's still
|
@@ -282,26 +301,24 @@ possible to perform finds by the old id.
|
|
282
301
|
|
283
302
|
The primary use case for this is avoiding broken URLs.
|
284
303
|
|
285
|
-
|
304
|
+
### Setup
|
286
305
|
|
287
306
|
In order to use this module, you must add a table to your database schema to
|
288
307
|
store the slug records. FriendlyId provides a generator for this purpose:
|
289
308
|
|
290
|
-
|
291
|
-
|
309
|
+
rails generate friendly_id
|
310
|
+
rake db:migrate
|
292
311
|
|
293
|
-
This will add a table named
|
312
|
+
This will add a table named `friendly_id_slugs`, used by the {FriendlyId::Slug}
|
294
313
|
model.
|
295
314
|
|
296
|
-
|
297
|
-
|
298
|
-
This module is incompatible with the +:scoped+ module.
|
315
|
+
### Considerations
|
299
316
|
|
300
317
|
Because recording slug history requires creating additional database records,
|
301
|
-
this module has an impact on the performance of the associated model's
|
318
|
+
this module has an impact on the performance of the associated model's `create`
|
302
319
|
method.
|
303
320
|
|
304
|
-
|
321
|
+
### Example
|
305
322
|
|
306
323
|
class Post < ActiveRecord::Base
|
307
324
|
extend FriendlyId
|
@@ -327,13 +344,13 @@ method.
|
|
327
344
|
end
|
328
345
|
|
329
346
|
|
330
|
-
|
347
|
+
## Unique Slugs by Scope
|
331
348
|
|
332
349
|
The {FriendlyId::Scoped} module allows FriendlyId to generate unique slugs
|
333
350
|
within a scope.
|
334
351
|
|
335
352
|
This allows, for example, two restaurants in different cities to have the slug
|
336
|
-
|
353
|
+
`joes-diner`:
|
337
354
|
|
338
355
|
class Restaurant < ActiveRecord::Base
|
339
356
|
extend FriendlyId
|
@@ -347,16 +364,16 @@ This allows, for example, two restaurants in different cities to have the slug
|
|
347
364
|
friendly_id :name, :use => :slugged
|
348
365
|
end
|
349
366
|
|
350
|
-
City.find("seattle").restaurants.find("joes-diner")
|
351
|
-
City.find("chicago").restaurants.find("joes-diner")
|
367
|
+
City.friendly.find("seattle").restaurants.friendly.find("joes-diner")
|
368
|
+
City.friendly.find("chicago").restaurants.friendly.find("joes-diner")
|
352
369
|
|
353
370
|
Without :scoped in this case, one of the restaurants would have the slug
|
354
|
-
|
371
|
+
`joes-diner` and the other would have `joes-diner-f9f3789a-daec-4156-af1d-fab81aa16ee5`.
|
355
372
|
|
356
|
-
The value for the
|
373
|
+
The value for the `:scope` option can be the name of a `belongs_to` relation, or
|
357
374
|
a column.
|
358
375
|
|
359
|
-
Additionally, the
|
376
|
+
Additionally, the `:scope` option can receive an array of scope values:
|
360
377
|
|
361
378
|
class Cuisine < ActiveRecord::Base
|
362
379
|
extend FriendlyId
|
@@ -378,30 +395,30 @@ Additionally, the +:scope+ option can receive an array of scope values:
|
|
378
395
|
|
379
396
|
All supplied values will be used to determine scope.
|
380
397
|
|
381
|
-
|
398
|
+
### Finding Records by Friendly ID
|
382
399
|
|
383
400
|
If you are using scopes your friendly ids may not be unique, so a simple find
|
384
401
|
like
|
385
402
|
|
386
|
-
Restaurant.find("joes-diner")
|
403
|
+
Restaurant.friendly.find("joes-diner")
|
387
404
|
|
388
405
|
may return the wrong record. In these cases it's best to query through the
|
389
406
|
relation:
|
390
407
|
|
391
|
-
@city.restaurants.find("joes-diner")
|
408
|
+
@city.restaurants.friendly.find("joes-diner")
|
392
409
|
|
393
410
|
Alternatively, you could pass the scope value as a query parameter:
|
394
411
|
|
395
|
-
Restaurant.find("joes-diner").where(:city_id => @city.id)
|
412
|
+
Restaurant.friendly.find("joes-diner").where(:city_id => @city.id)
|
396
413
|
|
397
414
|
|
398
|
-
|
415
|
+
### Finding All Records That Match a Scoped ID
|
399
416
|
|
400
417
|
Query the slug column directly:
|
401
418
|
|
402
|
-
Restaurant.
|
419
|
+
Restaurant.where(:slug => "joes-diner")
|
403
420
|
|
404
|
-
|
421
|
+
### Routes for Scoped Models
|
405
422
|
|
406
423
|
Recall that FriendlyId is a database-centric library, and does not set up any
|
407
424
|
routes for scoped models. You must do this yourself in your application. Here's
|
@@ -416,15 +433,15 @@ an example of one way to set this up:
|
|
416
433
|
<%= link_to 'Show', [@city, @restaurant] %>
|
417
434
|
|
418
435
|
# in controllers
|
419
|
-
@city = City.find(params[:city_id])
|
420
|
-
@restaurant = @city.restaurants.find(params[:id])
|
436
|
+
@city = City.friendly.find(params[:city_id])
|
437
|
+
@restaurant = @city.restaurants.friendly.find(params[:id])
|
421
438
|
|
422
439
|
# URLs:
|
423
440
|
http://example.org/cities/seattle/restaurants/joes-diner
|
424
441
|
http://example.org/cities/chicago/restaurants/joes-diner
|
425
442
|
|
426
443
|
|
427
|
-
|
444
|
+
## Translating Slugs Using Simple I18n
|
428
445
|
|
429
446
|
The {FriendlyId::SimpleI18n SimpleI18n} module adds very basic i18n support to
|
430
447
|
FriendlyId.
|
@@ -432,64 +449,64 @@ FriendlyId.
|
|
432
449
|
In order to use this module, your model must have a slug column for each locale.
|
433
450
|
By default FriendlyId looks for columns named, for example, "slug_en",
|
434
451
|
"slug_es", etc. The first part of the name can be configured by passing the
|
435
|
-
|
452
|
+
`:slug_column` option if you choose. Note that the column for the default locale
|
436
453
|
must also include the locale in its name.
|
437
454
|
|
438
455
|
This module is most suitable to applications that need to support few locales.
|
439
456
|
If you need to support two or more locales, you may wish to use the
|
440
457
|
friendly_id_globalize gem instead.
|
441
458
|
|
442
|
-
|
459
|
+
### Example migration
|
443
460
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
461
|
+
def self.up
|
462
|
+
create_table :posts do |t|
|
463
|
+
t.string :title
|
464
|
+
t.string :slug_en
|
465
|
+
t.string :slug_es
|
466
|
+
t.text :body
|
467
|
+
end
|
468
|
+
add_index :posts, :slug_en
|
469
|
+
add_index :posts, :slug_es
|
450
470
|
end
|
451
|
-
add_index :posts, :slug_en
|
452
|
-
add_index :posts, :slug_es
|
453
|
-
end
|
454
471
|
|
455
|
-
|
472
|
+
### Finds
|
456
473
|
|
457
474
|
Finds will take into consideration the current locale:
|
458
475
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
476
|
+
I18n.locale = :es
|
477
|
+
Post.find("la-guerra-de-las-galaxas")
|
478
|
+
I18n.locale = :en
|
479
|
+
Post.find("star-wars")
|
463
480
|
|
464
481
|
To find a slug by an explicit locale, perform the find inside a block
|
465
|
-
passed to I18n's
|
482
|
+
passed to I18n's `with_locale` method:
|
466
483
|
|
467
|
-
|
468
|
-
|
469
|
-
|
484
|
+
I18n.with_locale(:es) do
|
485
|
+
Post.find("la-guerra-de-las-galaxas")
|
486
|
+
end
|
470
487
|
|
471
|
-
|
488
|
+
### Creating Records
|
472
489
|
|
473
490
|
When new records are created, the slug is generated for the current locale only.
|
474
491
|
|
475
|
-
|
492
|
+
### Translating Slugs
|
476
493
|
|
477
494
|
To translate an existing record's friendly_id, use
|
478
495
|
{FriendlyId::SimpleI18n::Model#set_friendly_id}. This will ensure that the slug
|
479
496
|
you add is properly escaped, transliterated and sequenced:
|
480
497
|
|
481
|
-
|
482
|
-
|
498
|
+
post = Post.create :name => "Star Wars"
|
499
|
+
post.set_friendly_id("La guerra de las galaxas", :es)
|
483
500
|
|
484
501
|
If you don't pass in a locale argument, FriendlyId::SimpleI18n will just use the
|
485
502
|
current locale:
|
486
503
|
|
487
|
-
|
488
|
-
|
489
|
-
|
504
|
+
I18n.with_locale(:es) do
|
505
|
+
post.set_friendly_id("La guerra de las galaxas")
|
506
|
+
end
|
490
507
|
|
491
508
|
|
492
|
-
|
509
|
+
## Reserved Words
|
493
510
|
|
494
511
|
The {FriendlyId::Reserved Reserved} module adds the ability to exlude a list of
|
495
512
|
words from use as FriendlyId slugs.
|
@@ -504,7 +521,7 @@ FriendlyId.defaults}:
|
|
504
521
|
config.reserved_words = %w(new edit nueva nuevo editar)
|
505
522
|
end
|
506
523
|
|
507
|
-
Note that the error message will appear on the field
|
524
|
+
Note that the error message will appear on the field `:friendly_id`. If you are
|
508
525
|
using Rails's scaffolded form errors display, then it will have no field to
|
509
526
|
highlight. If you'd like to change this so that scaffolding works as expected,
|
510
527
|
one way to accomplish this is to move the error message to a different field.
|