friendly_id 5.2.4 → 5.5.0
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.
- 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
|