friendly_id 3.3.3.0 → 4.0.0.beta7
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.
- data/.gitignore +11 -0
- data/.travis.yml +24 -0
- data/.yardopts +4 -0
- data/Changelog.md +9 -10
- data/README.md +39 -48
- data/Rakefile +56 -58
- data/WhatsNew.md +95 -0
- data/bench.rb +63 -0
- data/friendly_id.gemspec +40 -0
- data/gemfiles/Gemfile.rails-3.0.rb +18 -0
- data/gemfiles/Gemfile.rails-3.0.rb.lock +52 -0
- data/gemfiles/Gemfile.rails-3.1.rb +18 -0
- data/gemfiles/Gemfile.rails-3.1.rb.lock +57 -0
- data/lib/friendly_id.rb +126 -80
- data/lib/friendly_id/active_record_adapter/relation.rb +10 -2
- data/lib/friendly_id/active_record_adapter/slugged_model.rb +3 -9
- data/lib/friendly_id/base.rb +132 -0
- data/lib/friendly_id/configuration.rb +65 -152
- data/lib/friendly_id/finder_methods.rb +20 -0
- data/lib/friendly_id/history.rb +88 -0
- data/lib/friendly_id/migration.rb +18 -0
- data/lib/friendly_id/model.rb +22 -0
- data/lib/friendly_id/object_utils.rb +40 -0
- data/lib/friendly_id/reserved.rb +46 -0
- data/lib/friendly_id/scoped.rb +131 -0
- data/lib/friendly_id/slug.rb +9 -0
- data/lib/friendly_id/slug_sequencer.rb +82 -0
- data/lib/friendly_id/slugged.rb +191 -76
- data/lib/friendly_id/version.rb +2 -2
- data/test/base_test.rb +54 -0
- data/test/configuration_test.rb +27 -0
- data/test/core_test.rb +30 -0
- data/test/databases.yml +19 -0
- data/test/helper.rb +88 -0
- data/test/history_test.rb +55 -0
- data/test/object_utils_test.rb +26 -0
- data/test/reserved_test.rb +26 -0
- data/test/schema.rb +59 -0
- data/test/scoped_test.rb +57 -0
- data/test/shared.rb +118 -0
- data/test/slugged_test.rb +83 -0
- data/test/sti_test.rb +48 -0
- metadata +110 -102
- data/Contributors.md +0 -46
- data/Guide.md +0 -626
- data/extras/README.txt +0 -3
- data/extras/bench.rb +0 -40
- data/extras/extras.rb +0 -38
- data/extras/prof.rb +0 -19
- data/extras/template-gem.rb +0 -26
- data/extras/template-plugin.rb +0 -28
- data/generators/friendly_id/friendly_id_generator.rb +0 -30
- data/generators/friendly_id/templates/create_slugs.rb +0 -18
- data/lib/tasks/friendly_id.rake +0 -19
- data/rails/init.rb +0 -2
- data/test/active_record_adapter/ar_test_helper.rb +0 -149
- data/test/active_record_adapter/basic_slugged_model_test.rb +0 -14
- data/test/active_record_adapter/cached_slug_test.rb +0 -76
- data/test/active_record_adapter/core.rb +0 -138
- data/test/active_record_adapter/custom_normalizer_test.rb +0 -20
- data/test/active_record_adapter/custom_table_name_test.rb +0 -22
- data/test/active_record_adapter/default_scope_test.rb +0 -30
- data/test/active_record_adapter/optimistic_locking_test.rb +0 -18
- data/test/active_record_adapter/scoped_model_test.rb +0 -129
- data/test/active_record_adapter/simple_test.rb +0 -76
- data/test/active_record_adapter/slug_test.rb +0 -34
- data/test/active_record_adapter/slugged.rb +0 -33
- data/test/active_record_adapter/slugged_status_test.rb +0 -28
- data/test/active_record_adapter/sti_test.rb +0 -22
- data/test/active_record_adapter/support/database.jdbcsqlite3.yml +0 -2
- data/test/active_record_adapter/support/database.mysql.yml +0 -4
- data/test/active_record_adapter/support/database.mysql2.yml +0 -4
- data/test/active_record_adapter/support/database.postgres.yml +0 -6
- data/test/active_record_adapter/support/database.sqlite3.yml +0 -2
- data/test/active_record_adapter/support/models.rb +0 -104
- data/test/active_record_adapter/tasks_test.rb +0 -82
- data/test/compatibility/ancestry/Gemfile.lock +0 -34
- data/test/friendly_id_test.rb +0 -96
- data/test/test_helper.rb +0 -13
@@ -124,8 +124,8 @@ module FriendlyId
|
|
124
124
|
if result.size == expected_size
|
125
125
|
result
|
126
126
|
else
|
127
|
-
conditions = arel.
|
128
|
-
conditions = " [#{conditions}]" if conditions
|
127
|
+
conditions = arel.send(:where_clauses).join(', ')
|
128
|
+
conditions = " [WHERE #{conditions}]" if conditions.present?
|
129
129
|
error = "Couldn't find all #{klass.name.pluralize} with IDs "
|
130
130
|
error << "(#{ids.join(", ")})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
|
131
131
|
raise ActiveRecord::RecordNotFound, error
|
@@ -141,6 +141,14 @@ module FriendlyId
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
+
def apply_finder_options(options)
|
145
|
+
if options[:scope]
|
146
|
+
raise "The :scope finder option has been removed from FriendlyId 3.2.0 " +
|
147
|
+
"https://github.com/norman/friendly_id/issues#issue/88"
|
148
|
+
end
|
149
|
+
super
|
150
|
+
end
|
151
|
+
|
144
152
|
protected
|
145
153
|
|
146
154
|
def find_one(id)
|
@@ -4,19 +4,13 @@ module FriendlyId
|
|
4
4
|
|
5
5
|
def self.included(base)
|
6
6
|
base.class_eval do
|
7
|
-
has_one :slug, :order => 'id DESC', :as => :sluggable, :dependent => :nullify
|
8
7
|
has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
|
8
|
+
has_one :slug, :order => 'id DESC', :as => :sluggable, :dependent => :nullify
|
9
9
|
before_save :build_a_slug
|
10
10
|
after_save :set_slug_cache
|
11
11
|
after_update :update_scope
|
12
12
|
after_update :update_dependent_scopes
|
13
13
|
protect_friendly_id_attributes
|
14
|
-
|
15
|
-
def slug_with_rails_3_2_patch
|
16
|
-
slug_without_rails_3_2_patch || slugs.first
|
17
|
-
end
|
18
|
-
|
19
|
-
alias_method_chain :slug, :rails_3_2_patch
|
20
14
|
end
|
21
15
|
end
|
22
16
|
|
@@ -80,7 +74,7 @@ module FriendlyId
|
|
80
74
|
slug.scope = send(friendly_id_config.scope).to_param
|
81
75
|
similar = Slug.similar_to(slug)
|
82
76
|
if !similar.empty?
|
83
|
-
slug.sequence = similar.
|
77
|
+
slug.sequence = similar.first.sequence.succ
|
84
78
|
end
|
85
79
|
slug.save!
|
86
80
|
end
|
@@ -104,7 +98,7 @@ module FriendlyId
|
|
104
98
|
end
|
105
99
|
|
106
100
|
# This method was removed in ActiveRecord 3.0.
|
107
|
-
if
|
101
|
+
if !ActiveRecord::Base.private_method_defined? :update_without_callbacks
|
108
102
|
def update_without_callbacks
|
109
103
|
attributes_with_values = arel_attributes_values(false, false, attribute_names)
|
110
104
|
return false if attributes_with_values.empty?
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
# Class methods that will be added to model classes that extend {FriendlyId}.
|
3
|
+
module Base
|
4
|
+
|
5
|
+
# Configure FriendlyId's behavior in a model.
|
6
|
+
#
|
7
|
+
# class Post < ActiveRecord::Base
|
8
|
+
# extend FriendlyId
|
9
|
+
# friendly_id :title, :use => :slugged
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# When given the optional block, this method will yield the class's instance
|
13
|
+
# of {FriendlyId::Configuration} to the block before evaluating other
|
14
|
+
# arguments, so configuration values set in the block may be overwritten by
|
15
|
+
# the arguments. This order was chosen to allow passing the same proc to
|
16
|
+
# multiple models, while being able to override the values it sets. Here is
|
17
|
+
# a contrived example:
|
18
|
+
#
|
19
|
+
# $friendly_id_config_proc = Proc.new do |config|
|
20
|
+
# config.base = :name
|
21
|
+
# config.use :slugged
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# class Foo < ActiveRecord::Base
|
25
|
+
# extend FriendlyId
|
26
|
+
# friendly_id &$friendly_id_config_proc
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# class Bar < ActiveRecord::Base
|
30
|
+
# extend FriendlyId
|
31
|
+
# friendly_id :title, &$friendly_id_config_proc
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# However, it's usually better to use {FriendlyId.defaults} for this:
|
35
|
+
#
|
36
|
+
# FriendlyId.defaults do |config|
|
37
|
+
# config.base = :name
|
38
|
+
# config.use :slugged
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# class Foo < ActiveRecord::Base
|
42
|
+
# extend FriendlyId
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# class Bar < ActiveRecord::Base
|
46
|
+
# extend FriendlyId
|
47
|
+
# friendly_id :title
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# In general you should use the block syntax either because of your personal
|
51
|
+
# aesthetic preference, or because you need to share some functionality
|
52
|
+
# between multiple models that can't be well encapsulated by
|
53
|
+
# {FriendlyId.defaults}.
|
54
|
+
#
|
55
|
+
# === Order Method Calls in a Block vs Ordering Options
|
56
|
+
#
|
57
|
+
# When calling this method without a block, you may set the hash options in
|
58
|
+
# any order.
|
59
|
+
#
|
60
|
+
# However, when using block-style invocation, be sure to call
|
61
|
+
# FriendlyId::Configuration's {FriendlyId::Configuration#use use} method
|
62
|
+
# *prior* to the associated configuration options, because it will include
|
63
|
+
# modules into your class, and these modules in turn may add required
|
64
|
+
# configuration options to the +@friendly_id_configuraton+'s class:
|
65
|
+
#
|
66
|
+
# class Person < ActiveRecord::Base
|
67
|
+
# friendly_id do |config|
|
68
|
+
# # This will work
|
69
|
+
# config.use :slugged
|
70
|
+
# config.sequence_separator = ":"
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# class Person < ActiveRecord::Base
|
75
|
+
# friendly_id do |config|
|
76
|
+
# # This will fail
|
77
|
+
# config.sequence_separator = ":"
|
78
|
+
# config.use :slugged
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# @option options [Symbol] :use The name of an addon to use. By default,
|
83
|
+
# FriendlyId provides {FriendlyId::Slugged :slugged},
|
84
|
+
# {FriendlyId::History :history}, {FriendlyId::Reserved :reserved}, and
|
85
|
+
# {FriendlyId::Scoped :scoped}.
|
86
|
+
#
|
87
|
+
# @option options [Array] :reserved_words Available when using +:reserved+,
|
88
|
+
# which is loaded by default. Sets an array of words banned for use as
|
89
|
+
# the basis of a friendly_id. By default this includes "edit" and "new".
|
90
|
+
#
|
91
|
+
# @option options [Symbol] :scope Available when using +:scoped+.
|
92
|
+
# Sets the relation or column used to scope generated friendly ids. This
|
93
|
+
# option has no default value.
|
94
|
+
#
|
95
|
+
# @option options [Symbol] :sequence_separator Available when using +:slugged+.
|
96
|
+
# Configures the sequence of characters used to separate a slug from a
|
97
|
+
# sequence. Defaults to +--+.
|
98
|
+
#
|
99
|
+
# @option options [Symbol] :slug_column Available when using +:slugged+.
|
100
|
+
# Configures the name of the column where FriendlyId will store the slug.
|
101
|
+
# Defaults to +:slug+.
|
102
|
+
#
|
103
|
+
# @option options [Symbol] :slug_sequencer_class Available when using +:slugged+.
|
104
|
+
# Sets the class used to generate unique slugs. You should not specify this
|
105
|
+
# unless you're doing some extensive hacking on FriendlyId. Defaults to
|
106
|
+
# {FriendlyId::SlugSequencer}.
|
107
|
+
#
|
108
|
+
# @yield Provides access to the model class's friendly_id_config, which
|
109
|
+
# allows an alternate configuration syntax, and conditional configuration
|
110
|
+
# logic.
|
111
|
+
#
|
112
|
+
# @yieldparam config The model class's {FriendlyId::Configuration friendly_id_config}.
|
113
|
+
def friendly_id(base = nil, options = {}, &block)
|
114
|
+
yield @friendly_id_config if block_given?
|
115
|
+
@friendly_id_config.use options.delete :use
|
116
|
+
@friendly_id_config.send :set, base ? options.merge(:base => base) : options
|
117
|
+
before_save {|rec| rec.instance_eval {@current_friendly_id = friendly_id}}
|
118
|
+
include Model
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns the model class's {FriendlyId::Configuration friendly_id_config}.
|
122
|
+
# @note In the case of Single Table Inheritance (STI), this method will
|
123
|
+
# duplicate the parent class's FriendlyId::Configuration instance on first
|
124
|
+
# access. If you're concerned about thread safety, then be sure to invoke
|
125
|
+
# {#friendly_id} in your class for each model.
|
126
|
+
def friendly_id_config
|
127
|
+
@friendly_id_config or begin
|
128
|
+
@friendly_id_config = base_class.friendly_id_config.dup
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -1,166 +1,79 @@
|
|
1
1
|
module FriendlyId
|
2
|
-
|
3
|
-
#
|
4
|
-
# by `has_friendly_id` to store a model's configuration and
|
5
|
-
# configuration-related methods.
|
6
|
-
#
|
7
|
-
# The arguments accepted by +has_friendly_id+ correspond to the writeable
|
8
|
-
# instance attributes of this class; please see the description of the
|
9
|
-
# attributes below for information on the possible options.
|
10
|
-
#
|
11
|
-
# @example
|
12
|
-
# has_friendly_id :name,
|
13
|
-
# :use_slug => true,
|
14
|
-
# :max_length => 150,
|
15
|
-
# :approximate_ascii => true,
|
16
|
-
# :ascii_approximation_options => :german,
|
17
|
-
# :sequence_separator => ":",
|
18
|
-
# :reserved_words => ["reserved", "words"],
|
19
|
-
# :scope => :country,
|
20
|
-
# :cache_column => :my_cache_column_name
|
21
|
-
# # etc.
|
2
|
+
# The configuration paramters passed to +friendly_id+ will be stored in
|
3
|
+
# this object.
|
22
4
|
class Configuration
|
23
5
|
|
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
|
-
# The
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
#
|
53
|
-
attr_reader :
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# Array of words that are reserved and can't be used as friendly_id strings.
|
61
|
-
# If a listed word is used in a sluggable model, it will raise a
|
62
|
-
# FriendlyId::SlugGenerationError. For Rails applications, you are recommended
|
63
|
-
# to include "index" and "new", which used as the defaults unless overridden.
|
64
|
-
attr_accessor :reserved_words
|
65
|
-
|
66
|
-
# The method or relation to use as the friendly_id's scope.
|
67
|
-
attr_reader :scope
|
68
|
-
|
69
|
-
# The string that separates slug names from slug sequences. Defaults to "--".
|
70
|
-
attr_accessor :sequence_separator
|
71
|
-
|
72
|
-
# Strip non-ASCII characters from the friendly_id string.
|
73
|
-
attr_accessor :strip_non_ascii
|
74
|
-
|
75
|
-
# Use slugs for storing the friendly_id string.
|
76
|
-
attr_accessor :use_slug
|
77
|
-
alias :use_slugs= :use_slug
|
78
|
-
|
79
|
-
def initialize(configured_class, method, options = nil, &block)
|
80
|
-
@configured_class = configured_class
|
81
|
-
@method = method.to_sym
|
82
|
-
DEFAULTS.merge(options || {}).each do |key, value|
|
83
|
-
self.send "#{key}=".to_sym, value
|
84
|
-
end
|
85
|
-
yield self if block_given?
|
86
|
-
end
|
87
|
-
|
88
|
-
def cache_column=(value)
|
89
|
-
@cache_column = value.to_s.strip.to_sym
|
90
|
-
if value =~ /\s/ || [:slug, :slugs].include?(@cache_column)
|
91
|
-
raise ArgumentError, "FriendlyId cache column can not be named '#{value}'"
|
92
|
-
end
|
93
|
-
@cache_column
|
94
|
-
end
|
95
|
-
|
96
|
-
# This should be overridden by adapters that implement caching.
|
97
|
-
def cache_column?
|
98
|
-
false
|
6
|
+
# The base column or method used by FriendlyId as the basis of a friendly id
|
7
|
+
# or slug.
|
8
|
+
#
|
9
|
+
# For models that don't use FriendlyId::Slugged, the base is the column that
|
10
|
+
# is used as the FriendlyId directly. For models using FriendlyId::Slugged,
|
11
|
+
# the base is a column or method whose value is used as the basis of the
|
12
|
+
# slug.
|
13
|
+
#
|
14
|
+
# For example, if you have a model representing blog posts and that uses
|
15
|
+
# slugs, you likely will want to use the "title" attribute as the base, and
|
16
|
+
# FriendlyId will take care of transforming the human-readable title into
|
17
|
+
# something suitable for use in a URL.
|
18
|
+
#
|
19
|
+
# @param [Symbol] A symbol referencing a column or method in the model. This
|
20
|
+
# value is usually set by passing it as the first argument to
|
21
|
+
# {FriendlyId::Base#friendly_id friendly_id}:
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# class Book < ActiveRecord::Base
|
25
|
+
# extend FriendlyId
|
26
|
+
# friendly_id :name
|
27
|
+
# end
|
28
|
+
attr_accessor :base
|
29
|
+
|
30
|
+
# The default configuration options.
|
31
|
+
attr_reader :defaults
|
32
|
+
|
33
|
+
# The model class that this configuration belongs to.
|
34
|
+
# @return ActiveRecord::Base
|
35
|
+
attr_reader :model_class
|
36
|
+
|
37
|
+
def initialize(model_class, values = nil)
|
38
|
+
@model_class = model_class
|
39
|
+
@defaults = {}
|
40
|
+
set values
|
99
41
|
end
|
100
42
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
43
|
+
# Lets you specify the modules to use with FriendlyId.
|
44
|
+
#
|
45
|
+
# This method is invoked by {FriendlyId::Base#friendly_id friendly_id} when
|
46
|
+
# passing the +:use+ option, or when using {FriendlyId::Base#friendly_id
|
47
|
+
# friendly_id} with a block.
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# class Book < ActiveRecord::Base
|
51
|
+
# extend FriendlyId
|
52
|
+
# friendly_id :name, :use => :slugged
|
53
|
+
# end
|
54
|
+
# @param [#to_s] *modules Arguments should be a symbols or strings that
|
55
|
+
# correspond with the name of a module inside the FriendlyId namespace. By
|
56
|
+
# default FriendlyId provides +:slugged+, +:history+ and +:scoped+.
|
57
|
+
def use(*modules)
|
58
|
+
modules.to_a.flatten.compact.map do |name|
|
59
|
+
mod = FriendlyId.const_get(name.to_s.classify)
|
60
|
+
model_class.send(:include, mod) unless model_class < mod
|
106
61
|
end
|
107
62
|
end
|
108
63
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
def reserved_error_message(word)
|
119
|
-
[method, reserved_message % word] if reserved? word
|
120
|
-
end
|
121
|
-
|
122
|
-
def scope=(scope)
|
123
|
-
self.class.scopes_used = true
|
124
|
-
@scope = scope
|
125
|
-
end
|
126
|
-
|
127
|
-
def sequence_separator=(string)
|
128
|
-
if string == "-" || string =~ /\s/
|
129
|
-
raise ArgumentError, "FriendlyId sequence_separator can not be '#{string}'"
|
130
|
-
end
|
131
|
-
@sequence_separator = string
|
132
|
-
end
|
133
|
-
|
134
|
-
# This will be set if FriendlyId's scope feature is used in any model. It is here
|
135
|
-
# to provide a way to avoid invoking costly scope lookup methods when the scoped
|
136
|
-
# slug feature is not being used by any models.
|
137
|
-
def self.scopes_used=(val)
|
138
|
-
@scopes_used = !!val
|
139
|
-
end
|
140
|
-
|
141
|
-
# Are scoped slugs being used by any model?
|
142
|
-
# @see Configuration.scoped_used=
|
143
|
-
def self.scopes_used?
|
144
|
-
@scopes_used
|
145
|
-
end
|
146
|
-
|
147
|
-
%w[approximate_ascii scope strip_non_ascii use_slug].each do |method|
|
148
|
-
class_eval(<<-EOM, __FILE__, __LINE__ + 1)
|
149
|
-
def #{method}?
|
150
|
-
!! #{method}
|
151
|
-
end
|
152
|
-
EOM
|
64
|
+
# The column that FriendlyId will use to find the record when querying by
|
65
|
+
# friendly id.
|
66
|
+
#
|
67
|
+
# This method is generally only used internally by FriendlyId.
|
68
|
+
# @return String
|
69
|
+
def query_field
|
70
|
+
base.to_s
|
153
71
|
end
|
154
72
|
|
155
|
-
|
73
|
+
private
|
156
74
|
|
157
|
-
def
|
158
|
-
{
|
159
|
-
:to_ascii => strip_non_ascii?,
|
160
|
-
:transliterate => approximate_ascii?,
|
161
|
-
:transliterations => ascii_approximation_options,
|
162
|
-
:max_length => max_length
|
163
|
-
}
|
75
|
+
def set(values)
|
76
|
+
values and values.each {|name, value| self.send "#{name}=", value}
|
164
77
|
end
|
165
78
|
end
|
166
79
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
# These methods will override the finder methods in ActiveRecord::Relation.
|
3
|
+
module FinderMethods
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
# FriendlyId overrides this method to make it possible to use friendly id's
|
8
|
+
# identically to numeric ids in finders.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# person = Person.find(123)
|
12
|
+
# person = Person.find("joe")
|
13
|
+
#
|
14
|
+
# @see FriendlyId::ObjectUtils
|
15
|
+
def find_one(id)
|
16
|
+
return super if !@klass.respond_to?(:friendly_id) || id.unfriendly_id?
|
17
|
+
where(@klass.friendly_id_config.query_field => id).first or super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|