friendly_id 5.2.3 → 5.4.1
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.tar.gz.sig +0 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/stale.yml +17 -0
- data/.github/workflows/test.yml +60 -0
- data/Changelog.md +43 -1
- data/Gemfile +3 -0
- data/README.md +61 -168
- data/Rakefile +2 -2
- data/UPGRADING.md +115 -0
- data/certs/parndt.pem +25 -0
- data/friendly_id.gemspec +7 -3
- data/gemfiles/{Gemfile.rails-4.2.rb → Gemfile.rails-5.2.rb} +4 -5
- data/gemfiles/{Gemfile.rails-4.1.rb → Gemfile.rails-6.0.rb} +5 -7
- data/lib/friendly_id/base.rb +4 -8
- data/lib/friendly_id/candidates.rb +0 -2
- data/lib/friendly_id/configuration.rb +3 -2
- data/lib/friendly_id/finder_methods.rb +18 -7
- data/lib/friendly_id/finders.rb +1 -1
- data/lib/friendly_id/history.rb +21 -12
- data/lib/friendly_id/initializer.rb +11 -0
- data/lib/friendly_id/migration.rb +9 -3
- data/lib/friendly_id/object_utils.rb +9 -2
- data/lib/friendly_id/scoped.rb +8 -1
- data/lib/friendly_id/sequentially_slugged.rb +12 -2
- data/lib/friendly_id/slug.rb +4 -0
- data/lib/friendly_id/slugged.rb +2 -2
- data/lib/friendly_id/version.rb +1 -1
- data/test/databases.yml +6 -4
- data/test/finders_test.rb +24 -0
- data/test/helper.rb +13 -3
- data/test/history_test.rb +86 -7
- data/test/numeric_slug_test.rb +31 -0
- data/test/object_utils_test.rb +2 -0
- data/test/schema.rb +19 -2
- data/test/scoped_test.rb +13 -0
- data/test/sequentially_slugged_test.rb +59 -0
- data/test/shared.rb +2 -2
- data/test/simple_i18n_test.rb +2 -2
- data/test/slugged_test.rb +168 -4
- metadata +44 -16
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -40
- data/gemfiles/Gemfile.rails-4.0.rb +0 -30
- data/gemfiles/Gemfile.rails-5.0.rb +0 -28
data/Rakefile
CHANGED
@@ -71,7 +71,7 @@ namespace :db do
|
|
71
71
|
driver = FriendlyId::Test::Database.driver
|
72
72
|
config = FriendlyId::Test::Database.config[driver]
|
73
73
|
commands = {
|
74
|
-
"mysql" => "mysql -u #{config['username']} -e 'create database #{config["database"]};' >/dev/null",
|
74
|
+
"mysql" => "mysql -h #{config['host']} -P #{config['port']} -u #{config['username']} --password=#{config['password']} -e 'create database #{config["database"]};' >/dev/null",
|
75
75
|
"postgres" => "psql -c 'create database #{config['database']};' -U #{config['username']} >/dev/null"
|
76
76
|
}
|
77
77
|
%x{#{commands[driver] || true}}
|
@@ -83,7 +83,7 @@ namespace :db do
|
|
83
83
|
driver = FriendlyId::Test::Database.driver
|
84
84
|
config = FriendlyId::Test::Database.config[driver]
|
85
85
|
commands = {
|
86
|
-
"mysql" => "mysql -u #{config['username']} -e 'drop database #{config["database"]};' >/dev/null",
|
86
|
+
"mysql" => "mysql -h #{config['host']} -P #{config['port']} -u #{config['username']} --password=#{config['password']} -e 'drop database #{config["database"]};' >/dev/null",
|
87
87
|
"postgres" => "psql -c 'drop database #{config['database']};' -U #{config['username']} >/dev/null"
|
88
88
|
}
|
89
89
|
%x{#{commands[driver] || true}}
|
data/UPGRADING.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
## Articles
|
2
|
+
|
3
|
+
* [Migrating an ad-hoc URL slug system to FriendlyId](http://olivierlacan.com/posts/migrating-an-ad-hoc-url-slug-system-to-friendly-id/)
|
4
|
+
* [Pretty URLs with FriendlyId](http://railscasts.com/episodes/314-pretty-urls-with-friendlyid)
|
5
|
+
|
6
|
+
## Docs
|
7
|
+
|
8
|
+
The most current docs from the master branch can always be found
|
9
|
+
[here](http://norman.github.io/friendly_id).
|
10
|
+
|
11
|
+
Docs for older versions are also available:
|
12
|
+
|
13
|
+
* [5.0](http://norman.github.io/friendly_id/5.0/)
|
14
|
+
* [4.0](http://norman.github.io/friendly_id/4.0/)
|
15
|
+
* [3.3](http://norman.github.io/friendly_id/3.3/)
|
16
|
+
* [2.3](http://norman.github.io/friendly_id/2.3/)
|
17
|
+
|
18
|
+
## What Changed in Version 5.1
|
19
|
+
|
20
|
+
5.1 is a bugfix release, but bumps the minor version because some applications may be dependent
|
21
|
+
on the previously buggy behavior. The changes include:
|
22
|
+
|
23
|
+
* Blank strings can no longer be used as slugs.
|
24
|
+
* When the first slug candidate is rejected because it is reserved, additional candidates will
|
25
|
+
now be considered before marking the record as invalid.
|
26
|
+
* The `:finders` module is now compatible with Rails 4.2.
|
27
|
+
|
28
|
+
## What Changed in Version 5.0
|
29
|
+
|
30
|
+
As of version 5.0, FriendlyId uses [semantic versioning](http://semver.org/). Therefore, as you might
|
31
|
+
infer from the version number, 5.0 introduces changes incompatible with 4.0.
|
32
|
+
|
33
|
+
The most important changes are:
|
34
|
+
|
35
|
+
* Finders are no longer overridden by default. If you want to do friendly finds,
|
36
|
+
you must do `Model.friendly.find` rather than `Model.find`. You can however
|
37
|
+
restore FriendlyId 4-style finders by using the `:finders` addon:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
friendly_id :foo, use: :slugged # you must do MyClass.friendly.find('bar')
|
41
|
+
# or...
|
42
|
+
friendly_id :foo, use: [:slugged, :finders] # you can now do MyClass.find('bar')
|
43
|
+
```
|
44
|
+
* A new "candidates" functionality which makes it easy to set up a list of
|
45
|
+
alternate slugs that can be used to uniquely distinguish records, rather than
|
46
|
+
appending a sequence. For example:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class Restaurant < ActiveRecord::Base
|
50
|
+
extend FriendlyId
|
51
|
+
friendly_id :slug_candidates, use: :slugged
|
52
|
+
|
53
|
+
# Try building a slug based on the following fields in
|
54
|
+
# increasing order of specificity.
|
55
|
+
def slug_candidates
|
56
|
+
[
|
57
|
+
:name,
|
58
|
+
[:name, :city],
|
59
|
+
[:name, :street, :city],
|
60
|
+
[:name, :street_number, :street, :city]
|
61
|
+
]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
```
|
65
|
+
* Now that candidates have been added, FriendlyId no longer uses a numeric
|
66
|
+
sequence to differentiate conflicting slug, but rather a UUID (e.g. something
|
67
|
+
like `2bc08962-b3dd-4f29-b2e6-244710c86106`). This makes the
|
68
|
+
codebase simpler and more reliable when running concurrently, at the expense
|
69
|
+
of uglier ids being generated when there are conflicts.
|
70
|
+
* The default sequence separator has been changed from two dashes to one dash.
|
71
|
+
* Slugs are no longer regenerated when a record is saved. If you want to regenerate
|
72
|
+
a slug, you must explicitly set the slug column to nil:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
restaurant.friendly_id # joes-diner
|
76
|
+
restaurant.name = "The Plaza Diner"
|
77
|
+
restaurant.save!
|
78
|
+
restaurant.friendly_id # joes-diner
|
79
|
+
restaurant.slug = nil
|
80
|
+
restaurant.save!
|
81
|
+
restaurant.friendly_id # the-plaza-diner
|
82
|
+
```
|
83
|
+
|
84
|
+
You can restore some of the old behavior by overriding the
|
85
|
+
`should_generate_new_friendly_id?` method.
|
86
|
+
* The `friendly_id` Rails generator now generates an initializer showing you
|
87
|
+
how to do some common global configuration.
|
88
|
+
* The Globalize plugin has moved to a [separate gem](https://github.com/norman/friendly_id-globalize) (currently in alpha).
|
89
|
+
* The `:reserved` module no longer includes any default reserved words.
|
90
|
+
Previously it blocked "edit" and "new" everywhere. The default word list has
|
91
|
+
been moved to `config/initializers/friendly_id.rb` and now includes many more
|
92
|
+
words.
|
93
|
+
* The `:history` and `:scoped` addons can now be used together.
|
94
|
+
* Since it now requires Rails 4, FriendlyId also now requires Ruby 1.9.3 or
|
95
|
+
higher.
|
96
|
+
|
97
|
+
## Upgrading from FriendlyId 4.0
|
98
|
+
|
99
|
+
Run `rails generate friendly_id --skip-migration` and edit the initializer
|
100
|
+
generated in `config/initializers/friendly_id.rb`. This file contains notes
|
101
|
+
describing how to restore (or not) some of the defaults from FriendlyId 4.0.
|
102
|
+
|
103
|
+
If you want to use the `:history` and `:scoped` addons together, you must add a
|
104
|
+
`:scope` column to your friendly_id_slugs table and replace the unique index on
|
105
|
+
`:slug` and `:sluggable_type` with a unique index on those two columns, plus
|
106
|
+
the new `:scope` column.
|
107
|
+
|
108
|
+
A migration like this should be sufficient:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
add_column :friendly_id_slugs, :scope, :string
|
112
|
+
remove_index :friendly_id_slugs, [:slug, :sluggable_type]
|
113
|
+
add_index :friendly_id_slugs, [:slug, :sluggable_type]
|
114
|
+
add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], unique: true
|
115
|
+
```
|
data/certs/parndt.pem
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIEMjCCApqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhnZW1z
|
3
|
+
L0RDPXAvREM9YXJuZHQvREM9aW8wHhcNMjAwNTEwMjIxOTQ2WhcNMjEwNTEwMjIx
|
4
|
+
OTQ2WjAjMSEwHwYDVQQDDBhnZW1zL0RDPXAvREM9YXJuZHQvREM9aW8wggGiMA0G
|
5
|
+
CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDT+JzHYPGMYJt9ct2DCsbIymn1uJJp
|
6
|
+
HnDkQESfsGe40jTC90oF2iVbVOkaacNc1N3CSWUZvZjuygUuS86P6/kpBILGdO2+
|
7
|
+
bkXXKtfGC2YGGx9TdNLpCb4925vQHvdFeKXGpQDZdDw1SNC6zraZou47CvOE1cl2
|
8
|
+
Bp+1QMZuGRZ4+5CzOEWDWurjqce3O1jUEbyBB7z5H0h/YEaxfXipxhL1Dhi0sgkH
|
9
|
+
qP/e6SxzifdifdZCksJFQ06a1ji9hJY6eM23qbv/aaluVHAZSVBAQBS7rYniLo+N
|
10
|
+
G4vpFhoubQO5u8UluUtCaPUpI/qOvVcSaZn3ZkzlMwC8b1RwAeXBQmtFE2wnrv2i
|
11
|
+
ovTwoN7rHchwhgaHbkuFh4Wr92wGbrWL7J+X8rWKk1f8RF4kvtNE/NA6YrkxTpVh
|
12
|
+
QMyDmekt7rTxvcq2NneLGroWIUVCx/JID+Jw492LKQ6Sl1/P2TRzdEDtqZAZL0gt
|
13
|
+
xlWeMUfGG2D/gLnhs5qnaFaWQwGTmBnTgHcCAwEAAaNxMG8wCQYDVR0TBAIwADAL
|
14
|
+
BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEqtAyQVxPgKsrgoTQ1YmaIu/fmvMBoGA1Ud
|
15
|
+
EQQTMBGBD2dlbXNAcC5hcm5kdC5pbzAaBgNVHRIEEzARgQ9nZW1zQHAuYXJuZHQu
|
16
|
+
aW8wDQYJKoZIhvcNAQELBQADggGBALu2HM50B8xqlAXkCwavJDvWWtV9pG1igFUg
|
17
|
+
friZRWprUQ5nTaNmAd8p8qbJQwaIK2gt+DfYWfB9LtKnQTfbhLRBbmJ7zYw8LjKY
|
18
|
+
PwCs4RWjDAiuyCO3ppfsz+1bsMUXPLgWlaUkXsUy3nr2NruEFTO9zu3wGYQQ93Tt
|
19
|
+
vYSHOnP35UB4QjsjNrOO7FBaQfy6O909PP+GnVcJ62s9c26voJz63RSolwY7Jydw
|
20
|
+
XUlG68jjJKSoDHRzVTmNB7sX8rs8P2kvYkpIUXPHyls3mWBWjBWbdEYWESZrxI2x
|
21
|
+
dS7jY3AnfqhvsWra2pSREb2IDqPnJrHVOejnEI/zuuufUxLwDx3AC6SMdsyWkZ7V
|
22
|
+
9OmLt2rg75Sct6h2220lO5ySqYtqAXuOMBDGv5L0zLalx1g8LACA7uILTKVWh8B8
|
23
|
+
Hsej0MQ3drCB1eA4c9OXdCUQJnY2aLTq3uNvTbZvoTgWK55eq3KLBJ4zzoKZ4tBX
|
24
|
+
/HIFI/fEwYlI1Ji3oikUrHkc4rWgaQ==
|
25
|
+
-----END CERTIFICATE-----
|
data/friendly_id.gemspec
CHANGED
@@ -8,18 +8,17 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.email = ["norman@njclarke.com", "p@arndt.io"]
|
9
9
|
s.homepage = "https://github.com/norman/friendly_id"
|
10
10
|
s.summary = "A comprehensive slugging and pretty-URL plugin."
|
11
|
-
s.rubyforge_project = "friendly_id"
|
12
11
|
s.files = `git ls-files`.split("\n")
|
13
12
|
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
14
13
|
s.require_paths = ["lib"]
|
15
14
|
s.license = 'MIT'
|
16
15
|
|
17
|
-
s.required_ruby_version = '>= 1.
|
16
|
+
s.required_ruby_version = '>= 2.1.0'
|
18
17
|
|
19
18
|
s.add_dependency 'activerecord', '>= 4.0.0'
|
20
19
|
|
21
20
|
s.add_development_dependency 'coveralls'
|
22
|
-
s.add_development_dependency 'railties', '
|
21
|
+
s.add_development_dependency 'railties', '>= 4.0'
|
23
22
|
s.add_development_dependency 'minitest', '~> 5.3'
|
24
23
|
s.add_development_dependency 'mocha', '~> 1.1'
|
25
24
|
s.add_development_dependency 'yard'
|
@@ -32,4 +31,9 @@ FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
|
|
32
31
|
Active Record. It lets you create pretty URLs and work with human-friendly
|
33
32
|
strings as if they were numeric ids.
|
34
33
|
EOM
|
34
|
+
|
35
|
+
s.cert_chain = [File.expand_path('certs/parndt.pem', __dir__)]
|
36
|
+
if $PROGRAM_NAME =~ /gem\z/ && ARGV.include?('build') && ARGV.include?(__FILE__)
|
37
|
+
s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
|
38
|
+
end
|
35
39
|
end
|
@@ -2,15 +2,14 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec path: '../'
|
4
4
|
|
5
|
-
gem 'activerecord', '~>
|
6
|
-
gem 'railties', '~>
|
7
|
-
gem 'i18n', '~> 0.7.0'
|
5
|
+
gem 'activerecord', '~> 5.2.0'
|
6
|
+
gem 'railties', '~> 5.2.0'
|
8
7
|
|
9
8
|
# Database Configuration
|
10
9
|
group :development, :test do
|
11
10
|
platforms :jruby do
|
12
|
-
gem 'activerecord-jdbcmysql-adapter', '~> 1
|
13
|
-
gem 'activerecord-jdbcpostgresql-adapter', '~> 1
|
11
|
+
gem 'activerecord-jdbcmysql-adapter', '~> 51.1'
|
12
|
+
gem 'activerecord-jdbcpostgresql-adapter', '~> 51.1'
|
14
13
|
gem 'kramdown'
|
15
14
|
end
|
16
15
|
|
@@ -2,21 +2,20 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec path: '../'
|
4
4
|
|
5
|
-
gem 'activerecord', '~>
|
6
|
-
gem 'railties', '~>
|
5
|
+
gem 'activerecord', '~> 6.0.0'
|
6
|
+
gem 'railties', '~> 6.0.0'
|
7
7
|
|
8
8
|
# Database Configuration
|
9
9
|
group :development, :test do
|
10
10
|
platforms :jruby do
|
11
|
-
gem 'activerecord-
|
12
|
-
gem 'activerecord-
|
13
|
-
gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.14'
|
11
|
+
gem 'activerecord-jdbcmysql-adapter', '~> 51.1'
|
12
|
+
gem 'activerecord-jdbcpostgresql-adapter', '~> 51.1'
|
14
13
|
gem 'kramdown'
|
15
14
|
end
|
16
15
|
|
17
16
|
platforms :ruby, :rbx do
|
18
17
|
gem 'sqlite3'
|
19
|
-
gem 'mysql2'
|
18
|
+
gem 'mysql2'
|
20
19
|
gem 'pg'
|
21
20
|
gem 'redcarpet'
|
22
21
|
end
|
@@ -24,6 +23,5 @@ group :development, :test do
|
|
24
23
|
platforms :rbx do
|
25
24
|
gem 'rubysl', '~> 2.0'
|
26
25
|
gem 'rubinius-developer_tools'
|
27
|
-
gem 'json'
|
28
26
|
end
|
29
27
|
end
|
data/lib/friendly_id/base.rb
CHANGED
@@ -159,8 +159,9 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
159
159
|
#
|
160
160
|
# @option options [Symbol,Module] :use The addon or name of an addon to use.
|
161
161
|
# By default, FriendlyId provides {FriendlyId::Slugged :slugged},
|
162
|
-
# {FriendlyId::
|
163
|
-
# {FriendlyId::
|
162
|
+
# {FriendlyId::Reserved :finders}, {FriendlyId::History :history},
|
163
|
+
# {FriendlyId::Reserved :reserved}, {FriendlyId::Scoped :scoped}, and
|
164
|
+
# {FriendlyId::SimpleI18n :simple_i18n}.
|
164
165
|
#
|
165
166
|
# @option options [Array] :reserved_words Available when using `:reserved`,
|
166
167
|
# which is loaded by default. Sets an array of words banned for use as
|
@@ -261,12 +262,7 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
261
262
|
# Either the friendly_id, or the numeric id cast to a string.
|
262
263
|
def to_param
|
263
264
|
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
|
265
|
+
friendly_id.presence.to_param || super
|
270
266
|
else
|
271
267
|
super
|
272
268
|
end
|
@@ -25,6 +25,7 @@ module FriendlyId
|
|
25
25
|
attr_accessor :routes
|
26
26
|
|
27
27
|
def initialize(model_class, values = nil)
|
28
|
+
@base = nil
|
28
29
|
@model_class = model_class
|
29
30
|
@defaults = {}
|
30
31
|
@modules = []
|
@@ -47,8 +48,8 @@ module FriendlyId
|
|
47
48
|
#
|
48
49
|
# @param [#to_s,Module] modules Arguments should be Modules, or symbols or
|
49
50
|
# strings that correspond with the name of an addon to use with FriendlyId.
|
50
|
-
# By default FriendlyId provides `:slugged`, `:
|
51
|
-
# and `:scoped`.
|
51
|
+
# By default FriendlyId provides `:slugged`, `:finders`, `:history`,
|
52
|
+
# `:reserved`, `:simple_i18n`, and `:scoped`.
|
52
53
|
def use(*modules)
|
53
54
|
modules.to_a.flatten.compact.map do |object|
|
54
55
|
mod = get_module(object)
|
@@ -9,7 +9,7 @@ module FriendlyId
|
|
9
9
|
# id matching '123' and then fall back to looking for a record with the
|
10
10
|
# numeric id '123'.
|
11
11
|
#
|
12
|
-
# Since FriendlyId 5.0, if the id is a
|
12
|
+
# Since FriendlyId 5.0, if the id is a nonnumeric string like '123-foo' it
|
13
13
|
# will *only* search by friendly id and not fall back to the regular find
|
14
14
|
# method.
|
15
15
|
#
|
@@ -20,20 +20,22 @@ module FriendlyId
|
|
20
20
|
return super if args.count != 1 || id.unfriendly_id?
|
21
21
|
first_by_friendly_id(id).tap {|result| return result unless result.nil?}
|
22
22
|
return super if potential_primary_key?(id)
|
23
|
-
|
23
|
+
raise_not_found_exception id
|
24
|
+
|
24
25
|
end
|
25
26
|
|
26
27
|
# Returns true if a record with the given id exists.
|
27
28
|
def exists?(conditions = :none)
|
28
|
-
return super
|
29
|
-
exists_by_friendly_id?(conditions)
|
29
|
+
return super if conditions.unfriendly_id?
|
30
|
+
return true if exists_by_friendly_id?(conditions)
|
31
|
+
super
|
30
32
|
end
|
31
33
|
|
32
34
|
# Finds exclusively by the friendly id, completely bypassing original
|
33
35
|
# `find`.
|
34
36
|
# @raise ActiveRecord::RecordNotFound
|
35
37
|
def find_by_friendly_id(id)
|
36
|
-
first_by_friendly_id(id) or raise
|
38
|
+
first_by_friendly_id(id) or raise raise_not_found_exception(id)
|
37
39
|
end
|
38
40
|
|
39
41
|
def exists_by_friendly_id?(id)
|
@@ -50,14 +52,23 @@ module FriendlyId
|
|
50
52
|
when :integer
|
51
53
|
Integer(id, 10) rescue false
|
52
54
|
when :uuid
|
53
|
-
id.match
|
55
|
+
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
56
|
else
|
55
57
|
true
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
61
|
def first_by_friendly_id(id)
|
60
|
-
find_by(friendly_id_config.query_field => id)
|
62
|
+
find_by(friendly_id_config.query_field => id.downcase)
|
63
|
+
end
|
64
|
+
|
65
|
+
def raise_not_found_exception(id)
|
66
|
+
message = "can't find record with friendly id: #{id.inspect}"
|
67
|
+
if ActiveRecord.version < Gem::Version.create('5.0') then
|
68
|
+
raise ActiveRecord::RecordNotFound.new(message)
|
69
|
+
else
|
70
|
+
raise ActiveRecord::RecordNotFound.new(message, name, friendly_id_config.query_field, id)
|
71
|
+
end
|
61
72
|
end
|
62
73
|
|
63
74
|
end
|
data/lib/friendly_id/finders.rb
CHANGED
@@ -76,7 +76,7 @@ for models that use FriendlyId with something similar to the following:
|
|
76
76
|
def self.setup(model_class)
|
77
77
|
model_class.instance_eval do
|
78
78
|
relation.class.send(:include, friendly_id_config.finder_methods)
|
79
|
-
if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2) || ActiveRecord::VERSION::MAJOR
|
79
|
+
if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2) || ActiveRecord::VERSION::MAJOR >= 5
|
80
80
|
model_class.send(:extend, friendly_id_config.finder_methods)
|
81
81
|
end
|
82
82
|
end
|
data/lib/friendly_id/history.rb
CHANGED
@@ -44,9 +44,9 @@ method.
|
|
44
44
|
@post = Post.friendly.find params[:id]
|
45
45
|
|
46
46
|
# If an old id or a numeric id was used to find the record, then
|
47
|
-
# the request
|
48
|
-
# a 301 redirect
|
49
|
-
if
|
47
|
+
# the request slug will not match the current slug, and we should do
|
48
|
+
# a 301 redirect to the new path
|
49
|
+
if params[:id] != @post.slug
|
50
50
|
return redirect_to @post, :status => :moved_permanently
|
51
51
|
end
|
52
52
|
end
|
@@ -72,7 +72,7 @@ method.
|
|
72
72
|
# Configures the model instance to use the History add-on.
|
73
73
|
def self.included(model_class)
|
74
74
|
model_class.class_eval do
|
75
|
-
has_many :slugs, -> {order(
|
75
|
+
has_many :slugs, -> {order(id: :desc)}, **{
|
76
76
|
:as => :sluggable,
|
77
77
|
:dependent => @friendly_id_config.dependent_value,
|
78
78
|
:class_name => Slug.to_s
|
@@ -86,14 +86,13 @@ method.
|
|
86
86
|
include ::FriendlyId::FinderMethods
|
87
87
|
|
88
88
|
def exists_by_friendly_id?(id)
|
89
|
-
|
89
|
+
super || joins(:slugs).where(slug_history_clause(id)).exists?
|
90
90
|
end
|
91
91
|
|
92
92
|
private
|
93
93
|
|
94
94
|
def first_by_friendly_id(id)
|
95
|
-
|
96
|
-
matching_record || slug_table_record(id)
|
95
|
+
super || slug_table_record(id)
|
97
96
|
end
|
98
97
|
|
99
98
|
def slug_table_record(id)
|
@@ -111,9 +110,10 @@ method.
|
|
111
110
|
# to be conflicts. This will allow a record to revert to a previously
|
112
111
|
# used slug.
|
113
112
|
def scope_for_slug_generator
|
114
|
-
relation = super
|
115
|
-
|
116
|
-
|
113
|
+
relation = super.joins(:slugs)
|
114
|
+
unless new_record?
|
115
|
+
relation = relation.merge(Slug.where('sluggable_id <> ?', id))
|
116
|
+
end
|
117
117
|
if friendly_id_config.uses?(:scoped)
|
118
118
|
relation = relation.where(Slug.arel_table[:scope].eq(serialized_scope))
|
119
119
|
end
|
@@ -122,17 +122,26 @@ method.
|
|
122
122
|
|
123
123
|
def create_slug
|
124
124
|
return unless friendly_id
|
125
|
-
return if
|
125
|
+
return if history_is_up_to_date?
|
126
126
|
# Allow reversion back to a previously used slug
|
127
127
|
relation = slugs.where(:slug => friendly_id)
|
128
128
|
if friendly_id_config.uses?(:scoped)
|
129
129
|
relation = relation.where(:scope => serialized_scope)
|
130
130
|
end
|
131
|
-
relation.
|
131
|
+
relation.destroy_all unless relation.empty?
|
132
132
|
slugs.create! do |record|
|
133
133
|
record.slug = friendly_id
|
134
134
|
record.scope = serialized_scope if friendly_id_config.uses?(:scoped)
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
def history_is_up_to_date?
|
139
|
+
latest_history = slugs.first
|
140
|
+
check = latest_history.try(:slug) == friendly_id
|
141
|
+
if friendly_id_config.uses?(:scoped)
|
142
|
+
check = check && latest_history.scope == serialized_scope
|
143
|
+
end
|
144
|
+
check
|
145
|
+
end
|
137
146
|
end
|
138
147
|
end
|