lib/friendly_id/object_utils.rb
module FriendlyId
# Instances of these classes will never be considered a friendly id.
# @see FriendlyId::ObjectUtils#friendly_id
UNFRIENDLY_CLASSES = [
Array,
FalseClass,
Hash,
NilClass,
Numeric,
Symbol,
TrueClass
]
# Utility methods for determining whether any object is a friendly id.
#
# Monkey-patching Object is a somewhat extreme measure not to be taken lightly
# by libraries, but in this case I decided to do it because to me, it feels
# cleaner than adding a module method to {FriendlyId}. I've given the methods
# names that unambigously refer to the library of their origin, which should
# be sufficient to avoid conflicts with other libraries.
module ObjectUtils
# True if the id is definitely friendly, false if definitely unfriendly,
# else nil.
#
# An object is considired "definitely unfriendly" if its class is or
# inherits from ActiveRecord::Base, Array, Hash, NilClass, Numeric, or
# Symbol.
#
# An object is considered "definitely friendly" if it responds to +to_i+,
# and its value when cast to an integer and then back to a string is
# different from its value when merely cast to a string:
#
# 123.friendly_id? #=> false
# :id.friendly_id? #=> false
# {:name => 'joe'}.friendly_id? #=> false
# ['name = ?', 'joe'].friendly_id? #=> false
# nil.friendly_id? #=> false
# "123".friendly_id? #=> nil
# "abc123".friendly_id? #=> true
def friendly_id?
true if respond_to?(:to_i) && to_i.to_s != to_s
end
# True if the id is definitely unfriendly, false if definitely friendly,
# else nil.
def unfriendly_id?
val = friendly_id?
!val unless val.nil?
end
end
module UnfriendlyUtils
def friendly_id?
false
end
def unfriendly_id?
true
end
end
def self.mark_as_unfriendly(klass)
klass.send(:include, FriendlyId::UnfriendlyUtils)
end
end
Object.send :include, FriendlyId::ObjectUtils
# Considered unfriendly if object is an instance of an unfriendly class or
# one of its descendants.
FriendlyId::UNFRIENDLY_CLASSES.each { |klass| FriendlyId.mark_as_unfriendly(klass) }
ActiveSupport.on_load(:active_record) do
FriendlyId.mark_as_unfriendly(ActiveRecord::Base)
end