friendly_id 5.2.4 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +6 -0
- data/.github/stale.yml +17 -0
- data/.github/workflows/test.yml +58 -0
- data/Changelog.md +41 -0
- data/Gemfile +10 -11
- data/README.md +42 -15
- data/Rakefile +24 -27
- data/bench.rb +30 -27
- data/certs/parndt.pem +27 -0
- data/friendly_id.gemspec +28 -27
- data/gemfiles/Gemfile.rails-5.2.rb +11 -16
- data/gemfiles/Gemfile.rails-6.0.rb +22 -0
- data/gemfiles/Gemfile.rails-6.1.rb +22 -0
- data/gemfiles/Gemfile.rails-7.0.rb +22 -0
- data/guide.rb +5 -5
- data/lib/friendly_id/base.rb +61 -68
- data/lib/friendly_id/candidates.rb +9 -11
- data/lib/friendly_id/configuration.rb +8 -8
- data/lib/friendly_id/finder_methods.rb +72 -13
- data/lib/friendly_id/finders.rb +64 -67
- data/lib/friendly_id/history.rb +72 -66
- data/lib/friendly_id/initializer.rb +5 -5
- data/lib/friendly_id/migration.rb +10 -11
- data/lib/friendly_id/object_utils.rb +2 -2
- data/lib/friendly_id/reserved.rb +28 -32
- data/lib/friendly_id/scoped.rb +105 -103
- data/lib/friendly_id/sequentially_slugged/calculator.rb +69 -0
- data/lib/friendly_id/sequentially_slugged.rb +21 -58
- data/lib/friendly_id/simple_i18n.rb +75 -69
- data/lib/friendly_id/slug.rb +1 -2
- data/lib/friendly_id/slug_generator.rb +1 -3
- data/lib/friendly_id/slugged.rb +236 -239
- data/lib/friendly_id/version.rb +1 -1
- data/lib/friendly_id.rb +41 -45
- data/lib/generators/friendly_id_generator.rb +9 -9
- data/test/base_test.rb +10 -13
- data/test/benchmarks/finders.rb +28 -26
- data/test/benchmarks/object_utils.rb +13 -13
- data/test/candidates_test.rb +17 -18
- data/test/configuration_test.rb +7 -11
- data/test/core_test.rb +1 -2
- data/test/databases.yml +7 -4
- data/test/finders_test.rb +52 -5
- data/test/generator_test.rb +16 -26
- data/test/helper.rb +33 -20
- data/test/history_test.rb +116 -72
- data/test/numeric_slug_test.rb +31 -0
- data/test/object_utils_test.rb +0 -2
- data/test/reserved_test.rb +9 -11
- data/test/schema.rb +5 -4
- data/test/scoped_test.rb +26 -15
- data/test/sequentially_slugged_test.rb +107 -33
- data/test/shared.rb +17 -18
- data/test/simple_i18n_test.rb +23 -13
- data/test/slugged_test.rb +254 -78
- data/test/sti_test.rb +19 -21
- data.tar.gz.sig +0 -0
- metadata +49 -19
- metadata.gz.sig +1 -0
- data/.travis.yml +0 -57
- data/gemfiles/Gemfile.rails-4.0.rb +0 -30
- data/gemfiles/Gemfile.rails-4.1.rb +0 -29
- data/gemfiles/Gemfile.rails-4.2.rb +0 -28
- data/gemfiles/Gemfile.rails-5.0.rb +0 -28
- data/gemfiles/Gemfile.rails-5.1.rb +0 -27
@@ -1,27 +1,22 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gemspec path:
|
3
|
+
gemspec path: "../"
|
4
4
|
|
5
|
-
gem
|
6
|
-
gem
|
5
|
+
gem "activerecord", "~> 5.2.0"
|
6
|
+
gem "railties", "~> 5.2.0"
|
7
7
|
|
8
8
|
# Database Configuration
|
9
9
|
group :development, :test do
|
10
10
|
platforms :jruby do
|
11
|
-
gem
|
12
|
-
gem
|
13
|
-
gem
|
11
|
+
gem "activerecord-jdbcmysql-adapter", "~> 51.1"
|
12
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 51.1"
|
13
|
+
gem "kramdown"
|
14
14
|
end
|
15
15
|
|
16
16
|
platforms :ruby, :rbx do
|
17
|
-
gem
|
18
|
-
gem
|
19
|
-
gem
|
20
|
-
gem
|
21
|
-
end
|
22
|
-
|
23
|
-
platforms :rbx do
|
24
|
-
gem 'rubysl', '~> 2.0'
|
25
|
-
gem 'rubinius-developer_tools'
|
17
|
+
gem "sqlite3"
|
18
|
+
gem "mysql2"
|
19
|
+
gem "pg"
|
20
|
+
gem "redcarpet"
|
26
21
|
end
|
27
22
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec path: "../"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 6.0.0"
|
6
|
+
gem "railties", "~> 6.0.0"
|
7
|
+
|
8
|
+
# Database Configuration
|
9
|
+
group :development, :test do
|
10
|
+
platforms :jruby do
|
11
|
+
gem "activerecord-jdbcmysql-adapter", "~> 51.1"
|
12
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 51.1"
|
13
|
+
gem "kramdown"
|
14
|
+
end
|
15
|
+
|
16
|
+
platforms :ruby, :rbx do
|
17
|
+
gem "sqlite3"
|
18
|
+
gem "mysql2"
|
19
|
+
gem "pg"
|
20
|
+
gem "redcarpet"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec path: "../"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 6.1.4"
|
6
|
+
gem "railties", "~> 6.1.4"
|
7
|
+
|
8
|
+
# Database Configuration
|
9
|
+
group :development, :test do
|
10
|
+
platforms :jruby do
|
11
|
+
gem "activerecord-jdbcmysql-adapter", "~> 61.0"
|
12
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 61.0"
|
13
|
+
gem "kramdown"
|
14
|
+
end
|
15
|
+
|
16
|
+
platforms :ruby, :rbx do
|
17
|
+
gem "sqlite3"
|
18
|
+
gem "mysql2"
|
19
|
+
gem "pg"
|
20
|
+
gem "redcarpet"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec path: "../"
|
4
|
+
|
5
|
+
gem "activerecord", "~> 7.0.0"
|
6
|
+
gem "railties", "~> 7.0.0"
|
7
|
+
|
8
|
+
# Database Configuration
|
9
|
+
group :development, :test do
|
10
|
+
platforms :jruby do
|
11
|
+
gem "activerecord-jdbcmysql-adapter", "~> 61.0"
|
12
|
+
gem "activerecord-jdbcpostgresql-adapter", "~> 61.0"
|
13
|
+
gem "kramdown"
|
14
|
+
end
|
15
|
+
|
16
|
+
platforms :ruby, :rbx do
|
17
|
+
gem "sqlite3"
|
18
|
+
gem "mysql2"
|
19
|
+
gem "pg"
|
20
|
+
gem "redcarpet"
|
21
|
+
end
|
22
|
+
end
|
data/guide.rb
CHANGED
@@ -3,14 +3,14 @@
|
|
3
3
|
# This script generates the Guide.md file included in the Yard docs.
|
4
4
|
|
5
5
|
def comments_from path
|
6
|
-
path
|
6
|
+
path = File.expand_path("../lib/friendly_id/#{path}", __FILE__)
|
7
7
|
match = File.read(path).match(/\n=begin(.*)\n=end/m)[1].to_s
|
8
|
-
match.split("\n").reject {|x| x =~ /^@/}.join("\n").strip
|
8
|
+
match.split("\n").reject { |x| x =~ /^@/ }.join("\n").strip
|
9
9
|
end
|
10
10
|
|
11
|
-
File.open(File.expand_path(
|
12
|
-
[
|
13
|
-
|
11
|
+
File.open(File.expand_path("../Guide.md", __FILE__), "w:utf-8") do |guide|
|
12
|
+
["../friendly_id.rb", "base.rb", "finders.rb", "slugged.rb", "history.rb",
|
13
|
+
"scoped.rb", "simple_i18n.rb", "reserved.rb"].each do |file|
|
14
14
|
guide.write comments_from file
|
15
15
|
guide.write "\n"
|
16
16
|
end
|
data/lib/friendly_id/base.rb
CHANGED
@@ -1,62 +1,59 @@
|
|
1
1
|
module FriendlyId
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
addons
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
=end
|
2
|
+
#
|
3
|
+
## Setting Up FriendlyId in Your Model
|
4
|
+
#
|
5
|
+
# To use FriendlyId in your ActiveRecord models, you must first either extend or
|
6
|
+
# include the FriendlyId module (it makes no difference), then invoke the
|
7
|
+
# {FriendlyId::Base#friendly_id friendly_id} method to configure your desired
|
8
|
+
# options:
|
9
|
+
#
|
10
|
+
# class Foo < ActiveRecord::Base
|
11
|
+
# include FriendlyId
|
12
|
+
# friendly_id :bar, :use => [:slugged, :simple_i18n]
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# The most important option is `:use`, which you use to tell FriendlyId which
|
16
|
+
# addons it should use. See the documentation for {FriendlyId::Base#friendly_id} for a list of all
|
17
|
+
# available addons, or skim through the rest of the docs to get a high-level
|
18
|
+
# overview.
|
19
|
+
#
|
20
|
+
# *A note about single table inheritance (STI): you must extend FriendlyId in
|
21
|
+
# all classes that participate in STI, both your parent classes and their
|
22
|
+
# children.*
|
23
|
+
#
|
24
|
+
### The Default Setup: Simple Models
|
25
|
+
#
|
26
|
+
# The simplest way to use FriendlyId is with a model that has a uniquely indexed
|
27
|
+
# column with no spaces or special characters, and that is seldom or never
|
28
|
+
# updated. The most common example of this is a user name:
|
29
|
+
#
|
30
|
+
# class User < ActiveRecord::Base
|
31
|
+
# extend FriendlyId
|
32
|
+
# friendly_id :login
|
33
|
+
# validates_format_of :login, :with => /\A[a-z0-9]+\z/i
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# @user = User.friendly.find "joe" # the old User.find(1) still works, too
|
37
|
+
# @user.to_param # returns "joe"
|
38
|
+
# redirect_to @user # the URL will be /users/joe
|
39
|
+
#
|
40
|
+
# In this case, FriendlyId assumes you want to use the column as-is; it will never
|
41
|
+
# modify the value of the column, and your application should ensure that the
|
42
|
+
# value is unique and admissible in a URL:
|
43
|
+
#
|
44
|
+
# class City < ActiveRecord::Base
|
45
|
+
# extend FriendlyId
|
46
|
+
# friendly_id :name
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# @city.friendly.find "Viña del Mar"
|
50
|
+
# redirect_to @city # the URL will be /cities/Viña%20del%20Mar
|
51
|
+
#
|
52
|
+
# Writing the code to process an arbitrary string into a good identifier for use
|
53
|
+
# in a URL can be repetitive and surprisingly tricky, so for this reason it's
|
54
|
+
# often better and easier to use {FriendlyId::Slugged slugs}.
|
55
|
+
#
|
58
56
|
module Base
|
59
|
-
|
60
57
|
# Configure FriendlyId's behavior in a model.
|
61
58
|
#
|
62
59
|
# class Post < ActiveRecord::Base
|
@@ -159,8 +156,9 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
159
156
|
#
|
160
157
|
# @option options [Symbol,Module] :use The addon or name of an addon to use.
|
161
158
|
# By default, FriendlyId provides {FriendlyId::Slugged :slugged},
|
162
|
-
# {FriendlyId::
|
163
|
-
# {FriendlyId::
|
159
|
+
# {FriendlyId::Reserved :finders}, {FriendlyId::History :history},
|
160
|
+
# {FriendlyId::Reserved :reserved}, {FriendlyId::Scoped :scoped}, and
|
161
|
+
# {FriendlyId::SimpleI18n :simple_i18n}.
|
164
162
|
#
|
165
163
|
# @option options [Array] :reserved_words Available when using `:reserved`,
|
166
164
|
# which is loaded by default. Sets an array of words banned for use as
|
@@ -204,10 +202,10 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
204
202
|
#
|
205
203
|
# @yieldparam config The model class's {FriendlyId::Configuration friendly_id_config}.
|
206
204
|
def friendly_id(base = nil, options = {}, &block)
|
207
|
-
yield friendly_id_config if
|
205
|
+
yield friendly_id_config if block
|
208
206
|
friendly_id_config.dependent = options.delete :dependent
|
209
207
|
friendly_id_config.use options.delete :use
|
210
|
-
friendly_id_config.send :set, base ? options.merge(:
|
208
|
+
friendly_id_config.send :set, base ? options.merge(base: base) : options
|
211
209
|
include Model
|
212
210
|
end
|
213
211
|
|
@@ -261,12 +259,7 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
261
259
|
# Either the friendly_id, or the numeric id cast to a string.
|
262
260
|
def to_param
|
263
261
|
if friendly_id_config.routes == :friendly
|
264
|
-
|
265
|
-
diff = changes[friendly_id_config.query_field]
|
266
|
-
diff.first || diff.second
|
267
|
-
else
|
268
|
-
friendly_id.presence.to_param || super
|
269
|
-
end
|
262
|
+
friendly_id.presence.to_param || super
|
270
263
|
else
|
271
264
|
super
|
272
265
|
end
|
@@ -274,7 +267,7 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
274
267
|
|
275
268
|
# Clears slug on duplicate records when calling `dup`.
|
276
269
|
def dup
|
277
|
-
super.tap { |duplicate| duplicate.slug = nil if duplicate.respond_to?(
|
270
|
+
super.tap { |duplicate| duplicate.slug = nil if duplicate.respond_to?("slug=") }
|
278
271
|
end
|
279
272
|
end
|
280
273
|
end
|
@@ -1,11 +1,9 @@
|
|
1
|
-
require
|
1
|
+
require "securerandom"
|
2
2
|
|
3
3
|
module FriendlyId
|
4
|
-
|
5
4
|
# This class provides the slug candidate functionality.
|
6
5
|
# @see FriendlyId::Slugged
|
7
6
|
class Candidates
|
8
|
-
|
9
7
|
include Enumerable
|
10
8
|
|
11
9
|
def initialize(object, *array)
|
@@ -14,8 +12,8 @@ module FriendlyId
|
|
14
12
|
end
|
15
13
|
|
16
14
|
def each(*args, &block)
|
17
|
-
return candidates unless
|
18
|
-
candidates.each{ |candidate| yield candidate }
|
15
|
+
return candidates unless block
|
16
|
+
candidates.each { |candidate| yield candidate }
|
19
17
|
end
|
20
18
|
|
21
19
|
private
|
@@ -29,13 +27,13 @@ module FriendlyId
|
|
29
27
|
|
30
28
|
def normalize(candidates)
|
31
29
|
candidates.map do |candidate|
|
32
|
-
@object.normalize_friendly_id(candidate.map(&:call).join(
|
33
|
-
end.select {|x| wanted?(x)}
|
30
|
+
@object.normalize_friendly_id(candidate.map(&:call).join(" "))
|
31
|
+
end.select { |x| wanted?(x) }
|
34
32
|
end
|
35
33
|
|
36
34
|
def filter(candidates)
|
37
|
-
unless candidates.all? {|x| reserved?(x)}
|
38
|
-
candidates.reject! {|x| reserved?(x)}
|
35
|
+
unless candidates.all? { |x| reserved?(x) }
|
36
|
+
candidates.reject! { |x| reserved?(x) }
|
39
37
|
end
|
40
38
|
candidates
|
41
39
|
end
|
@@ -44,7 +42,7 @@ module FriendlyId
|
|
44
42
|
array.map do |candidate|
|
45
43
|
case candidate
|
46
44
|
when String
|
47
|
-
[->{candidate}]
|
45
|
+
[-> { candidate }]
|
48
46
|
when Array
|
49
47
|
to_candidate_array(object, candidate).flatten
|
50
48
|
when Symbol
|
@@ -53,7 +51,7 @@ module FriendlyId
|
|
53
51
|
if candidate.respond_to?(:call)
|
54
52
|
[candidate]
|
55
53
|
else
|
56
|
-
[->{candidate.to_s}]
|
54
|
+
[-> { candidate.to_s }]
|
57
55
|
end
|
58
56
|
end
|
59
57
|
end
|
@@ -2,7 +2,6 @@ module FriendlyId
|
|
2
2
|
# The configuration parameters passed to {Base#friendly_id} will be stored in
|
3
3
|
# this object.
|
4
4
|
class Configuration
|
5
|
-
|
6
5
|
attr_writer :base
|
7
6
|
|
8
7
|
# The default configuration options.
|
@@ -25,9 +24,10 @@ module FriendlyId
|
|
25
24
|
attr_accessor :routes
|
26
25
|
|
27
26
|
def initialize(model_class, values = nil)
|
28
|
-
@
|
29
|
-
@
|
30
|
-
@
|
27
|
+
@base = nil
|
28
|
+
@model_class = model_class
|
29
|
+
@defaults = {}
|
30
|
+
@modules = []
|
31
31
|
@finder_methods = FriendlyId::FinderMethods
|
32
32
|
self.routes = :friendly
|
33
33
|
set values
|
@@ -47,8 +47,8 @@ module FriendlyId
|
|
47
47
|
#
|
48
48
|
# @param [#to_s,Module] modules Arguments should be Modules, or symbols or
|
49
49
|
# strings that correspond with the name of an addon to use with FriendlyId.
|
50
|
-
# By default FriendlyId provides `:slugged`, `:
|
51
|
-
# and `:scoped`.
|
50
|
+
# By default FriendlyId provides `:slugged`, `:finders`, `:history`,
|
51
|
+
# `:reserved`, `:simple_i18n`, and `:scoped`.
|
52
52
|
def use(*modules)
|
53
53
|
modules.to_a.flatten.compact.map do |object|
|
54
54
|
mod = get_module(object)
|
@@ -101,11 +101,11 @@ module FriendlyId
|
|
101
101
|
private
|
102
102
|
|
103
103
|
def get_module(object)
|
104
|
-
Module === object ? object : FriendlyId.const_get(object.to_s.titleize.camelize.gsub(/\s+/,
|
104
|
+
Module === object ? object : FriendlyId.const_get(object.to_s.titleize.camelize.gsub(/\s+/, ""))
|
105
105
|
end
|
106
106
|
|
107
107
|
def set(values)
|
108
|
-
values
|
108
|
+
values&.each { |name, value| send "#{name}=", value }
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module FriendlyId
|
2
|
-
|
3
2
|
module FinderMethods
|
4
|
-
|
5
3
|
# Finds a record using the given id.
|
6
4
|
#
|
7
5
|
# If the id is "unfriendly", it will call the original find method.
|
@@ -9,35 +7,51 @@ module FriendlyId
|
|
9
7
|
# id matching '123' and then fall back to looking for a record with the
|
10
8
|
# numeric id '123'.
|
11
9
|
#
|
10
|
+
# @param [Boolean] allow_nil (default: false)
|
11
|
+
# Use allow_nil: true if you'd like the finder to return nil instead of
|
12
|
+
# raising ActivRecord::RecordNotFound
|
13
|
+
#
|
14
|
+
# ### Example
|
15
|
+
#
|
16
|
+
# MyModel.friendly.find("bad-slug")
|
17
|
+
# #=> raise ActiveRecord::RecordNotFound
|
18
|
+
#
|
19
|
+
# MyModel.friendly.find("bad-slug", allow_nil: true)
|
20
|
+
# #=> nil
|
21
|
+
#
|
12
22
|
# Since FriendlyId 5.0, if the id is a nonnumeric string like '123-foo' it
|
13
23
|
# will *only* search by friendly id and not fall back to the regular find
|
14
24
|
# method.
|
15
25
|
#
|
16
26
|
# If you want to search only by the friendly id, use {#find_by_friendly_id}.
|
17
27
|
# @raise ActiveRecord::RecordNotFound
|
18
|
-
def find(*args)
|
28
|
+
def find(*args, allow_nil: false)
|
19
29
|
id = args.first
|
20
|
-
return super if args.count != 1 || id.unfriendly_id?
|
21
|
-
first_by_friendly_id(id).tap {|result| return result unless result.nil?}
|
22
|
-
return super if potential_primary_key?(id)
|
23
|
-
|
30
|
+
return super(*args) if args.count != 1 || id.unfriendly_id?
|
31
|
+
first_by_friendly_id(id).tap { |result| return result unless result.nil? }
|
32
|
+
return super(*args) if potential_primary_key?(id)
|
33
|
+
|
34
|
+
raise_not_found_exception(id) unless allow_nil
|
35
|
+
rescue ActiveRecord::RecordNotFound => exception
|
36
|
+
raise exception unless allow_nil
|
24
37
|
end
|
25
38
|
|
26
39
|
# Returns true if a record with the given id exists.
|
27
40
|
def exists?(conditions = :none)
|
28
|
-
return super
|
29
|
-
exists_by_friendly_id?(conditions)
|
41
|
+
return super if conditions.unfriendly_id?
|
42
|
+
return true if exists_by_friendly_id?(conditions)
|
43
|
+
super
|
30
44
|
end
|
31
45
|
|
32
46
|
# Finds exclusively by the friendly id, completely bypassing original
|
33
47
|
# `find`.
|
34
48
|
# @raise ActiveRecord::RecordNotFound
|
35
49
|
def find_by_friendly_id(id)
|
36
|
-
first_by_friendly_id(id) or
|
50
|
+
first_by_friendly_id(id) or raise_not_found_exception(id)
|
37
51
|
end
|
38
52
|
|
39
53
|
def exists_by_friendly_id?(id)
|
40
|
-
where(friendly_id_config.query_field => id).exists?
|
54
|
+
where(friendly_id_config.query_field => parse_friendly_id(id)).exists?
|
41
55
|
end
|
42
56
|
|
43
57
|
private
|
@@ -48,7 +62,11 @@ module FriendlyId
|
|
48
62
|
key_type = key_type.type if key_type.respond_to?(:type)
|
49
63
|
case key_type
|
50
64
|
when :integer
|
51
|
-
|
65
|
+
begin
|
66
|
+
Integer(id, 10)
|
67
|
+
rescue
|
68
|
+
false
|
69
|
+
end
|
52
70
|
when :uuid
|
53
71
|
id.match(/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/)
|
54
72
|
else
|
@@ -57,8 +75,49 @@ module FriendlyId
|
|
57
75
|
end
|
58
76
|
|
59
77
|
def first_by_friendly_id(id)
|
60
|
-
find_by(friendly_id_config.query_field => id)
|
78
|
+
find_by(friendly_id_config.query_field => parse_friendly_id(id))
|
61
79
|
end
|
62
80
|
|
81
|
+
# Parse the given value to make it suitable for use as a slug according to
|
82
|
+
# your application's rules.
|
83
|
+
#
|
84
|
+
# This method is not intended to be invoked directly; FriendlyId uses it
|
85
|
+
# internally to process a slug into string to use as a finder.
|
86
|
+
#
|
87
|
+
# However, if FriendlyId's default slug parsing doesn't suit your needs,
|
88
|
+
# you can override this method in your model class to control exactly how
|
89
|
+
# slugs are generated.
|
90
|
+
#
|
91
|
+
# ### Example
|
92
|
+
#
|
93
|
+
# class Person < ActiveRecord::Base
|
94
|
+
# extend FriendlyId
|
95
|
+
# friendly_id :name_and_location
|
96
|
+
#
|
97
|
+
# def name_and_location
|
98
|
+
# "#{name} from #{location}"
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# # Use default slug, but lower case
|
102
|
+
# # If `id` is "Jane-Doe" or "JANE-DOE", this finds data by "jane-doe"
|
103
|
+
# def parse_friendly_id(slug)
|
104
|
+
# super.downcase
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# @param [#to_s] value The slug to be parsed.
|
109
|
+
# @return The parsed slug, which is not modified by default.
|
110
|
+
def parse_friendly_id(value)
|
111
|
+
value
|
112
|
+
end
|
113
|
+
|
114
|
+
def raise_not_found_exception(id)
|
115
|
+
message = "can't find record with friendly id: #{id.inspect}"
|
116
|
+
if ActiveRecord.version < Gem::Version.create("5.0")
|
117
|
+
raise ActiveRecord::RecordNotFound.new(message)
|
118
|
+
else
|
119
|
+
raise ActiveRecord::RecordNotFound.new(message, name, friendly_id_config.query_field, id)
|
120
|
+
end
|
121
|
+
end
|
63
122
|
end
|
64
123
|
end
|