slug 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/slug/slug.rb +50 -47
- data/slug.gemspec +1 -1
- data/test/models.rb +3 -0
- data/test/schema.rb +6 -0
- data/test/slug_test.rb +11 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65d6b738a1e306b5803f1b92e8328ed20632eb0d7706eb2417a198bd1acf8bfc
|
4
|
+
data.tar.gz: b1833f858513babd75d2f94ef776831fab3cc2e105ed9df33bf2912c9d7feb5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b46a5b3226a1b4adbdf027fe9c7692d2a33431a5aa0b67ef99edd6297974008789407eee80cd614b8d65a5bfdcbadd6c2112c554e7d79e7198571ccee967a52
|
7
|
+
data.tar.gz: d9e07b0b4b55810ab4eaff7f828755bf0bdf0d5e6744cc8ba866e50e96642db707ee459d0c8b31288ef9978cf82677a386163a646e7eff570662587395996b02
|
data/README.md
CHANGED
@@ -110,6 +110,10 @@ slug and move on.
|
|
110
110
|
* If a slug already exists, Slug will automatically append a '-n' suffix to your slug to make it unique. The second instance of a slug is '-1'.
|
111
111
|
* If you don't like the slug formatting or the accented character stripping doesn't work for you, it's easy to override Slug's formatting functions. Check the source for details.
|
112
112
|
|
113
|
+
## Development
|
114
|
+
|
115
|
+
`rake test` will run the included unit tests.
|
116
|
+
|
113
117
|
## Authors
|
114
118
|
|
115
119
|
Ben Koski, ben.koski@gmail.com
|
data/lib/slug/slug.rb
CHANGED
@@ -36,63 +36,66 @@ module Slug
|
|
36
36
|
with: /\A[a-z0-9-]+\z/,
|
37
37
|
message: "contains invalid characters. Only downcase letters, numbers, and '-' are allowed."
|
38
38
|
before_validation :set_slug, :on => :create
|
39
|
+
|
40
|
+
include SlugInstanceMethods
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
module SlugInstanceMethods
|
45
|
+
# Sets the slug. Called before create.
|
46
|
+
# By default, set_slug won't change slug if one already exists. Pass :force => true to overwrite.
|
47
|
+
def set_slug(opts={})
|
48
|
+
validate_slug_columns
|
49
|
+
return if self[self.slug_column].present? && !opts[:force]
|
47
50
|
|
48
|
-
|
51
|
+
self[self.slug_column] = normalize_slug(self.send(self.slug_source))
|
49
52
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
# if normalize_slug returned a blank string, try the generic_default handling
|
54
|
+
if generic_default && self[self.slug_column].blank?
|
55
|
+
self[self.slug_column] = self.class.to_s.demodulize.underscore.dasherize
|
56
|
+
end
|
54
57
|
|
55
|
-
|
56
|
-
|
58
|
+
assign_slug_sequence if self.changed_attributes.include?(self.slug_column)
|
59
|
+
end
|
57
60
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
# Overwrite existing slug based on current contents of source column.
|
62
|
+
def reset_slug
|
63
|
+
set_slug(:force => true)
|
64
|
+
end
|
62
65
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
# Overrides to_param to return the model's slug.
|
67
|
+
def to_param
|
68
|
+
self[self.slug_column]
|
69
|
+
end
|
67
70
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
private
|
72
|
+
# Validates that source and destination methods exist. Invoked at runtime to allow definition
|
73
|
+
# of source/slug methods after <tt>slug</tt> setup in class.
|
74
|
+
def validate_slug_columns
|
75
|
+
raise ArgumentError, "Source column '#{self.slug_source}' does not exist!" if !self.respond_to?(self.slug_source)
|
76
|
+
raise ArgumentError, "Slug column '#{self.slug_column}' does not exist!" if !self.respond_to?("#{self.slug_column}=")
|
77
|
+
end
|
75
78
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
# Takes the slug, downcases it and replaces non-word characters with a -.
|
80
|
+
# Feel free to override this method if you'd like different slug formatting.
|
81
|
+
def normalize_slug(str)
|
82
|
+
return if str.blank?
|
83
|
+
str.gsub!(/[\p{Pc}\p{Ps}\p{Pe}\p{Pi}\p{Pf}\p{Po}]/, '') # Remove punctuation
|
84
|
+
str.parameterize
|
85
|
+
end
|
83
86
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
87
|
+
# If a slug of the same name already exists, this will append '-n' to the end of the slug to
|
88
|
+
# make it unique. The second instance gets a '-1' suffix.
|
89
|
+
def assign_slug_sequence
|
90
|
+
return if self[self.slug_column].blank?
|
91
|
+
assoc = self.class.base_class
|
92
|
+
base_slug = self[self.slug_column]
|
93
|
+
seq = 0
|
94
|
+
|
95
|
+
while assoc.where(self.slug_column => self[self.slug_column]).exists? do
|
96
|
+
seq += 1
|
97
|
+
self[self.slug_column] = "#{base_slug}-#{seq}"
|
98
|
+
end
|
95
99
|
end
|
96
100
|
end
|
97
|
-
|
98
|
-
end
|
101
|
+
end
|
data/slug.gemspec
CHANGED
data/test/models.rb
CHANGED
data/test/schema.rb
CHANGED
@@ -32,4 +32,10 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
32
32
|
t.column "title", "string"
|
33
33
|
t.column "slug", "string", null: false
|
34
34
|
end
|
35
|
+
|
36
|
+
# table with no slug column
|
37
|
+
create_table "orphans", :force => true do |t|
|
38
|
+
t.column "name", "string"
|
39
|
+
t.column "location", "string"
|
40
|
+
end
|
35
41
|
end
|
data/test/slug_test.rb
CHANGED
@@ -17,6 +17,17 @@ describe Slug do
|
|
17
17
|
assert_equal 'test-event-portland', article.slug
|
18
18
|
end
|
19
19
|
|
20
|
+
it "bases to_param on slug" do
|
21
|
+
article = Article.create!(:headline => 'Test Headline')
|
22
|
+
assert_equal(article.slug, article.to_param)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does not impact lookup of model with no slug column" do
|
26
|
+
orphan = Orphan.create!(:name => 'Oliver')
|
27
|
+
query = orphan.to_param
|
28
|
+
assert_equal(orphan.id.to_s, query)
|
29
|
+
end
|
30
|
+
|
20
31
|
describe "slug column" do
|
21
32
|
it "saves slug to 'slug' column by default" do
|
22
33
|
article = Article.create!(:headline => 'Test Headline')
|