friendly_id_globalize3 3.2.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.
- data/Changelog.md +354 -0
- data/Contributors.md +43 -0
- data/Guide.md +686 -0
- data/MIT-LICENSE +19 -0
- data/README.md +99 -0
- data/Rakefile +75 -0
- data/extras/README.txt +3 -0
- data/extras/bench.rb +40 -0
- data/extras/extras.rb +38 -0
- data/extras/prof.rb +19 -0
- data/extras/template-gem.rb +26 -0
- data/extras/template-plugin.rb +28 -0
- data/generators/friendly_id/friendly_id_generator.rb +30 -0
- data/generators/friendly_id/templates/create_slugs.rb +18 -0
- data/lib/friendly_id.rb +93 -0
- data/lib/friendly_id/active_record.rb +74 -0
- data/lib/friendly_id/active_record_adapter/configuration.rb +68 -0
- data/lib/friendly_id/active_record_adapter/finders.rb +148 -0
- data/lib/friendly_id/active_record_adapter/relation.rb +165 -0
- data/lib/friendly_id/active_record_adapter/simple_model.rb +63 -0
- data/lib/friendly_id/active_record_adapter/slug.rb +77 -0
- data/lib/friendly_id/active_record_adapter/slugged_model.rb +122 -0
- data/lib/friendly_id/active_record_adapter/tasks.rb +72 -0
- data/lib/friendly_id/configuration.rb +178 -0
- data/lib/friendly_id/datamapper.rb +5 -0
- data/lib/friendly_id/railtie.rb +22 -0
- data/lib/friendly_id/sequel.rb +5 -0
- data/lib/friendly_id/slug_string.rb +25 -0
- data/lib/friendly_id/slugged.rb +105 -0
- data/lib/friendly_id/status.rb +35 -0
- data/lib/friendly_id/test.rb +350 -0
- data/lib/friendly_id/version.rb +9 -0
- data/lib/generators/friendly_id_generator.rb +25 -0
- data/lib/tasks/friendly_id.rake +19 -0
- data/rails/init.rb +2 -0
- data/test/active_record_adapter/ar_test_helper.rb +150 -0
- data/test/active_record_adapter/basic_slugged_model_test.rb +14 -0
- data/test/active_record_adapter/cached_slug_test.rb +76 -0
- data/test/active_record_adapter/core.rb +138 -0
- data/test/active_record_adapter/custom_normalizer_test.rb +20 -0
- data/test/active_record_adapter/custom_table_name_test.rb +22 -0
- data/test/active_record_adapter/default_scope_test.rb +30 -0
- data/test/active_record_adapter/optimistic_locking_test.rb +18 -0
- data/test/active_record_adapter/scoped_model_test.rb +119 -0
- data/test/active_record_adapter/simple_test.rb +76 -0
- data/test/active_record_adapter/slug_test.rb +34 -0
- data/test/active_record_adapter/slugged.rb +33 -0
- data/test/active_record_adapter/slugged_status_test.rb +28 -0
- data/test/active_record_adapter/sti_test.rb +22 -0
- data/test/active_record_adapter/support/database.jdbcsqlite3.yml +2 -0
- data/test/active_record_adapter/support/database.mysql.yml +4 -0
- data/test/active_record_adapter/support/database.postgres.yml +6 -0
- data/test/active_record_adapter/support/database.sqlite3.yml +2 -0
- data/test/active_record_adapter/support/models.rb +104 -0
- data/test/active_record_adapter/tasks_test.rb +82 -0
- data/test/friendly_id_test.rb +96 -0
- data/test/test_helper.rb +13 -0
- metadata +193 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
module ActiveRecordAdapter
|
3
|
+
|
4
|
+
module SimpleModel
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
column = friendly_id_config.column
|
9
|
+
validate :validate_friendly_id, :unless => :skip_friendly_id_validations
|
10
|
+
validates_presence_of column, :unless => :skip_friendly_id_validations
|
11
|
+
validates_length_of column, :maximum => friendly_id_config.max_length, :unless => :skip_friendly_id_validations
|
12
|
+
after_update :update_scopes
|
13
|
+
extend FriendlyId::ActiveRecordAdapter::Finders unless FriendlyId.on_ar3?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get the {FriendlyId::Status} after the find has been performed.
|
18
|
+
def friendly_id_status
|
19
|
+
@friendly_id_status ||= Status.new :record => self
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the friendly_id.
|
23
|
+
def friendly_id
|
24
|
+
send friendly_id_config.column
|
25
|
+
end
|
26
|
+
alias best_id friendly_id
|
27
|
+
|
28
|
+
# Returns the friendly id, or if none is available, the numeric id.
|
29
|
+
def to_param
|
30
|
+
(friendly_id || id).to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# The old and new values for the friendly_id column.
|
36
|
+
def friendly_id_changes
|
37
|
+
changes[friendly_id_config.column.to_s]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Update the slugs for any model that is using this model as its
|
41
|
+
# FriendlyId scope.
|
42
|
+
def update_scopes
|
43
|
+
if changes = friendly_id_changes
|
44
|
+
friendly_id_config.child_scopes.each do |klass|
|
45
|
+
Slug.update_all "scope = '#{changes[1]}'", ["sluggable_type = ? AND scope = ?", klass.to_s, changes[0]]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def skip_friendly_id_validations
|
51
|
+
friendly_id.nil? && friendly_id_config.allow_nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_friendly_id
|
55
|
+
if result = friendly_id_config.reserved_error_message(friendly_id)
|
56
|
+
self.errors.add(*result)
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# A Slug is a unique, human-friendly identifier for an ActiveRecord.
|
2
|
+
class Slug < ::ActiveRecord::Base
|
3
|
+
attr_writer :sluggable
|
4
|
+
attr_accessible :name, :scope, :sluggable, :sequence, :locale
|
5
|
+
def self.named_scope(*args, &block) scope(*args, &block) end if FriendlyId.on_ar3?
|
6
|
+
table_name = "slugs"
|
7
|
+
before_save :enable_name_reversion, :set_sequence
|
8
|
+
validate :validate_name
|
9
|
+
named_scope :similar_to, lambda {|slug| {:conditions => {
|
10
|
+
:name => slug.name,
|
11
|
+
:scope => slug.scope,
|
12
|
+
:sluggable_type => slug.sluggable_type
|
13
|
+
},
|
14
|
+
:order => "sequence ASC"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
def sluggable
|
19
|
+
sluggable_id && !@sluggable and begin
|
20
|
+
klass = sluggable_type.constantize
|
21
|
+
klass.send(:with_exclusive_scope) do
|
22
|
+
@sluggable = klass.find(sluggable_id.to_i)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
@sluggable
|
26
|
+
end
|
27
|
+
|
28
|
+
# Whether this slug is the most recent of its owner's slugs.
|
29
|
+
def current?
|
30
|
+
sluggable.slug == self
|
31
|
+
end
|
32
|
+
|
33
|
+
def outdated?
|
34
|
+
!current?
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_friendly_id
|
38
|
+
sequence > 1 ? friendly_id_with_sequence : name
|
39
|
+
end
|
40
|
+
|
41
|
+
# Raise a FriendlyId::SlugGenerationError if the slug name is blank.
|
42
|
+
def validate_name
|
43
|
+
if name.blank?
|
44
|
+
raise FriendlyId::BlankError.new("slug.name can not be blank.")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# If we're renaming back to a previously used friendly_id, delete the
|
51
|
+
# slug so that we can recycle the name without having to use a sequence.
|
52
|
+
def enable_name_reversion
|
53
|
+
sluggable.slugs.find_all_by_name_and_scope(name, scope).each { |slug| slug.destroy }
|
54
|
+
end
|
55
|
+
|
56
|
+
def friendly_id_with_sequence
|
57
|
+
"#{name}#{separator}#{sequence}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def similar_to_other_slugs?
|
61
|
+
!similar_slugs.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def similar_slugs
|
65
|
+
self.class.similar_to(self)
|
66
|
+
end
|
67
|
+
|
68
|
+
def separator
|
69
|
+
sluggable.friendly_id_config.sequence_separator
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_sequence
|
73
|
+
return unless new_record?
|
74
|
+
self.sequence = similar_slugs.last.sequence.succ if similar_to_other_slugs?
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
module ActiveRecordAdapter
|
3
|
+
module SluggedModel
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
|
8
|
+
has_one :slug, :order => 'id DESC', :as => :sluggable, :dependent => :destroy,
|
9
|
+
:conditions => ({:locale => (Thread.current[:globalize_locale] || ::I18n.locale)} if friendly_id_config.class.locales_used?)
|
10
|
+
before_save :build_a_slug
|
11
|
+
after_save :set_slug_cache
|
12
|
+
after_update :update_scope
|
13
|
+
after_update :update_dependent_scopes
|
14
|
+
protect_friendly_id_attributes
|
15
|
+
extend FriendlyId::ActiveRecordAdapter::Finders unless FriendlyId.on_ar3?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
include FriendlyId::Slugged::Model
|
20
|
+
|
21
|
+
def find_slug(name, sequence)
|
22
|
+
slugs.find_by_name_and_sequence(name, sequence)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the friendly id, or if none is available, the numeric id. Note that this
|
26
|
+
# method will use the cached_slug value if present, unlike {#friendly_id}.
|
27
|
+
def to_param
|
28
|
+
friendly_id_config.cache_column ? to_param_from_cache : to_param_from_slug
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def scope_changed?
|
34
|
+
friendly_id_config.scope? && send(friendly_id_config.scope).to_param != slug.scope
|
35
|
+
end
|
36
|
+
|
37
|
+
# Respond with the cached value if available.
|
38
|
+
def to_param_from_cache
|
39
|
+
read_attribute(friendly_id_config.cache_column) || id.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
# Respond with the slugged value if available.
|
43
|
+
def to_param_from_slug
|
44
|
+
unless friendly_id_config.class.locales_used?
|
45
|
+
slug? ? slug.to_friendly_id : id.to_s
|
46
|
+
else
|
47
|
+
locale = (Thread.current[:globalize_locale] || ::I18n.locale).to_s
|
48
|
+
if (locale_slug = slugs.detect{|s| s.locale.to_s == locale}).present?
|
49
|
+
locale_slug.to_friendly_id
|
50
|
+
else
|
51
|
+
id.to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Build the new slug using the generated friendly id.
|
57
|
+
def build_a_slug
|
58
|
+
return unless new_slug_needed?
|
59
|
+
@slug = slugs.build :name => slug_text.to_s, :scope => friendly_id_config.scope_for(self),
|
60
|
+
:sluggable => self
|
61
|
+
@slug.locale = Thread.current[:globalize_locale] || ::I18n.locale if friendly_id_config.class.locales_used?
|
62
|
+
@new_friendly_id = @slug.to_friendly_id
|
63
|
+
end
|
64
|
+
|
65
|
+
# Reset the cached friendly_id?
|
66
|
+
def new_cache_needed?
|
67
|
+
uses_slug_cache? && slug? && send(friendly_id_config.cache_column) != slug.to_friendly_id
|
68
|
+
end
|
69
|
+
|
70
|
+
# Reset the cached friendly_id.
|
71
|
+
def set_slug_cache
|
72
|
+
if new_cache_needed?
|
73
|
+
begin
|
74
|
+
send "#{friendly_id_config.cache_column}=", slug.to_friendly_id
|
75
|
+
update_without_callbacks
|
76
|
+
rescue ActiveRecord::StaleObjectError
|
77
|
+
reload
|
78
|
+
retry
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def update_scope
|
84
|
+
return unless slug && scope_changed?
|
85
|
+
self.class.transaction do
|
86
|
+
slug.scope = send(friendly_id_config.scope).to_param
|
87
|
+
similar = Slug.similar_to(slug)
|
88
|
+
if !similar.empty?
|
89
|
+
slug.sequence = similar.first.sequence.succ
|
90
|
+
end
|
91
|
+
slug.save!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Update the slugs for any model that is using this model as its
|
96
|
+
# FriendlyId scope.
|
97
|
+
def update_dependent_scopes
|
98
|
+
return unless friendly_id_config.class.scopes_used?
|
99
|
+
if slugs(true).size > 1 && @new_friendly_id
|
100
|
+
friendly_id_config.child_scopes.each do |klass|
|
101
|
+
Slug.update_all "scope = '#{@new_friendly_id}'", ["sluggable_type = ? AND scope = ?",
|
102
|
+
klass.to_s, slugs.second.to_friendly_id]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Does the model use slug caching?
|
108
|
+
def uses_slug_cache?
|
109
|
+
friendly_id_config.cache_column?
|
110
|
+
end
|
111
|
+
|
112
|
+
# This method was removed in ActiveRecord 3.0.
|
113
|
+
if !ActiveRecord::Base.private_method_defined? :update_without_callbacks
|
114
|
+
def update_without_callbacks
|
115
|
+
attributes_with_values = arel_attributes_values(false, false, attribute_names)
|
116
|
+
return false if attributes_with_values.empty?
|
117
|
+
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.update(attributes_with_values)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
class TaskRunner
|
3
|
+
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
attr_accessor :days
|
7
|
+
attr_accessor :klass
|
8
|
+
attr_accessor :task_options
|
9
|
+
|
10
|
+
def_delegators :klass, :find, :friendly_id_config, :update_all
|
11
|
+
|
12
|
+
OLD_SLUG_DAYS = 45
|
13
|
+
|
14
|
+
def initialize(&block)
|
15
|
+
self.klass = ENV["MODEL"]
|
16
|
+
self.days = ENV["DAYS"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def days=(days)
|
20
|
+
@days ||= days.blank? ? OLD_SLUG_DAYS : days.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def klass=(klass)
|
24
|
+
@klass ||= klass.to_s.classify.constantize unless klass.blank?
|
25
|
+
end
|
26
|
+
|
27
|
+
def make_slugs
|
28
|
+
validate_uses_slugs
|
29
|
+
options = {
|
30
|
+
:include => :slug,
|
31
|
+
:limit => (ENV["LIMIT"] || 100).to_i,
|
32
|
+
:offset => 0,
|
33
|
+
:order => ENV["ORDER"] || "#{klass.table_name}.id ASC",
|
34
|
+
}.merge(task_options || {})
|
35
|
+
|
36
|
+
while records = find(:all, options) do
|
37
|
+
break if records.size == 0
|
38
|
+
records.each do |record|
|
39
|
+
record.save(:validate => false) unless record.slug?
|
40
|
+
yield(record) if block_given?
|
41
|
+
end
|
42
|
+
options[:offset] += options[:limit]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete_slugs
|
47
|
+
validate_uses_slugs
|
48
|
+
Slug.destroy_all(["sluggable_type = ?", klass.to_s])
|
49
|
+
if column = friendly_id_config.cache_column
|
50
|
+
update_all("#{column} = NULL")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete_old_slugs
|
55
|
+
conditions = ["created_at < ?", DateTime.now - days]
|
56
|
+
if klass
|
57
|
+
conditions[0] << " AND sluggable_type = ?"
|
58
|
+
conditions << klass.to_s
|
59
|
+
end
|
60
|
+
Slug.all(:conditions => conditions).select(&:outdated?).map(&:destroy)
|
61
|
+
end
|
62
|
+
|
63
|
+
def validate_uses_slugs
|
64
|
+
(raise "You need to pass a MODEL=<model name> argument to rake") if klass.blank?
|
65
|
+
unless friendly_id_config.use_slug?
|
66
|
+
raise "Class '%s' doesn't use slugs" % klass.to_s
|
67
|
+
end
|
68
|
+
rescue NoMethodError
|
69
|
+
raise "Class '%s' doesn't use FriendlyId" % klass.to_s
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module FriendlyId
|
2
|
+
|
3
|
+
# This class is not intended to be used on its own, it is used internally
|
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
|
+
# :default_locale => :en
|
22
|
+
# # etc.
|
23
|
+
class Configuration
|
24
|
+
|
25
|
+
DEFAULTS = {
|
26
|
+
:allow_nil => false,
|
27
|
+
:ascii_approximation_options => [],
|
28
|
+
:max_length => 255,
|
29
|
+
:reserved_words => ["index", "new"],
|
30
|
+
:reserved_message => 'can not be "%s"',
|
31
|
+
:sequence_separator => "--",
|
32
|
+
:default_locale => :en
|
33
|
+
}
|
34
|
+
|
35
|
+
# Whether to allow friendly_id and/or slugs to be nil. This is not
|
36
|
+
# generally useful on its own, but may allow you greater flexibility to
|
37
|
+
# customize your application.
|
38
|
+
attr_accessor :allow_nil
|
39
|
+
alias :allow_nil? :allow_nil
|
40
|
+
|
41
|
+
# Strip diacritics from Western characters.
|
42
|
+
attr_accessor :approximate_ascii
|
43
|
+
|
44
|
+
# Locale-type options for ASCII approximations.
|
45
|
+
attr_accessor :ascii_approximation_options
|
46
|
+
|
47
|
+
# The class that's using the configuration.
|
48
|
+
attr_reader :configured_class
|
49
|
+
|
50
|
+
# The maximum allowed byte length for a friendly_id string. This is checked *after* a
|
51
|
+
# string is processed by FriendlyId to remove spaces, special characters, etc.
|
52
|
+
attr_accessor :max_length
|
53
|
+
|
54
|
+
# The method or column that will be used as the basis of the friendly_id string.
|
55
|
+
attr_reader :method
|
56
|
+
alias :column :method
|
57
|
+
|
58
|
+
# The message shown when a reserved word is used.
|
59
|
+
# @see #reserved_words
|
60
|
+
attr_accessor :reserved_message
|
61
|
+
|
62
|
+
# Array of words that are reserved and can't be used as friendly_id strings.
|
63
|
+
# If a listed word is used in a sluggable model, it will raise a
|
64
|
+
# FriendlyId::SlugGenerationError. For Rails applications, you are recommended
|
65
|
+
# to include "index" and "new", which used as the defaults unless overridden.
|
66
|
+
attr_accessor :reserved_words
|
67
|
+
|
68
|
+
# The method or relation to use as the friendly_id's scope.
|
69
|
+
attr_reader :scope
|
70
|
+
|
71
|
+
# The string that separates slug names from slug sequences. Defaults to "--".
|
72
|
+
attr_accessor :sequence_separator
|
73
|
+
|
74
|
+
# Strip non-ASCII characters from the friendly_id string.
|
75
|
+
attr_accessor :strip_non_ascii
|
76
|
+
|
77
|
+
# Use slugs for storing the friendly_id string.
|
78
|
+
attr_accessor :use_slug
|
79
|
+
alias :use_slugs= :use_slug
|
80
|
+
|
81
|
+
# Allows setting the default locale when locale column is present.
|
82
|
+
attr_accessor :locale, :default_locale
|
83
|
+
|
84
|
+
def initialize(configured_class, method, options = nil, &block)
|
85
|
+
@configured_class = configured_class
|
86
|
+
@method = method.to_sym
|
87
|
+
DEFAULTS.merge(options || {}).each do |key, value|
|
88
|
+
self.send "#{key}=".to_sym, value
|
89
|
+
end
|
90
|
+
yield self if block_given?
|
91
|
+
end
|
92
|
+
|
93
|
+
def cache_column=(value)
|
94
|
+
@cache_column = value.to_s.strip.to_sym
|
95
|
+
if value =~ /\s/ || [:slug, :slugs].include?(@cache_column)
|
96
|
+
raise ArgumentError, "FriendlyId cache column can not be named '#{value}'"
|
97
|
+
end
|
98
|
+
@cache_column
|
99
|
+
end
|
100
|
+
|
101
|
+
# This should be overridden by adapters that implement caching.
|
102
|
+
def cache_column?
|
103
|
+
false
|
104
|
+
end
|
105
|
+
|
106
|
+
def reserved_words=(*args)
|
107
|
+
if args.first.kind_of?(Regexp)
|
108
|
+
@reserved_words = args.first
|
109
|
+
else
|
110
|
+
@reserved_words = args.flatten.uniq
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def reserved?(word)
|
115
|
+
word = word.to_s
|
116
|
+
if reserved_words.kind_of?(Regexp)
|
117
|
+
reserved_words =~ word
|
118
|
+
else
|
119
|
+
reserved_words.include?(word)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def reserved_error_message(word)
|
124
|
+
[method, reserved_message % word] if reserved? word
|
125
|
+
end
|
126
|
+
|
127
|
+
def scope=(scope)
|
128
|
+
self.class.scopes_used = true
|
129
|
+
@scope = scope
|
130
|
+
end
|
131
|
+
|
132
|
+
def sequence_separator=(string)
|
133
|
+
if string == "-" || string =~ /\s/
|
134
|
+
raise ArgumentError, "FriendlyId sequence_separator can not be '#{string}'"
|
135
|
+
end
|
136
|
+
@sequence_separator = string
|
137
|
+
end
|
138
|
+
|
139
|
+
class << self
|
140
|
+
# This will be set if FriendlyId's scope feature is used in any model. It is here
|
141
|
+
# to provide a way to avoid invoking costly scope lookup methods when the scoped
|
142
|
+
# slug feature is not being used by any models.
|
143
|
+
def scopes_used=(val)
|
144
|
+
@scopes_used = !!val
|
145
|
+
end
|
146
|
+
|
147
|
+
# Are scoped slugs being used by any model?
|
148
|
+
# @see Configuration.scoped_used=
|
149
|
+
def scopes_used?
|
150
|
+
@scopes_used
|
151
|
+
end
|
152
|
+
|
153
|
+
# Are localed used by the slugs model?
|
154
|
+
def locales_used?
|
155
|
+
::Slug.table_exists? && ::Slug.column_names.include?('locale')
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
%w[approximate_ascii scope strip_non_ascii use_slug locale].each do |method|
|
160
|
+
class_eval(<<-EOM, __FILE__, __LINE__ + 1)
|
161
|
+
def #{method}?
|
162
|
+
!! #{method}
|
163
|
+
end
|
164
|
+
EOM
|
165
|
+
end
|
166
|
+
|
167
|
+
alias :use_slugs? :use_slug?
|
168
|
+
|
169
|
+
def babosa_options
|
170
|
+
{
|
171
|
+
:to_ascii => strip_non_ascii?,
|
172
|
+
:transliterate => approximate_ascii?,
|
173
|
+
:transliterations => ascii_approximation_options,
|
174
|
+
:max_length => max_length
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|