simple_slug 0.3.5 → 0.4.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.
- checksums.yaml +5 -5
- data/.travis.yml +1 -1
- data/README.md +8 -1
- data/db/migrate/20140113000001_create_simple_slug_history_slug.rb +6 -5
- data/lib/simple_slug.rb +11 -34
- data/lib/simple_slug/adapter.rb +123 -0
- data/lib/simple_slug/history_slug.rb +1 -0
- data/lib/simple_slug/model_addition.rb +24 -134
- data/lib/simple_slug/railtie.rb +0 -2
- data/lib/simple_slug/version.rb +1 -1
- data/simple_slug.gemspec +2 -2
- data/spec/simple_slug/base_spec.rb +5 -5
- data/spec/simple_slug/history_spec.rb +59 -34
- data/spec/simple_slug/model_addition_spec.rb +93 -121
- data/spec/spec_helper.rb +32 -36
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ac49bba6dff11ad2a2bce99cef0ff717ca35a626fb22c23ef708369b596c57fe
|
4
|
+
data.tar.gz: eb3955cec13641066e6d15aef572b78491fc8b6c59500658edbd72e05126083d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 961d7deede6a55925d4020f2b09f3e40b86012d3574f5745318a69ea34b952cef7f00b251562832ec053fcc61db52b268f647092f57e934e7278f58a34c8b789
|
7
|
+
data.tar.gz: dbc20244f3751330ac668edf4a92b381c9c1b2480a924be0b90cf0d37a194703cd6c9833e6cc1d852f8b912b08c815a93c916666660460b780a7cce02ed1341b
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# SimpleSlug
|
2
2
|
|
3
3
|
[](https://travis-ci.org/leschenko/simple_slug)
|
4
|
-
[](https://gemnasium.com/leschenko/simple_slug)
|
5
4
|
|
6
5
|
Simple friendly url generator for ActiveRecord models with history.
|
7
6
|
|
@@ -37,6 +36,14 @@ class User < ActiveRecord::Base
|
|
37
36
|
end
|
38
37
|
```
|
39
38
|
|
39
|
+
Add localization with `slug_YOUR_LOCALE` like columns:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
class User < ActiveRecord::Base
|
43
|
+
simple_slug :full_name, locales: [nil, :it]
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
40
47
|
If you want to control when slug is generated, define `should_generate_new_slug?` method:
|
41
48
|
|
42
49
|
```ruby
|
@@ -1,13 +1,14 @@
|
|
1
1
|
class CreateSimpleSlugHistorySlug < ActiveRecord::Migration
|
2
2
|
def change
|
3
|
-
create_table :
|
4
|
-
t.string :slug, null: false
|
3
|
+
create_table :simple_slug_history_slugs do |t|
|
4
|
+
t.string :slug, null: false, limit: 191
|
5
|
+
t.string :locale, limit: 10
|
5
6
|
t.integer :sluggable_id, null: false
|
6
7
|
t.string :sluggable_type, limit: 50, null: false
|
7
|
-
t.
|
8
|
+
t.timestamps
|
8
9
|
end
|
9
10
|
|
10
|
-
add_index :
|
11
|
-
add_index :
|
11
|
+
add_index :simple_slug_history_slugs, :slug
|
12
|
+
add_index :simple_slug_history_slugs, [:sluggable_type, :sluggable_id], name: 'simple_slug_history_slugs_on_sluggable_type_and_sluggable_id'
|
12
13
|
end
|
13
14
|
end
|
data/lib/simple_slug.rb
CHANGED
@@ -4,10 +4,12 @@ require 'simple_slug/model_addition'
|
|
4
4
|
require 'simple_slug/railtie' if Object.const_defined?(:Rails)
|
5
5
|
|
6
6
|
module SimpleSlug
|
7
|
+
autoload :Adapter, 'simple_slug/adapter'
|
8
|
+
autoload :ModelAddition, 'simple_slug/model_addition'
|
7
9
|
autoload :HistorySlug, 'simple_slug/history_slug'
|
8
10
|
|
9
11
|
mattr_accessor :excludes
|
10
|
-
@@excludes = %w(new edit show index session login logout sign_in sign_out users admin stylesheets
|
12
|
+
@@excludes = %w(new edit show index session login logout sign_in sign_out users admin stylesheets javascripts images fonts assets)
|
11
13
|
|
12
14
|
mattr_accessor :slug_regexp
|
13
15
|
@@slug_regexp = /\A(?:\w+[\w\d\-_]*|--\d+)\z/
|
@@ -15,48 +17,23 @@ module SimpleSlug
|
|
15
17
|
mattr_accessor :slug_column
|
16
18
|
@@slug_column = 'slug'
|
17
19
|
|
20
|
+
mattr_accessor :min_length
|
21
|
+
@@min_length = 3
|
22
|
+
|
18
23
|
mattr_accessor :max_length
|
19
|
-
@@max_length =
|
24
|
+
@@max_length = 191
|
20
25
|
|
21
26
|
mattr_accessor :callback_type
|
22
27
|
@@callback_type = :before_validation
|
23
28
|
|
24
|
-
mattr_accessor :
|
25
|
-
@@
|
29
|
+
mattr_accessor :validation
|
30
|
+
@@validation = true
|
26
31
|
|
27
32
|
STARTS_WITH_NUMBER_REGEXP =/\A\d+/
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
ES_NORMALIZE_SINGLE = [
|
32
|
-
'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåçèéêëìíîïñòóôõöøùúûüýÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıĴĵĶķĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſƒƠơƯưǍǎǏǐǑǒǓǔǕǖǗǘǙǚǛǜǺǻǾǿ',
|
33
|
-
'AAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaceeeeiiiinoooooouuuuyyAaAaAaCcCcCcCcDdDdEeEeEeEeEeGgGgGgGgHhHhIiIiIiIiIiJjKkLlLlLlLlllNnNnNnnOoOoOoRrRrRrSsSsSsSsTtTtTtUuUuUuUuUuUuWwYyYZzZzZzsfOoUuAaIiOoUuUuUuUuUuAaOo'
|
34
|
-
].freeze
|
35
|
-
|
36
|
-
ES_NORMALIZE_MULTI = [['Æ', 'AE'], ['æ', 'ae'], ['IJ', 'IJ'], ['ij', 'ij'], ['Œ', 'OE'], ['œ', 'oe'], ['Ǽ', 'AE'], ['ǽ', 'ae']].freeze
|
33
|
+
NUMBER_REGEXP =/\A\d+\z/
|
34
|
+
RESOLVE_SUFFIX_REGEXP = /--\d+\z/
|
37
35
|
|
38
36
|
def self.setup
|
39
37
|
yield self
|
40
38
|
end
|
41
|
-
|
42
|
-
def self.normalize_i18n_fix(base, locale=I18n.locale)
|
43
|
-
locale_sym = locale.to_sym
|
44
|
-
if CYRILLIC_LOCALES.include?(locale_sym)
|
45
|
-
normalize_cyrillic(base)
|
46
|
-
elsif ES_LOCALES.include?(locale_sym)
|
47
|
-
normalize_es(base)
|
48
|
-
else
|
49
|
-
base
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.normalize_cyrillic(base)
|
54
|
-
base.tr('АаВЕеіКкМНОоРрСсТуХх', 'AaBEeiKkMHOoPpCcTyXx')
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.normalize_es(base)
|
58
|
-
base = base.tr(*ES_NORMALIZE_SINGLE)
|
59
|
-
ES_NORMALIZE_MULTI.each{|d| base.gsub!(*d) }
|
60
|
-
base
|
61
|
-
end
|
62
39
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module SimpleSlug
|
2
|
+
class Adapter
|
3
|
+
attr_reader :model, :options, :locales
|
4
|
+
attr_accessor :current_locale
|
5
|
+
|
6
|
+
def initialize(model)
|
7
|
+
@model = model
|
8
|
+
@options = model.simple_slug_options
|
9
|
+
@locales = Array(@options[:locales] || [nil])
|
10
|
+
end
|
11
|
+
|
12
|
+
def finder_method
|
13
|
+
options[:history] ? :find_by : :find_by!
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid_locale?(locale)
|
17
|
+
locales.include?(locale)
|
18
|
+
end
|
19
|
+
|
20
|
+
def current_locale
|
21
|
+
valid_locale?(I18n.locale) ? I18n.locale : nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def column_names
|
25
|
+
locales.map{|l| column_name(l) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def column_name(locale=I18n.locale)
|
29
|
+
[options[:slug_column], (locale if valid_locale?(locale))].compact.join('_')
|
30
|
+
end
|
31
|
+
|
32
|
+
def get(record)
|
33
|
+
record.send(column_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_prev(record)
|
37
|
+
record.send("#{column_name}_was")
|
38
|
+
end
|
39
|
+
|
40
|
+
def set(record, value)
|
41
|
+
record.send("#{column_name}=", value)
|
42
|
+
end
|
43
|
+
|
44
|
+
def each_locale
|
45
|
+
locales.each do |l|
|
46
|
+
with_locale(l || I18n.default_locale) { yield }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def reset(record)
|
51
|
+
each_locale{ set record, get_prev(record) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def save_history(record)
|
55
|
+
each_locale do
|
56
|
+
slug_was = record.saved_change_to_attribute(column_name).try!(:first)
|
57
|
+
next if slug_was.blank?
|
58
|
+
::SimpleSlug::HistorySlug.where(sluggable_type: record.class.name, slug: slug_was, locale: current_locale).first_or_initialize.update(sluggable_id: record.id)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def generate(record, force: false)
|
63
|
+
each_locale do
|
64
|
+
next unless force || record.should_generate_new_slug?
|
65
|
+
simple_slug = normalize(slug_base(record))
|
66
|
+
simple_slug = "__#{record.id || rand(9999)}" if simple_slug.blank? && options[:fallback_on_blank]
|
67
|
+
return if simple_slug == get(record).to_s.sub(SimpleSlug::RESOLVE_SUFFIX_REGEXP, '')
|
68
|
+
set(record, resolve(record, simple_slug))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def normalize(base)
|
73
|
+
parameterize_args = ActiveSupport::VERSION::MAJOR > 4 ? {separator: '-'} : '-'
|
74
|
+
normalized = I18n.transliterate(base).parameterize(parameterize_args).downcase
|
75
|
+
normalized = "_#{normalized}" if normalized =~ SimpleSlug::STARTS_WITH_NUMBER_REGEXP
|
76
|
+
normalized = normalized.first(options[:max_length]) if options[:max_length]
|
77
|
+
normalized
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_suffix(slug_value)
|
81
|
+
"#{slug_value}--#{rand(99999)}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def slug_base(record)
|
85
|
+
options[:slug_method].map{|m| record.send(m).to_s }.reject(&:blank?).join(' ')
|
86
|
+
end
|
87
|
+
|
88
|
+
def resolve(record, slug_value)
|
89
|
+
return slug_value unless slug_exists?(record, slug_value)
|
90
|
+
loop do
|
91
|
+
slug_with_suffix = add_suffix(slug_value)
|
92
|
+
break slug_with_suffix unless slug_exists?(record, slug_with_suffix)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def slug_exists?(record, slug_value)
|
97
|
+
model_slug_exists?(record, slug_value) || history_slug_exists?(record, slug_value)
|
98
|
+
end
|
99
|
+
|
100
|
+
def model_slug_exists?(record, slug_value)
|
101
|
+
base_scope = record.class.unscoped.where(column_name => slug_value)
|
102
|
+
base_scope = base_scope.where('id != ?', record.id) if record.persisted?
|
103
|
+
base_scope.exists?
|
104
|
+
end
|
105
|
+
|
106
|
+
def history_slug_exists?(record, slug_value)
|
107
|
+
return false unless options[:history]
|
108
|
+
base_scope = SimpleSlug::HistorySlug.where(sluggable_type: record.class.name, slug: slug_value)
|
109
|
+
base_scope = base_scope.where('sluggable_id != ?', record.id) if record.persisted?
|
110
|
+
base_scope.exists?
|
111
|
+
end
|
112
|
+
|
113
|
+
def with_locale(locale)
|
114
|
+
if defined? Globalize
|
115
|
+
Globalize.with_locale(locale) do
|
116
|
+
I18n.with_locale(locale) { yield }
|
117
|
+
end
|
118
|
+
else
|
119
|
+
I18n.with_locale(locale) { yield }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -6,33 +6,35 @@ module SimpleSlug
|
|
6
6
|
|
7
7
|
module SingletonMethods
|
8
8
|
def simple_slug(*args)
|
9
|
-
class_attribute :simple_slug_options, instance_writer: false
|
9
|
+
class_attribute :simple_slug_options, :simple_slug_adapter, instance_writer: false
|
10
10
|
options = args.extract_options!
|
11
11
|
self.simple_slug_options = options.reverse_merge(
|
12
12
|
slug_column: SimpleSlug.slug_column,
|
13
13
|
slug_method: args,
|
14
14
|
slug_regexp: SimpleSlug.slug_regexp,
|
15
|
+
min_length: SimpleSlug.min_length,
|
15
16
|
max_length: SimpleSlug.max_length,
|
16
17
|
callback_type: SimpleSlug.callback_type,
|
17
|
-
|
18
|
+
validation: SimpleSlug.validation
|
18
19
|
)
|
20
|
+
self.simple_slug_adapter = SimpleSlug::Adapter.new(self)
|
19
21
|
|
20
22
|
include InstanceMethods
|
21
23
|
extend ClassMethods
|
22
24
|
|
23
25
|
send(simple_slug_options[:callback_type], :simple_slug_generate, if: :should_generate_new_slug?) if simple_slug_options[:callback_type]
|
24
26
|
|
25
|
-
if simple_slug_options[:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
if simple_slug_options[:validation]
|
28
|
+
validates *simple_slug_adapter.column_names,
|
29
|
+
presence: true,
|
30
|
+
uniqueness: {case_sensitive: true},
|
31
|
+
exclusion: {in: SimpleSlug.excludes},
|
32
|
+
format: {with: simple_slug_options[:slug_regexp]},
|
33
|
+
length: {minimum: simple_slug_options[:min_length], maximum: simple_slug_options[:max_length]}.reject{|_, v| v.blank? }
|
32
34
|
end
|
33
35
|
|
34
36
|
if simple_slug_options[:history]
|
35
|
-
after_save :
|
37
|
+
after_save :simple_slug_reset, :simple_slug_save_history
|
36
38
|
after_destroy :simple_slug_cleanup_history
|
37
39
|
include InstanceHistoryMethods
|
38
40
|
end
|
@@ -42,157 +44,45 @@ module SimpleSlug
|
|
42
44
|
module ClassMethods
|
43
45
|
def simple_slug_find(id_param)
|
44
46
|
return unless id_param
|
45
|
-
if id_param.is_a?(Integer) || id_param =~
|
47
|
+
if id_param.is_a?(Integer) || id_param =~ SimpleSlug::NUMBER_REGEXP
|
46
48
|
find(id_param)
|
47
49
|
else
|
48
|
-
finder_method
|
49
|
-
send(finder_method, simple_slug_column => id_param) or find(::SimpleSlug::HistorySlug.find_by!(slug: id_param).sluggable_id)
|
50
|
+
send(simple_slug_adapter.finder_method, simple_slug_adapter.column_name => id_param) or simple_slug_history_find(id_param)
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
def simple_slug_column(locale=I18n.locale)
|
56
|
-
if simple_slug_localized?(locale)
|
57
|
-
[simple_slug_options[:slug_column], locale].compact.join('_')
|
58
|
-
else
|
59
|
-
simple_slug_options[:slug_column]
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def simple_slug_columns
|
64
|
-
simple_slug_locales.map{|locale| simple_slug_column(locale) }
|
54
|
+
def simple_slug_history_find(slug, locale=I18n.locale)
|
55
|
+
find(SimpleSlug::HistorySlug.find_by!(locale: (locale if simple_slug_adapter.valid_locale?(locale)), slug: slug).sluggable_id)
|
65
56
|
end
|
66
57
|
|
67
|
-
|
68
|
-
Array(simple_slug_options[:locales] || [nil])
|
69
|
-
end
|
70
|
-
|
71
|
-
def simple_slug_localized?(locale=I18n.locale)
|
72
|
-
return unless locale
|
73
|
-
simple_slug_locales.include?(locale.to_sym)
|
74
|
-
end
|
58
|
+
alias_method :friendly_find, :simple_slug_find
|
75
59
|
end
|
76
60
|
|
77
61
|
module InstanceMethods
|
78
62
|
def to_param
|
79
|
-
|
63
|
+
simple_slug_adapter.get_prev(self).presence || super
|
80
64
|
end
|
81
65
|
|
82
66
|
def should_generate_new_slug?
|
83
|
-
|
84
|
-
if simple_slug_options[:locales]
|
85
|
-
should_generate_new_slug_for_locales.present?
|
86
|
-
else
|
87
|
-
simple_slug_get.blank?
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def should_generate_new_slug_for_locales
|
92
|
-
return unless simple_slug_options[:locales]
|
93
|
-
simple_slug_options[:locales].find_all {|locale| simple_slug_get(locale).blank?}
|
67
|
+
simple_slug_adapter.column_names.any?{|cn| send(cn).blank? }
|
94
68
|
end
|
95
69
|
|
96
70
|
def simple_slug_generate(force=false)
|
97
|
-
|
98
|
-
((!force && should_generate_new_slug_for_locales) || simple_slug_options[:locales])
|
99
|
-
else
|
100
|
-
[nil]
|
101
|
-
end
|
102
|
-
locales.each do |locale|
|
103
|
-
simple_slug_generate_for_locale(locale, force)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def simple_slug_generate_for_locale(locale=I18n.locale, force=false)
|
108
|
-
simple_slug_with_locale(locale) do
|
109
|
-
simple_slug = simple_slug_normalize(simple_slug_base)
|
110
|
-
simple_slug = simple_slug.first(simple_slug_options[:max_length]) if simple_slug_options[:max_length]
|
111
|
-
simple_slug = "__#{id || rand(9999)}" if simple_slug.blank? && simple_slug_options[:fallback_on_blank]
|
112
|
-
return if !force && simple_slug == simple_slug_get(locale).to_s.sub(/--\d+\z/, '')
|
113
|
-
resolved_simple_slug = simple_slug_resolve(simple_slug, locale)
|
114
|
-
simple_slug_set(resolved_simple_slug, locale)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def simple_slug_with_locale(locale)
|
119
|
-
if defined? Globalize
|
120
|
-
Globalize.with_locale(locale) do
|
121
|
-
I18n.with_locale(locale) { yield }
|
122
|
-
end
|
123
|
-
else
|
124
|
-
I18n.with_locale(locale) { yield }
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def simple_slug_base
|
129
|
-
simple_slug_options[:slug_method].map{|m| send(m).to_s }.reject(&:blank?).join(' ')
|
130
|
-
end
|
131
|
-
|
132
|
-
def simple_slug_normalize(base)
|
133
|
-
parameterize_args = ActiveSupport::VERSION::MAJOR > 4 ? {separator: '-'} : '-'
|
134
|
-
normalized = I18n.transliterate(SimpleSlug.normalize_i18n_fix(base)).parameterize(parameterize_args).downcase
|
135
|
-
normalized.to_s =~ SimpleSlug::STARTS_WITH_NUMBER_REGEXP ? "_#{normalized}" : normalized
|
136
|
-
end
|
137
|
-
|
138
|
-
def simple_slug_resolve(slug_value, locale=I18n.locale)
|
139
|
-
if simple_slug_exists?(slug_value, locale)
|
140
|
-
loop do
|
141
|
-
slug_value_with_suffix = simple_slug_next(slug_value)
|
142
|
-
break slug_value_with_suffix unless simple_slug_exists?(slug_value_with_suffix, locale)
|
143
|
-
end
|
144
|
-
else
|
145
|
-
slug_value
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def simple_slug_next(slug_value)
|
150
|
-
"#{slug_value}--#{rand(99999)}"
|
151
|
-
end
|
152
|
-
|
153
|
-
def simple_slug_exists?(slug_value, locale=I18n.locale)
|
154
|
-
simple_slug_base_exists?(slug_value, locale) || simple_slug_history_exists?(slug_value)
|
155
|
-
end
|
156
|
-
|
157
|
-
def simple_slug_base_exists?(slug_value, locale=I18n.locale)
|
158
|
-
base_scope = self.class.unscoped.where(self.class.simple_slug_column(locale) => slug_value)
|
159
|
-
base_scope = base_scope.where('id != ?', id) if persisted?
|
160
|
-
base_scope.exists?
|
161
|
-
end
|
162
|
-
|
163
|
-
def simple_slug_history_exists?(slug_value)
|
164
|
-
return false unless simple_slug_options[:history]
|
165
|
-
base_scope = ::SimpleSlug::HistorySlug.where(sluggable_type: self.class.name, slug: slug_value)
|
166
|
-
base_scope = base_scope.where('sluggable_id != ?', id) if persisted?
|
167
|
-
base_scope.exists?
|
168
|
-
end
|
169
|
-
|
170
|
-
def simple_slug_set(value, locale=I18n.locale)
|
171
|
-
send "#{self.class.simple_slug_column(locale)}=", value
|
172
|
-
end
|
173
|
-
|
174
|
-
def simple_slug_get(locale=I18n.locale)
|
175
|
-
send self.class.simple_slug_column(locale)
|
176
|
-
end
|
177
|
-
|
178
|
-
def simple_slug_stored_slug(locale=I18n.locale)
|
179
|
-
send("#{self.class.simple_slug_column(locale)}_was")
|
71
|
+
simple_slug_adapter.generate(self, force: force)
|
180
72
|
end
|
181
73
|
end
|
182
74
|
|
183
75
|
module InstanceHistoryMethods
|
184
|
-
def
|
185
|
-
|
186
|
-
simple_slug_set simple_slug_stored_slug
|
76
|
+
def simple_slug_reset
|
77
|
+
errors.blank? || simple_slug_adapter.reset(self)
|
187
78
|
end
|
188
79
|
|
189
80
|
def simple_slug_cleanup_history
|
190
81
|
::SimpleSlug::HistorySlug.where(sluggable_type: self.class.name, sluggable_id: id).delete_all
|
191
82
|
end
|
192
83
|
|
193
|
-
def
|
194
|
-
|
195
|
-
::SimpleSlug::HistorySlug.where(sluggable_type: self.class.name, slug: simple_slug_get).first_or_create{|hs| hs.sluggable_id = id }
|
84
|
+
def simple_slug_save_history
|
85
|
+
simple_slug_adapter.save_history(self)
|
196
86
|
end
|
197
87
|
end
|
198
88
|
end
|
data/lib/simple_slug/railtie.rb
CHANGED
data/lib/simple_slug/version.rb
CHANGED
data/simple_slug.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'simple_slug/version'
|
@@ -18,10 +17,11 @@ Gem::Specification.new do |spec|
|
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ['lib']
|
20
19
|
|
21
|
-
spec.add_dependency 'activerecord', '>= 4.0.0', '<
|
20
|
+
spec.add_dependency 'activerecord', '>= 4.0.0', '< 6.1'
|
22
21
|
spec.add_dependency 'i18n', '~> 0.7'
|
23
22
|
|
24
23
|
spec.add_development_dependency 'bundler', '~> 1.5'
|
25
24
|
spec.add_development_dependency 'rake'
|
26
25
|
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'sqlite3'
|
27
27
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SimpleSlug do
|
4
|
-
|
5
|
-
it '
|
4
|
+
describe 'config' do
|
5
|
+
it 'has column name' do
|
6
6
|
expect(SimpleSlug.slug_column).to eq 'slug'
|
7
7
|
end
|
8
8
|
|
9
|
-
it 'excludes' do
|
9
|
+
it 'has excludes' do
|
10
10
|
expect(SimpleSlug.excludes).to include('new', 'edit')
|
11
11
|
end
|
12
12
|
|
13
|
-
it 'max length' do
|
14
|
-
expect( SimpleSlug.max_length).to eq
|
13
|
+
it 'has max length' do
|
14
|
+
expect( SimpleSlug.max_length).to eq 191
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -1,54 +1,79 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class SlugHistoryRspecModel <
|
3
|
+
class SlugHistoryRspecModel < RspecActiveRecordBase
|
4
4
|
simple_slug :name, history: true
|
5
|
+
|
6
|
+
def should_generate_new_slug?
|
7
|
+
true
|
8
|
+
end
|
5
9
|
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
class SlugLocalizedHistoryRspecModel < RspecActiveRecordBase
|
12
|
+
simple_slug :name_for_slug, history: true, locales: [nil, :en]
|
13
|
+
|
14
|
+
def name_for_slug
|
15
|
+
[name, (I18n.locale unless I18n.locale == I18n.default_locale)].compact.join(' ')
|
16
|
+
end
|
17
|
+
|
18
|
+
def should_generate_new_slug?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'history' do
|
24
|
+
before :each do
|
25
|
+
RspecActiveRecordBase.delete_all
|
26
|
+
SimpleSlug::HistorySlug.delete_all
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'persistence' do
|
30
|
+
it 'save previous on change' do
|
31
|
+
sluggable = SlugHistoryRspecModel.create(id: 1, name: 'Hello')
|
32
|
+
expect(SimpleSlug::HistorySlug.where(sluggable_type: 'SlugHistoryRspecModel', sluggable_id: 1).exists?).to be_falsey
|
33
|
+
sluggable.update(name: 'Bye')
|
34
|
+
hs = SimpleSlug::HistorySlug.where(sluggable_type: 'SlugHistoryRspecModel', sluggable_id: 1).to_a
|
35
|
+
expect(hs.size).to eq 1
|
36
|
+
expect(hs.first.locale).to be_falsey
|
37
|
+
expect(hs.first.slug).to eq 'hello'
|
11
38
|
end
|
12
39
|
|
13
|
-
it '
|
14
|
-
|
15
|
-
|
16
|
-
expect
|
17
|
-
SlugHistoryRspecModel.create(id: 1, name: 'Hello')
|
40
|
+
it 'remove on destroy' do
|
41
|
+
sluggable = SlugHistoryRspecModel.create(id: 1, name: 'Hello')
|
42
|
+
sluggable.update(name: 'Bye')
|
43
|
+
expect{ sluggable.destroy }.to change{ SimpleSlug::HistorySlug.where(sluggable_type: 'SlugHistoryRspecModel', sluggable_id: 1).count }.from(1).to(0)
|
18
44
|
end
|
19
45
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
46
|
+
context 'localized' do
|
47
|
+
it 'save previous on change' do
|
48
|
+
SlugLocalizedHistoryRspecModel.create(id: 1, name: 'Hello').update(name: 'Bye')
|
49
|
+
hs = SimpleSlug::HistorySlug.where(sluggable_type: 'SlugLocalizedHistoryRspecModel', sluggable_id: 1).to_a
|
50
|
+
expect(hs.map(&:locale)).to match_array [nil, 'en']
|
51
|
+
expect(hs.map(&:slug)).to match_array %w(hello hello-en)
|
52
|
+
end
|
26
53
|
end
|
27
54
|
end
|
28
55
|
|
29
56
|
describe 'conflicts' do
|
30
|
-
it '
|
31
|
-
|
32
|
-
|
33
|
-
expect(record).to
|
34
|
-
expect(record).to receive(:simple_slug_history_exists?).once.ordered.and_return(false)
|
35
|
-
record.save
|
36
|
-
expect(record.slug).to start_with('hi--')
|
57
|
+
it 'resolve with suffix' do
|
58
|
+
SlugHistoryRspecModel.create(name: 'Hello').update(name: 'Bye')
|
59
|
+
record = SlugHistoryRspecModel.create(name: 'Hello')
|
60
|
+
expect(record.slug).to start_with('hello--')
|
37
61
|
end
|
38
|
-
end
|
39
62
|
|
40
|
-
|
41
|
-
|
42
|
-
|
63
|
+
context 'localized' do
|
64
|
+
it 'resolve with suffix' do
|
65
|
+
SlugLocalizedHistoryRspecModel.create(name: 'Hello').update(name: 'Bye')
|
66
|
+
record = SlugLocalizedHistoryRspecModel.create(name: 'Hello')
|
67
|
+
expect(record.slug).to start_with('hello--')
|
68
|
+
expect(record.slug_en).to start_with('hello-en--')
|
69
|
+
end
|
43
70
|
end
|
71
|
+
end
|
44
72
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
expect(
|
49
|
-
expect(SlugHistoryRspecModel).to receive(:find).with(1).and_return(record)
|
50
|
-
SlugHistoryRspecModel.friendly_find('title')
|
73
|
+
describe 'find' do
|
74
|
+
it 'use history' do
|
75
|
+
SlugLocalizedHistoryRspecModel.create(id: 1, name: 'Hello').update(name: 'Bye')
|
76
|
+
expect(SlugLocalizedHistoryRspecModel.friendly_find('hello')).to be_truthy
|
51
77
|
end
|
52
78
|
end
|
53
|
-
|
54
79
|
end
|
@@ -1,220 +1,192 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class SlugRspecModel < RspecActiveRecordBase
|
4
4
|
simple_slug :name
|
5
5
|
end
|
6
6
|
|
7
|
-
class
|
8
|
-
simple_slug :name,
|
7
|
+
class SlugWithFallbackOnBlankRspecModel < RspecActiveRecordBase
|
8
|
+
simple_slug :name, fallback_on_blank: true
|
9
9
|
end
|
10
10
|
|
11
|
-
class
|
12
|
-
simple_slug :name,
|
11
|
+
class SlugWithoutMaxLengthRspecModel < RspecActiveRecordBase
|
12
|
+
simple_slug :name, max_length: nil
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
|
16
|
+
class SlugWithoutValidationRspecModel < RspecActiveRecordBase
|
17
|
+
simple_slug :name, validation: false
|
17
18
|
end
|
18
19
|
|
19
|
-
class
|
20
|
-
|
21
|
-
|
20
|
+
class SlugWithoutCallbackRspecModel < RspecActiveRecordBase
|
21
|
+
simple_slug :name, callback_type: nil
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
+
class SlugLocalizedRspecModel < RspecActiveRecordBase
|
25
|
+
simple_slug :name_for_slug, history: true, locales: [nil, :en]
|
24
26
|
|
25
|
-
def
|
26
|
-
I18n.locale
|
27
|
+
def name_for_slug
|
28
|
+
[name, (I18n.locale unless I18n.locale == I18n.default_locale)].compact.join(' ')
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
describe SimpleSlug::ModelAddition do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'after save' do
|
38
|
-
expect(SlugGenerationRspecModel.create(name: 'Hello').slug).to eq 'hello'
|
39
|
-
end
|
33
|
+
before :each do
|
34
|
+
RspecActiveRecordBase.delete_all
|
35
|
+
SimpleSlug::HistorySlug.delete_all
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
38
|
+
describe 'slug' do
|
39
|
+
it 'generate on save' do
|
40
|
+
expect(SlugRspecModel.create(name: 'Hello').slug).to eq 'hello'
|
43
41
|
end
|
44
42
|
|
45
|
-
it '
|
46
|
-
expect(
|
43
|
+
it 'add prefix for numbers' do
|
44
|
+
expect(SlugRspecModel.create(name: '123').slug).to eq '_123'
|
47
45
|
end
|
48
46
|
|
49
|
-
it '
|
50
|
-
expect(
|
47
|
+
it 'reject excludes' do
|
48
|
+
expect(SlugRspecModel.new(name: 'new')).not_to be_valid
|
51
49
|
end
|
52
50
|
|
53
|
-
it '
|
54
|
-
expect(
|
51
|
+
it 'reject spaces' do
|
52
|
+
expect(SlugRspecModel.new(slug: 'test test')).not_to be_valid
|
55
53
|
end
|
56
54
|
|
57
|
-
it '
|
58
|
-
|
59
|
-
expect(SlugGenerationRspecModel.create(name: 'áǼßHello').slug).to eq 'aaeshello'
|
60
|
-
end
|
55
|
+
it 'reject punctuation' do
|
56
|
+
expect(SlugRspecModel.new(slug: 'test.test')).not_to be_valid
|
61
57
|
end
|
62
58
|
|
63
|
-
it 'fallback on blank' do
|
64
|
-
|
65
|
-
expect(SlugGenerationRspecModelWithFallbackOnBlank.create({}).slug).to start_with '__'
|
59
|
+
it 'fallback to prefixed id on blank slug source' do
|
60
|
+
expect(SlugWithFallbackOnBlankRspecModel.create({}).slug).to start_with '__'
|
66
61
|
end
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
describe '#should_generate_new_slug?' do
|
64
|
+
it 'can omit generation' do
|
65
|
+
allow_any_instance_of(SlugRspecModel).to receive(:should_generate_new_slug?).and_return(false)
|
66
|
+
expect(SlugRspecModel.create(name: 'Hello').slug).to be_blank
|
67
|
+
end
|
71
68
|
end
|
72
69
|
end
|
73
70
|
|
74
|
-
describe '
|
75
|
-
it '
|
76
|
-
|
77
|
-
|
78
|
-
expect(record).to
|
79
|
-
record.save
|
80
|
-
expect(record.slug).to start_with('hi--')
|
71
|
+
describe 'conflicts' do
|
72
|
+
it 'resolve with suffix' do
|
73
|
+
SlugRspecModel.create(name: 'Hello')
|
74
|
+
record = SlugHistoryRspecModel.create(name: 'Hello')
|
75
|
+
expect(record.slug).to start_with('hello--')
|
81
76
|
end
|
82
77
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
78
|
+
context 'localized' do
|
79
|
+
it 'resolve with suffix' do
|
80
|
+
SlugLocalizedRspecModel.create(name: 'Hello')
|
81
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
82
|
+
expect(record.slug).to start_with('hello--')
|
83
|
+
expect(record.slug_en).to start_with('hello-en--')
|
84
|
+
end
|
88
85
|
end
|
89
86
|
end
|
90
87
|
|
91
88
|
describe '#to_param' do
|
92
89
|
before do
|
93
|
-
allow_any_instance_of(
|
90
|
+
allow_any_instance_of(SlugRspecModel).to receive(:simple_slug_exists?).and_return(false)
|
94
91
|
end
|
95
92
|
|
96
|
-
it 'slug if
|
97
|
-
expect(
|
93
|
+
it 'use slug if present' do
|
94
|
+
expect(SlugRspecModel.create(name: 'Hello').to_param).to eq 'hello'
|
98
95
|
end
|
99
96
|
|
100
|
-
it '
|
101
|
-
expect(
|
97
|
+
it 'do not use unsaved slug' do
|
98
|
+
expect(SlugRspecModel.new(name: 'Hello').to_param).to be_falsey
|
102
99
|
end
|
103
|
-
end
|
104
100
|
|
105
|
-
|
106
|
-
|
107
|
-
expect(SlugGenerationRspecModel).to receive(:find).with(1)
|
108
|
-
SlugGenerationRspecModel.friendly_find(1)
|
101
|
+
it 'use id if slug blank' do
|
102
|
+
expect(SlugRspecModel.create(id: 1).to_param).to eq '1'
|
109
103
|
end
|
104
|
+
end
|
110
105
|
|
111
|
-
|
112
|
-
|
113
|
-
|
106
|
+
describe 'find' do
|
107
|
+
it 'by id on integer like param' do
|
108
|
+
expect(SlugRspecModel).to receive(:find).with('1')
|
109
|
+
SlugRspecModel.friendly_find('1')
|
114
110
|
end
|
115
111
|
|
116
|
-
it '
|
117
|
-
expect(
|
118
|
-
|
112
|
+
it 'by slug' do
|
113
|
+
expect(SlugRspecModel).to receive(:find_by!).with('slug' => 'title').and_return(double)
|
114
|
+
SlugRspecModel.friendly_find('title')
|
119
115
|
end
|
120
116
|
end
|
121
117
|
|
122
118
|
describe 'max length' do
|
123
|
-
before do
|
124
|
-
allow_any_instance_of(SlugGenerationRspecModel).to receive(:simple_slug_exists?).and_return(false)
|
125
|
-
end
|
126
|
-
|
127
|
-
after do
|
128
|
-
SlugGenerationRspecModel.simple_slug_options.delete(:max_length)
|
129
|
-
end
|
130
|
-
|
131
119
|
it 'cuts slug to max length' do
|
132
|
-
record =
|
133
|
-
record.simple_slug_generate
|
134
|
-
expect(record.slug.length).to eq 240
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'use max length from per model options' do
|
138
|
-
SlugGenerationRspecModel.simple_slug_options[:max_length] = 100
|
139
|
-
record = SlugGenerationRspecModel.new(name: 'Hello' * 100)
|
120
|
+
record = SlugRspecModel.new(name: 'Hello' * 100)
|
140
121
|
record.simple_slug_generate
|
141
|
-
expect(record.slug.length).to eq
|
122
|
+
expect(record.slug.length).to eq 191
|
142
123
|
end
|
143
124
|
|
144
|
-
it '
|
145
|
-
|
146
|
-
record = SlugGenerationRspecModel.new(name: 'Hello' * 100)
|
125
|
+
it 'return full slug without max_length option' do
|
126
|
+
record = SlugWithoutMaxLengthRspecModel.new(name: 'Hello' * 100)
|
147
127
|
record.simple_slug_generate
|
148
128
|
expect(record.slug.length).to eq 500
|
149
129
|
end
|
150
130
|
end
|
151
131
|
|
152
|
-
describe '
|
153
|
-
it 'skip
|
154
|
-
expect(
|
132
|
+
describe 'validation' do
|
133
|
+
it 'optionally skip validations' do
|
134
|
+
expect(SlugWithoutValidationRspecModel.validators_on(:slug)).to be_blank
|
155
135
|
end
|
156
136
|
end
|
157
137
|
|
158
|
-
describe '
|
159
|
-
it 'skip callback' do
|
160
|
-
expect(
|
138
|
+
describe 'callbacks' do
|
139
|
+
it 'optionally skip callback' do
|
140
|
+
expect(SlugWithoutCallbackRspecModel.new).not_to receive(:should_generate_new_slug?)
|
161
141
|
end
|
162
142
|
end
|
163
143
|
|
164
144
|
describe 'localized' do
|
165
|
-
before do
|
166
|
-
allow_any_instance_of(SlugGenerationRspecModelLocalized).to receive(:simple_slug_exists?).and_return(false)
|
167
|
-
end
|
168
|
-
|
169
145
|
it 'generate slug for locales' do
|
170
|
-
record =
|
146
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
171
147
|
expect(record.slug).to eq 'hello'
|
172
148
|
expect(record.slug_en).to eq 'hello-en'
|
173
149
|
end
|
174
150
|
|
175
151
|
describe '#should_generate_new_slug?' do
|
176
|
-
it 'keep
|
177
|
-
record =
|
178
|
-
record.name
|
179
|
-
record.slug_en = nil
|
180
|
-
record.name_en = 'Bye en'
|
181
|
-
expect{ record.save }.not_to change{ record.slug }
|
152
|
+
it 'keep slug when present' do
|
153
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
154
|
+
expect{ record.update(name: 'Bye') }.not_to change{ record.slug }
|
182
155
|
end
|
183
156
|
|
184
|
-
it 'generate slug
|
185
|
-
record =
|
157
|
+
it 'generate slug when blank' do
|
158
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
186
159
|
record.name = 'bye'
|
187
160
|
record.slug_en = nil
|
188
|
-
record.name_en = 'Bye en'
|
189
161
|
expect{ record.save }.to change{ record.slug_en }.to('bye-en')
|
190
162
|
end
|
191
163
|
end
|
192
164
|
|
193
165
|
describe '#to_param' do
|
194
|
-
it '
|
195
|
-
record =
|
166
|
+
it 'use unlocalized column for default locale' do
|
167
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
196
168
|
expect(record.to_param).to eq 'hello'
|
197
169
|
end
|
198
170
|
|
199
|
-
it '
|
200
|
-
record =
|
171
|
+
it 'use localized column for non-default locales' do
|
172
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
201
173
|
I18n.with_locale(:en) do
|
202
174
|
expect(record.to_param).to eq 'hello-en'
|
203
175
|
end
|
204
176
|
end
|
205
177
|
end
|
206
178
|
|
207
|
-
describe '
|
208
|
-
it 'use default slug column
|
209
|
-
record =
|
210
|
-
expect(
|
211
|
-
SlugGenerationRspecModelLocalized.simple_slug_find('hello')
|
179
|
+
describe 'find' do
|
180
|
+
it 'use default slug column for default locale' do
|
181
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
182
|
+
expect(SlugLocalizedRspecModel.simple_slug_find('hello')).to eq record
|
212
183
|
end
|
213
184
|
|
214
|
-
it 'use localized slug column' do
|
215
|
-
record =
|
216
|
-
|
217
|
-
|
185
|
+
it 'use localized slug column for non-default locale' do
|
186
|
+
record = SlugLocalizedRspecModel.create(name: 'Hello')
|
187
|
+
I18n.with_locale(:en) do
|
188
|
+
expect(SlugLocalizedRspecModel.simple_slug_find('hello-en')).to eq record
|
189
|
+
end
|
218
190
|
end
|
219
191
|
end
|
220
192
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,48 +1,44 @@
|
|
1
|
+
require 'sqlite3'
|
1
2
|
require 'active_record'
|
2
3
|
require 'i18n'
|
3
4
|
require 'active_support/core_ext'
|
4
5
|
require 'byebug'
|
5
6
|
require 'simple_slug'
|
6
7
|
|
7
|
-
# just silence warning
|
8
8
|
I18n.enforce_available_locales = false
|
9
9
|
I18n.default_locale = :uk
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
true
|
11
|
+
ActiveRecord::Base.establish_connection(
|
12
|
+
adapter: 'sqlite3',
|
13
|
+
database: ':memory:'
|
14
|
+
)
|
15
|
+
|
16
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.before(:suite) do
|
20
|
+
ActiveRecord::Migration.verbose = false
|
21
|
+
|
22
|
+
ActiveRecord::Schema.define do
|
23
|
+
create_table :rspec_active_record_bases, force: true do |t|
|
24
|
+
t.string :name
|
25
|
+
t.string :slug, limit: 191
|
26
|
+
t.string :slug_en, limit: 191
|
27
|
+
t.timestamps
|
28
|
+
end
|
29
|
+
|
30
|
+
create_table :simple_slug_history_slugs, force: true do |t|
|
31
|
+
t.string :slug, null: false, limit: 191
|
32
|
+
t.string :locale, limit: 10
|
33
|
+
t.integer :sluggable_id, null: false
|
34
|
+
t.string :sluggable_type, limit: 50, null: false
|
35
|
+
t.timestamps
|
36
|
+
end
|
37
|
+
end
|
39
38
|
end
|
39
|
+
end
|
40
40
|
|
41
|
-
def slug_changed?
|
42
|
-
slug.present?
|
43
|
-
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
42
|
+
class RspecActiveRecordBase < ActiveRecord::Base
|
43
|
+
include SimpleSlug::ModelAddition
|
44
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_slug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Leschenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: 4.0.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '6.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: 4.0.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '6.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: i18n
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,6 +86,20 @@ dependencies:
|
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: sqlite3
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
89
103
|
description: Simple friendly url generator for ActiveRecord with history."
|
90
104
|
email:
|
91
105
|
- leschenko.al@gmail.com
|
@@ -101,6 +115,7 @@ files:
|
|
101
115
|
- Rakefile
|
102
116
|
- db/migrate/20140113000001_create_simple_slug_history_slug.rb
|
103
117
|
- lib/simple_slug.rb
|
118
|
+
- lib/simple_slug/adapter.rb
|
104
119
|
- lib/simple_slug/history_slug.rb
|
105
120
|
- lib/simple_slug/model_addition.rb
|
106
121
|
- lib/simple_slug/railtie.rb
|
@@ -129,8 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
144
|
- !ruby/object:Gem::Version
|
130
145
|
version: '0'
|
131
146
|
requirements: []
|
132
|
-
|
133
|
-
rubygems_version: 2.6.14
|
147
|
+
rubygems_version: 3.0.6
|
134
148
|
signing_key:
|
135
149
|
specification_version: 4
|
136
150
|
summary: Friendly url generator with history.
|