friendly_id 4.1.0.beta.1 → 5.0.0.alpha.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 +7 -0
- data/.travis.yml +7 -12
- data/Changelog.md +4 -0
- data/Gemfile +2 -2
- data/Guide.rdoc +34 -63
- data/README.md +116 -60
- data/Rakefile +5 -1
- data/WhatsNew.md +2 -94
- data/friendly_id.gemspec +10 -20
- data/gemfiles/Gemfile.rails-4.0.rb +19 -0
- data/lib/friendly_id.rb +11 -6
- data/lib/friendly_id/.gitattributes +1 -0
- data/lib/friendly_id/base.rb +6 -65
- data/lib/friendly_id/candidates.rb +41 -0
- data/lib/friendly_id/configuration.rb +10 -6
- data/lib/friendly_id/history.rb +22 -60
- data/lib/friendly_id/object_utils.rb +1 -1
- data/lib/friendly_id/scoped.rb +40 -34
- data/lib/friendly_id/scopes.rb +28 -0
- data/lib/friendly_id/simple_i18n.rb +13 -3
- data/lib/friendly_id/slug.rb +0 -1
- data/lib/friendly_id/slug_generator.rb +9 -68
- data/lib/friendly_id/slugged.rb +22 -34
- data/lib/friendly_id/version.rb +3 -0
- data/lib/generators/friendly_id_generator.rb +5 -4
- data/test/helper.rb +1 -1
- data/test/history_test.rb +63 -56
- data/test/object_utils_test.rb +0 -1
- data/test/schema.rb +1 -10
- data/test/shared.rb +27 -23
- data/test/simple_i18n_test.rb +3 -2
- data/test/slugged_test.rb +17 -48
- data/test/sti_test.rb +2 -2
- metadata +40 -103
- data/gemfiles/Gemfile.rails-3.0.rb +0 -21
- data/gemfiles/Gemfile.rails-3.1.rb +0 -22
- data/gemfiles/Gemfile.rails-3.2.rb +0 -22
- data/lib/friendly_id/finder_methods.rb +0 -35
- data/lib/friendly_id/globalize.rb +0 -115
- data/test/globalize_test.rb +0 -57
data/WhatsNew.md
CHANGED
@@ -1,95 +1,3 @@
|
|
1
|
-
# What's New in FriendlyId
|
1
|
+
# What's New in FriendlyId 5?
|
2
2
|
|
3
|
-
##
|
4
|
-
|
5
|
-
FriendlyId is mostly a different codebase from FriendlyId 3. However, this isn't
|
6
|
-
the "big rewrite," it's the "small rewrite:"
|
7
|
-
|
8
|
-
Adding new features with each release is not sustainable. This release *removes*
|
9
|
-
features, but makes it possible to add them back as addons. We can also remove
|
10
|
-
some complexity by relying on the better default functionality provided by newer
|
11
|
-
versions of Active Support and Active Record.
|
12
|
-
|
13
|
-
Here's what's changed:
|
14
|
-
|
15
|
-
## New configuration and setup
|
16
|
-
|
17
|
-
FriendlyId is no longer added to Active Record by default, you must explicitly
|
18
|
-
add it to each model you want to use it in. The method and options have also
|
19
|
-
changed:
|
20
|
-
|
21
|
-
# FriendlyId 3
|
22
|
-
class Post < ActiveRecord::Base
|
23
|
-
has_friendly_id :title, :use_slugs => true
|
24
|
-
end
|
25
|
-
|
26
|
-
# FriendlyId 4
|
27
|
-
class Post < ActiveRecord::Base
|
28
|
-
extend FriendlyId
|
29
|
-
friendly_id :title, :use => :slugged
|
30
|
-
end
|
31
|
-
|
32
|
-
It also adds a new "defaults" method for configuring all models:
|
33
|
-
|
34
|
-
FriendlyId.defaults do |config|
|
35
|
-
config.use :slugged, :reserved
|
36
|
-
config.base = :name
|
37
|
-
end
|
38
|
-
|
39
|
-
## Active Record 3+ only
|
40
|
-
|
41
|
-
For 2.3 support, you can use FriendlyId 3.x, which will continue to be
|
42
|
-
maintained until people don't want it any more.
|
43
|
-
|
44
|
-
## In-table slugs
|
45
|
-
|
46
|
-
FriendlyId no longer creates a separate slugs table - it just stores the
|
47
|
-
generated slug value in the model table, which is simpler, faster and what most
|
48
|
-
want by default. Keeping slug history in a separate table is an
|
49
|
-
{FriendlyId::History optional add-on} for FriendlyId 4.
|
50
|
-
|
51
|
-
## No more multiple finds
|
52
|
-
|
53
|
-
Person.find "joe-schmoe" # Supported
|
54
|
-
Person.find ["joe-schmoe", "john-doe"] # No longer supported
|
55
|
-
|
56
|
-
If you want find by more than one friendly id, build your own query:
|
57
|
-
|
58
|
-
Person.where(:slug => ["joe-schmoe", "john-doe"])
|
59
|
-
|
60
|
-
This lets us do *far* less monkeypatching in Active Record. How much less?
|
61
|
-
FriendlyId overrides the base find with a mere 2 lines of code, and otherwise
|
62
|
-
changes nothing else. This means more stability and less breakage between Rails
|
63
|
-
updates.
|
64
|
-
|
65
|
-
## No more finder status
|
66
|
-
|
67
|
-
FriendlyId 3 offered finder statuses to help you determine when an outdated
|
68
|
-
or non-friendly id was used to find the record, so that you could decide whether
|
69
|
-
to permanently redirect to the canonical URL. However, there's a simpler way to
|
70
|
-
do that, so this feature has been removed:
|
71
|
-
|
72
|
-
if request.path != person_path(@person)
|
73
|
-
return redirect_to @person, :status => :moved_permanently
|
74
|
-
end
|
75
|
-
|
76
|
-
## Bye-bye Babosa
|
77
|
-
|
78
|
-
[Babosa](http://github.com/norman/babosa) is FriendlyId 3's slugging library.
|
79
|
-
|
80
|
-
FriendlyId 4 doesn't use it by default because the most important pieces of it
|
81
|
-
were already accepted into Active Support 3.
|
82
|
-
|
83
|
-
However, Babosa is still useful, for example, for idiomatically transliterating
|
84
|
-
Cyrillic ([or other
|
85
|
-
language](https://github.com/norman/babosa/tree/master/lib/babosa/transliterator))
|
86
|
-
strings to ASCII. It's very easy to include - just override
|
87
|
-
`#normalize_friendly_id` in your model:
|
88
|
-
|
89
|
-
class MyModel < ActiveRecord::Base
|
90
|
-
...
|
91
|
-
|
92
|
-
def normalize_friendly_id(text)
|
93
|
-
text.to_slug.normalize! :transliterations => :russian
|
94
|
-
end
|
95
|
-
end
|
3
|
+
## Write me
|
data/friendly_id.gemspec
CHANGED
@@ -1,43 +1,33 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
require "friendly_id"
|
2
|
+
require File.expand_path("../lib/friendly_id/version", __FILE__)
|
5
3
|
|
6
4
|
Gem::Specification.new do |s|
|
7
5
|
s.name = "friendly_id"
|
8
6
|
s.version = FriendlyId::VERSION
|
9
7
|
s.authors = ["Norman Clarke", "Philip Arndt"]
|
10
|
-
s.email = ["norman@njclarke.com", "
|
11
|
-
s.homepage = "http://github.com/
|
8
|
+
s.email = ["norman@njclarke.com", "p@arndt.io"]
|
9
|
+
s.homepage = "http://github.com/FriendlyId/friendly_id"
|
12
10
|
s.summary = "A comprehensive slugging and pretty-URL plugin."
|
13
11
|
s.rubyforge_project = "friendly_id"
|
14
12
|
s.files = `git ls-files`.split("\n")
|
15
13
|
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
16
14
|
s.require_paths = ["lib"]
|
15
|
+
s.license = 'MIT'
|
16
|
+
|
17
|
+
s.required_ruby_version = '>= 1.9.3'
|
17
18
|
|
18
|
-
s.add_development_dependency "railties", "~>
|
19
|
-
s.add_development_dependency "activerecord", "~>
|
20
|
-
s.add_development_dependency "minitest", "
|
21
|
-
s.add_development_dependency "mocha"
|
22
|
-
s.add_development_dependency "maruku"
|
19
|
+
s.add_development_dependency "railties", "~> 4.0.0"
|
20
|
+
s.add_development_dependency "activerecord", "~> 4.0.0"
|
21
|
+
s.add_development_dependency "minitest", ">= 4.4.0"
|
22
|
+
s.add_development_dependency "mocha", "~> 0.13.3"
|
23
23
|
s.add_development_dependency "yard"
|
24
24
|
s.add_development_dependency "i18n"
|
25
25
|
s.add_development_dependency "ffaker"
|
26
26
|
s.add_development_dependency "simplecov"
|
27
|
-
s.add_development_dependency "globalize3"
|
28
27
|
|
29
28
|
s.description = <<-EOM
|
30
29
|
FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
|
31
30
|
Ruby on Rails. It allows you to create pretty URLs and work with human-friendly
|
32
31
|
strings as if they were numeric ids for Active Record models.
|
33
32
|
EOM
|
34
|
-
|
35
|
-
s.post_install_message = <<-EOM
|
36
|
-
NOTE: FriendlyId 4.x breaks compatibility with 3.x. If you're upgrading
|
37
|
-
from 3.x, please see this document:
|
38
|
-
|
39
|
-
http://rubydoc.info/github/norman/friendly_id/master/file/WhatsNew.md
|
40
|
-
|
41
|
-
EOM
|
42
|
-
|
43
33
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec path: '../'
|
4
|
+
|
5
|
+
# Database Configuration
|
6
|
+
group :development, :test do
|
7
|
+
platforms :jruby do
|
8
|
+
gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0.beta2'
|
9
|
+
gem 'activerecord-jdbcmysql-adapter', '>= 1.3.0.beta2'
|
10
|
+
gem 'activerecord-jdbcpostgresql-adapter', '>= 1.3.0.beta2'
|
11
|
+
gem 'jruby-openssl'
|
12
|
+
end
|
13
|
+
|
14
|
+
platforms :ruby do
|
15
|
+
gem 'sqlite3'
|
16
|
+
gem 'mysql2'
|
17
|
+
gem 'pg'
|
18
|
+
end
|
19
|
+
end
|
data/lib/friendly_id.rb
CHANGED
@@ -3,7 +3,7 @@ require "thread"
|
|
3
3
|
require "friendly_id/base"
|
4
4
|
require "friendly_id/object_utils"
|
5
5
|
require "friendly_id/configuration"
|
6
|
-
require "friendly_id/
|
6
|
+
require "friendly_id/scopes"
|
7
7
|
|
8
8
|
=begin
|
9
9
|
|
@@ -44,9 +44,6 @@ with numeric ids:
|
|
44
44
|
=end
|
45
45
|
module FriendlyId
|
46
46
|
|
47
|
-
# The current version.
|
48
|
-
VERSION = "4.1.0.beta.1"
|
49
|
-
|
50
47
|
@mutex = Mutex.new
|
51
48
|
|
52
49
|
autoload :History, "friendly_id/history"
|
@@ -55,7 +52,6 @@ module FriendlyId
|
|
55
52
|
autoload :Reserved, "friendly_id/reserved"
|
56
53
|
autoload :Scoped, "friendly_id/scoped"
|
57
54
|
autoload :Slugged, "friendly_id/slugged"
|
58
|
-
autoload :Globalize, "friendly_id/globalize"
|
59
55
|
|
60
56
|
# FriendlyId takes advantage of `extended` to do basic model setup, primarily
|
61
57
|
# extending {FriendlyId::Base} to add {FriendlyId::Base#friendly_id
|
@@ -84,10 +80,11 @@ module FriendlyId
|
|
84
80
|
class << model_class
|
85
81
|
alias relation_without_friendly_id relation
|
86
82
|
end
|
87
|
-
model_class.
|
83
|
+
model_class.class_eval do
|
88
84
|
extend Base
|
89
85
|
@friendly_id_config = Class.new(Configuration).new(self)
|
90
86
|
FriendlyId.defaults.call @friendly_id_config
|
87
|
+
include Model
|
91
88
|
end
|
92
89
|
end
|
93
90
|
|
@@ -111,4 +108,12 @@ module FriendlyId
|
|
111
108
|
@defaults ||= lambda {|config| config.use :reserved}
|
112
109
|
end
|
113
110
|
end
|
111
|
+
|
112
|
+
# Set the ActiveRecord table name prefix to friendly_id_
|
113
|
+
#
|
114
|
+
# This makes 'slugs' into 'friendly_id_slugs' and also respects any
|
115
|
+
# 'global' table_name_prefix set on ActiveRecord::Base.
|
116
|
+
def self.table_name_prefix
|
117
|
+
"#{ActiveRecord::Base.table_name_prefix}friendly_id_"
|
118
|
+
end
|
114
119
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
version.rb merge=ours
|
data/lib/friendly_id/base.rb
CHANGED
@@ -156,8 +156,7 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
156
156
|
# @option options [Symbol,Module] :use The addon or name of an addon to use.
|
157
157
|
# By default, FriendlyId provides {FriendlyId::Slugged :slugged},
|
158
158
|
# {FriendlyId::History :history}, {FriendlyId::Reserved :reserved}, and
|
159
|
-
# {FriendlyId::Scoped :scoped}, {FriendlyId::SimpleI18n :simple_i18n}
|
160
|
-
# and {FriendlyId::Globalize :globalize}.
|
159
|
+
# {FriendlyId::Scoped :scoped}, and {FriendlyId::SimpleI18n :simple_i18n}.
|
161
160
|
#
|
162
161
|
# @option options [Array] :reserved_words Available when using +:reserved+,
|
163
162
|
# which is loaded by default. Sets an array of words banned for use as
|
@@ -169,7 +168,7 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
169
168
|
#
|
170
169
|
# @option options [Symbol] :sequence_separator Available when using +:slugged+.
|
171
170
|
# Configures the sequence of characters used to separate a slug from a
|
172
|
-
# sequence. Defaults to
|
171
|
+
# sequence. Defaults to +-+.
|
173
172
|
#
|
174
173
|
# @option options [Symbol] :slug_column Available when using +:slugged+.
|
175
174
|
# Configures the name of the column where FriendlyId will store the slug.
|
@@ -189,8 +188,8 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
189
188
|
yield friendly_id_config if block_given?
|
190
189
|
friendly_id_config.use options.delete :use
|
191
190
|
friendly_id_config.send :set, base ? options.merge(:base => base) : options
|
192
|
-
before_save {|rec| rec.instance_eval {@current_friendly_id = friendly_id}}
|
193
191
|
include Model
|
192
|
+
extend Scopes
|
194
193
|
end
|
195
194
|
|
196
195
|
# Returns the model class's {FriendlyId::Configuration friendly_id_config}.
|
@@ -201,73 +200,15 @@ often better and easier to use {FriendlyId::Slugged slugs}.
|
|
201
200
|
def friendly_id_config
|
202
201
|
@friendly_id_config ||= base_class.friendly_id_config.dup.tap do |config|
|
203
202
|
config.model_class = self
|
204
|
-
@relation_class = base_class.send(:relation_class)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
private
|
209
|
-
|
210
|
-
# Gets an instance of an the relation class.
|
211
|
-
#
|
212
|
-
# With FriendlyId this will be a subclass of ActiveRecord::Relation, rather than
|
213
|
-
# Relation itself, in order to avoid tainting all Active Record models with
|
214
|
-
# FriendlyId.
|
215
|
-
#
|
216
|
-
# Note that this method is essentially copied and pasted from Rails 3.2.9.rc1,
|
217
|
-
# with the exception of changing the relation class. Obviously this is less than
|
218
|
-
# ideal, but I know of no better way to accomplish this.
|
219
|
-
# @see #relation_class
|
220
|
-
def relation #:nodoc:
|
221
|
-
relation = relation_class.new(self, arel_table)
|
222
|
-
|
223
|
-
if finder_needs_type_condition?
|
224
|
-
relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
|
225
|
-
else
|
226
|
-
relation
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
# Gets (and if necessary, creates) a subclass of the model's relation class.
|
231
|
-
#
|
232
|
-
# Rather than including FriendlyId's overridden finder methods in
|
233
|
-
# ActiveRecord::Relation directly, FriendlyId adds them to a subclass
|
234
|
-
# specific to the AR model, and makes #relation return an instance of this
|
235
|
-
# class. By doing this, we ensure that only models that specifically extend
|
236
|
-
# FriendlyId have their finder methods overridden.
|
237
|
-
#
|
238
|
-
# Note that this method does not directly subclass ActiveRecord::Relation,
|
239
|
-
# but rather whatever class the @relation class instance variable is an
|
240
|
-
# instance of. In practice, this will almost always end up being
|
241
|
-
# ActiveRecord::Relation, but in case another plugin is using this same
|
242
|
-
# pattern to extend a model's finder functionality, FriendlyId will not
|
243
|
-
# replace it, but rather override it.
|
244
|
-
#
|
245
|
-
# This pattern can be seen as a poor man's "refinement"
|
246
|
-
# (http://timelessrepo.com/refinements-in-ruby), and while I **think** it
|
247
|
-
# will work quite well, I realize that it could cause unexpected issues,
|
248
|
-
# since the authors of Rails are probably not intending this kind of usage
|
249
|
-
# against a private API. If this ends up being problematic I will probably
|
250
|
-
# revert back to the old behavior of simply extending
|
251
|
-
# ActiveRecord::Relation.
|
252
|
-
def relation_class
|
253
|
-
@relation_class or begin
|
254
|
-
@relation_class = Class.new(relation_without_friendly_id.class) do
|
255
|
-
alias_method :find_one_without_friendly_id, :find_one
|
256
|
-
alias_method :exists_without_friendly_id?, :exists?
|
257
|
-
include FriendlyId::FinderMethods
|
258
|
-
end
|
259
|
-
# Set a name so that model instances can be marshalled. Use a
|
260
|
-
# ridiculously long name that will not conflict with anything.
|
261
|
-
# TODO: just use the constant, no need for the @relation_class variable.
|
262
|
-
const_set('FriendlyIdActiveRecordRelation', @relation_class)
|
263
203
|
end
|
264
204
|
end
|
265
205
|
end
|
266
206
|
|
267
207
|
# Instance methods that will be added to all classes using FriendlyId.
|
268
208
|
module Model
|
269
|
-
|
270
|
-
|
209
|
+
def self.included(model_class)
|
210
|
+
return if model_class.respond_to?(:friendly)
|
211
|
+
end
|
271
212
|
|
272
213
|
# Convenience method for accessing the class method of the same name.
|
273
214
|
def friendly_id_config
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module FriendlyId
|
4
|
+
|
5
|
+
class Candidates
|
6
|
+
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize(object, *array)
|
10
|
+
@object = object
|
11
|
+
@candidates = to_candidate_array(object, array.flatten(1))
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(*args, &block)
|
15
|
+
@candidates.each(*args) do |candidate|
|
16
|
+
yield @object.normalize_friendly_id(candidate.map(&:call).join(' '))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def to_candidate_array(object, array)
|
23
|
+
array.map do |candidate|
|
24
|
+
case candidate
|
25
|
+
when String
|
26
|
+
[->{candidate}]
|
27
|
+
when Array
|
28
|
+
to_candidate_array(object, candidate).flatten
|
29
|
+
when Symbol
|
30
|
+
[object.method(candidate)]
|
31
|
+
else
|
32
|
+
if candidate.respond_to?(:call)
|
33
|
+
[candidate]
|
34
|
+
else
|
35
|
+
[->{candidate.to_s}]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -58,18 +58,18 @@ module FriendlyId
|
|
58
58
|
# @param [#to_s,Module] *modules Arguments should be Modules, or symbols or
|
59
59
|
# strings that correspond with the name of a module inside the FriendlyId
|
60
60
|
# namespace. By default FriendlyId provides +:slugged+, +:history+,
|
61
|
-
# +:simple_i18n+,
|
61
|
+
# +:simple_i18n+, and +:scoped+.
|
62
62
|
def use(*modules)
|
63
63
|
modules.to_a.flatten.compact.map do |object|
|
64
|
-
mod =
|
65
|
-
model_class.
|
66
|
-
@
|
64
|
+
mod = get_module(object)
|
65
|
+
mod.setup(@model_class) if mod.respond_to?(:setup)
|
66
|
+
@model_class.send(:include, mod) unless uses? object
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
# Returns whether the given module is in use
|
71
|
-
def uses?(
|
72
|
-
@
|
71
|
+
def uses?(mod)
|
72
|
+
@model_class < get_module(mod)
|
73
73
|
end
|
74
74
|
|
75
75
|
# The column that FriendlyId will use to find the record when querying by
|
@@ -83,6 +83,10 @@ module FriendlyId
|
|
83
83
|
|
84
84
|
private
|
85
85
|
|
86
|
+
def get_module(object)
|
87
|
+
Module === object ? object : FriendlyId.const_get(object.to_s.classify)
|
88
|
+
end
|
89
|
+
|
86
90
|
def set(values)
|
87
91
|
values and values.each {|name, value| self.send "#{name}=", value}
|
88
92
|
end
|
data/lib/friendly_id/history.rb
CHANGED
@@ -58,13 +58,26 @@ method.
|
|
58
58
|
|
59
59
|
# Configures the model instance to use the History add-on.
|
60
60
|
def self.included(model_class)
|
61
|
-
model_class.
|
61
|
+
model_class.class_eval do
|
62
62
|
@friendly_id_config.use :slugged
|
63
|
-
|
64
|
-
|
63
|
+
|
64
|
+
has_many :slugs, -> {order("#{Slug.quoted_table_name}.id DESC")}, {
|
65
|
+
:as => :sluggable,
|
66
|
+
:dependent => :destroy,
|
67
|
+
:class_name => Slug.to_s
|
68
|
+
}
|
65
69
|
after_save :create_slug
|
66
|
-
|
67
|
-
|
70
|
+
def self.find_by_friendly_id(id)
|
71
|
+
includes(:slugs).where(slug_history_clause(id)).references(:slugs).first
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.exists_by_friendly_id?(id)
|
75
|
+
includes(:slugs).where(arel_table[friendly_id_config.query_field].eq(id).or(slug_history_clause(id))).exists?
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.slug_history_clause(id)
|
79
|
+
Slug.arel_table[:sluggable_type].eq(base_class.to_s).and(Slug.arel_table[:slug].eq(id))
|
80
|
+
end
|
68
81
|
end
|
69
82
|
end
|
70
83
|
|
@@ -75,65 +88,14 @@ method.
|
|
75
88
|
return if slugs.first.try(:slug) == friendly_id
|
76
89
|
# Allow reversion back to a previously used slug
|
77
90
|
relation = slugs.where(:slug => friendly_id)
|
78
|
-
|
79
|
-
|
91
|
+
if friendly_id_config.uses?(:scoped)
|
92
|
+
relation = relation.where(:scope => serialized_scope)
|
93
|
+
end
|
94
|
+
relation.delete_all
|
80
95
|
slugs.create! do |record|
|
81
96
|
record.slug = friendly_id
|
82
97
|
record.scope = serialized_scope if friendly_id_config.uses?(:scoped)
|
83
98
|
end
|
84
99
|
end
|
85
|
-
|
86
|
-
# Adds a finder that explictly uses slugs from the slug table.
|
87
|
-
module FinderMethods
|
88
|
-
|
89
|
-
# Search for a record in the slugs table using the specified slug.
|
90
|
-
def find_one(id)
|
91
|
-
return super(id) if id.unfriendly_id?
|
92
|
-
where(@klass.friendly_id_config.query_field => id).first or
|
93
|
-
with_old_friendly_id(id) {|x| where(:id => x).first} or
|
94
|
-
find_one_without_friendly_id(id)
|
95
|
-
end
|
96
|
-
|
97
|
-
# Search for a record in the slugs table using the specified slug.
|
98
|
-
def exists?(id = false)
|
99
|
-
return super if id.unfriendly_id?
|
100
|
-
exists_without_friendly_id?(@klass.friendly_id_config.query_field => id) or
|
101
|
-
with_old_friendly_id(id) {|x| exists_without_friendly_id?(:id => x)} or
|
102
|
-
exists_without_friendly_id?(id)
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
# Accepts a slug, and yields a corresponding sluggable_id into the block.
|
108
|
-
def with_old_friendly_id(slug, &block)
|
109
|
-
sql = "SELECT sluggable_id FROM #{Slug.quoted_table_name} WHERE sluggable_type = %s AND slug = %s"
|
110
|
-
sql = sql % [@klass.base_class.to_s, slug].map {|x| connection.quote(x)}
|
111
|
-
sluggable_ids = connection.select_values(sql)
|
112
|
-
yield sluggable_ids if sluggable_ids
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# This module overrides {FriendlyId::SlugGenerator#conflicts} to consider
|
117
|
-
# all historic slugs for that model.
|
118
|
-
module SlugGenerator
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
def conflicts
|
123
|
-
sluggable_class = friendly_id_config.model_class.base_class
|
124
|
-
pkey = sluggable_class.primary_key
|
125
|
-
value = sluggable.send pkey
|
126
|
-
|
127
|
-
scope = Slug.where("slug = ? OR slug LIKE ?", normalized, wildcard)
|
128
|
-
scope = scope.where(:sluggable_type => sluggable_class.to_s)
|
129
|
-
scope = scope.where("sluggable_id <> ?", value) unless sluggable.new_record?
|
130
|
-
if sluggable.friendly_id_config.uses?(:scoped)
|
131
|
-
scope = scope.where("scope = ?", sluggable.serialized_scope)
|
132
|
-
end
|
133
|
-
length_command = "LENGTH"
|
134
|
-
length_command = "LEN" if sluggable.connection.adapter_name =~ /sqlserver/i
|
135
|
-
scope.order("#{length_command}(slug) DESC, slug DESC")
|
136
|
-
end
|
137
|
-
end
|
138
100
|
end
|
139
101
|
end
|