sluggi 0.1.0 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e34bbe2f4b5982b3866ede14c2df9c616cd2e96
4
- data.tar.gz: 61c5635cd1e788d9d9acadb875abeb0a7a4ab2fd
3
+ metadata.gz: 1d47ac0cb584d36352b4ac43a1e2f7fc7cde0b85
4
+ data.tar.gz: a62c76432d186ab0024492c686fc45cb505f6768
5
5
  SHA512:
6
- metadata.gz: 086b5ecf2710ebf4ed4679b26611e8ba4e500047a184341a7ff4e5658f61f12ebd09d149507f164f837b74542f28a7419c787c04ee2a3a7175f03f593d02ca78
7
- data.tar.gz: 0052170046dc4116492555ab5f0a9d2760637b5123e9ab809f6a8d883224b00a73e79f0c3942fade85a7b19ea501e7ba8eaadbd200098462d882d43f03511e74
6
+ metadata.gz: 7584d82c191aa1c70e35c8ff16c1d0bc39c286340f9a01fb299e9e542b0fe6099bc89c9d55f3bc1147a45bfdf205b9d58d346b58ede60ef2e26e8c418a096ee0
7
+ data.tar.gz: f9740626f5c05f675848f399fecd486f296e957420fb52cb726346e47428915e3a185a71dd84261d7e8b834431ac394c3eb755ef802c9a1a1e40ccd4ce3e8a01
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.2
3
+ - 2.1.4
4
4
  - 2.0.0
5
5
  - 1.9.3
data/README.md CHANGED
@@ -20,13 +20,7 @@ gem 'sluggi'
20
20
  Add a string column named `slug` to any models you want to slug. You can generate a migration like so:
21
21
 
22
22
  ```sh
23
- rails generate migration AddSlugToCats slug:string
24
- ```
25
- ```ruby
26
- # edit the migration to add a unique index:
27
- add_index :cats, :slug, unique: true
28
- ```
29
- ```sh
23
+ rails generate migration AddSlugToCats slug:string:uniq:index
30
24
  rake db:migrate
31
25
  ```
32
26
 
data/lib/sluggi.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  require "sluggi/version"
2
2
  require "sluggi/slug"
3
3
  require "sluggi/history"
4
+ require "sluggi/validate_exclusion_of"
5
+ require "sluggi/validate_presence"
6
+ require "sluggi/validate_uniqueness"
7
+ require "sluggi/model"
4
8
  require "sluggi/slugged"
5
9
  require "sluggi/generators/sluggi_generator"
@@ -3,7 +3,12 @@ module Sluggi
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- has_many :slugs, -> { order('slugs.id DESC') }, class_name: 'Sluggi::Slug', as: :sluggable, dependent: :destroy
6
+ has_many :slugs,
7
+ -> { order('slugs.id DESC') },
8
+ class_name: 'Sluggi::Slug',
9
+ as: :sluggable,
10
+ dependent: :destroy
11
+
7
12
  after_save :create_slug
8
13
  end
9
14
 
@@ -0,0 +1,52 @@
1
+ module Sluggi
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ NOT_IMPLEMENTED_MESSAGE = 'You must implement #slug_value_changed? '\
6
+ 'and either #slug_value or #slug_candidates'.freeze
7
+
8
+ included do
9
+ before_validation :set_slug
10
+ end
11
+
12
+ def to_param
13
+ slug_was
14
+ end
15
+
16
+ private
17
+
18
+ def clean_slug(value)
19
+ value.try :parameterize
20
+ end
21
+
22
+ def set_slug
23
+ return unless new_record? || slug_value_changed?
24
+ new_slug = clean_slug(slug_value)
25
+ return if new_slug.blank?
26
+ self.slug = new_slug
27
+ end
28
+
29
+ # these are generally good to override:
30
+
31
+ def slug_value
32
+ slug_candidates.each do |value|
33
+ next if value.blank?
34
+ candidate = clean_slug(value)
35
+ return candidate if candidate == slug
36
+ return candidate unless self.class.exists?(slug: candidate)
37
+ end
38
+ nil
39
+ end
40
+
41
+ # return an array of candidate slug values
42
+ # Example:
43
+ # [first_name, full_name, id_and_full_name]
44
+ def slug_candidates
45
+ raise NotImplementedError, NOT_IMPLEMENTED_MESSAGE
46
+ end
47
+
48
+ def slug_value_changed?
49
+ raise NotImplementedError, NOT_IMPLEMENTED_MESSAGE
50
+ end
51
+ end
52
+ end
@@ -1,77 +1,11 @@
1
1
  module Sluggi
2
2
  module Slugged
3
3
  extend ActiveSupport::Concern
4
-
5
- RESERVED_SLUGS = %w(
6
- create
7
- edit
8
- index
9
- new
10
- update
11
- admin
12
- assets
13
- images
14
- javascripts
15
- login
16
- logout
17
- stylesheets
18
- session
19
- users
20
- )
21
-
22
- NOT_IMPLEMENTED_MESSAGE = 'You must implement #slug_value_changed? and either #slug_value or #slug_candidates'
23
-
24
4
  included do
25
- before_validation :set_slug
26
- validates :slug, presence: true, uniqueness: true
27
- validates_exclusion_of :slug, in: ->(_) { reserved_slugs }
5
+ include Sluggi::ValidatePresence
6
+ include Sluggi::ValidateUniqueness
7
+ include Sluggi::ValidateExclusionOf
8
+ include Sluggi::Model
28
9
  end
29
-
30
- module ClassMethods
31
- def reserved_slugs
32
- RESERVED_SLUGS
33
- end
34
- end
35
-
36
- def to_param
37
- slug_was
38
- end
39
-
40
- private
41
-
42
- def clean_slug(value)
43
- value.try :parameterize
44
- end
45
-
46
- def set_slug
47
- return unless new_record? || slug_value_changed?
48
- new_slug = clean_slug(slug_value)
49
- return if new_slug.blank?
50
- self.slug = new_slug
51
- end
52
-
53
- # these are generally good to override:
54
-
55
- def slug_value
56
- slug_candidates.each do |value|
57
- next if value.blank?
58
- candidate = clean_slug(value)
59
- return candidate if candidate == slug
60
- return candidate unless self.class.exists?(slug: candidate)
61
- end
62
- nil
63
- end
64
-
65
- # return an array of candidate slug values
66
- # Example:
67
- # [first_name, full_name, id_and_full_name]
68
- def slug_candidates
69
- raise NotImplementedError.new(NOT_IMPLEMENTED_MESSAGE)
70
- end
71
-
72
- def slug_value_changed?
73
- raise NotImplementedError.new(NOT_IMPLEMENTED_MESSAGE)
74
- end
75
-
76
10
  end
77
11
  end
@@ -0,0 +1,32 @@
1
+ module Sluggi
2
+ module ValidateExclusionOf
3
+ extend ActiveSupport::Concern
4
+
5
+ RESERVED_SLUGS = %w(
6
+ admin
7
+ assets
8
+ create
9
+ edit
10
+ images
11
+ index
12
+ javascripts
13
+ login
14
+ logout
15
+ new
16
+ session
17
+ stylesheets
18
+ update
19
+ users
20
+ )
21
+
22
+ included do
23
+ validates_exclusion_of :slug, in: ->(_) { reserved_slugs }
24
+ end
25
+
26
+ module ClassMethods
27
+ def reserved_slugs
28
+ RESERVED_SLUGS
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ module Sluggi
2
+ module ValidatePresence
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validates :slug, presence: true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Sluggi
2
+ module ValidateUniqueness
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validates :slug, uniqueness: true
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Sluggi
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,73 @@
1
+ require "test_helper"
2
+
3
+ class ModelTest < MiniTest::Spec
4
+ class IncompleteCat < ActiveRecord::Base
5
+ self.table_name = 'cats'
6
+ include Sluggi::Model
7
+ end
8
+
9
+ class Cat < ActiveRecord::Base
10
+ include Sluggi::Model
11
+
12
+ def slug_value
13
+ name
14
+ end
15
+
16
+ def slug_value_changed?
17
+ name_changed?
18
+ end
19
+ end
20
+
21
+ class CandidateCat < ActiveRecord::Base
22
+ self.table_name = 'cats'
23
+ include Sluggi::Model
24
+
25
+ def slug_candidates
26
+ [nil, name]
27
+ end
28
+
29
+ def slug_value_changed?
30
+ name_changed?
31
+ end
32
+ end
33
+
34
+ it "raises when slug_value is not implemented" do
35
+ assert_raises(NotImplementedError) do
36
+ IncompleteCat.new.valid?
37
+ end
38
+ end
39
+
40
+ describe "#to_param" do
41
+ before do
42
+ Cat.delete_all
43
+ @cat = Cat.new(name: 'Tuxedo Stan')
44
+ end
45
+
46
+ it "is nil when new" do
47
+ assert_nil @cat.to_param
48
+ end
49
+
50
+ it "is the slug when persisted" do
51
+ @cat.save!
52
+ assert_equal 'tuxedo-stan', @cat.to_param
53
+ end
54
+
55
+ it "is the old slug when changed but not saved" do
56
+ @cat.save!
57
+ @cat.slug = 'ketzel'
58
+ assert_equal 'tuxedo-stan', @cat.to_param
59
+ end
60
+ end
61
+
62
+ it "sets slug from candidates on validation" do
63
+ cat = CandidateCat.new(name: 'Smokey')
64
+ assert cat.valid?
65
+ assert_equal 'smokey', cat.slug
66
+ end
67
+
68
+ it "sets slug on validation" do
69
+ cat = Cat.new(name: 'Prince Chunk')
70
+ assert cat.valid?
71
+ assert_equal 'prince-chunk', cat.slug
72
+ end
73
+ end
data/test/slugged_test.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class SluggedTest < MiniTest::Spec
4
- class ::Cat < ActiveRecord::Base
4
+ class Cat < ActiveRecord::Base
5
5
  include Sluggi::Slugged
6
6
 
7
7
  def slug_value
@@ -13,93 +13,19 @@ class SluggedTest < MiniTest::Spec
13
13
  end
14
14
  end
15
15
 
16
- class ::CandidateCat < ActiveRecord::Base
17
- self.table_name = 'cats'
18
- include Sluggi::Slugged
19
-
20
- def slug_candidates
21
- [nil, name]
22
- end
23
-
24
- def slug_value_changed?
25
- name_changed?
26
- end
27
- end
28
-
29
- class ::IncompleteCat < ActiveRecord::Base
30
- self.table_name = 'cats'
31
- include Sluggi::Slugged
32
- end
33
-
34
- it "raises when slug_value is not implemented" do
35
- assert_raises(NotImplementedError) do
36
- IncompleteCat.new.valid?
37
- end
38
- end
39
-
40
- describe "#to_param" do
41
- before do
42
- Cat.delete_all
43
- @cat = Cat.new(name: 'Tuxedo Stan')
44
- end
45
-
46
- it "is nil when new" do
47
- assert_nil @cat.to_param
48
- end
49
-
50
- it "is the slug when persisted" do
51
- @cat.save!
52
- assert_equal 'tuxedo-stan', @cat.to_param
53
- end
54
-
55
- it "is the old slug when changed but not saved" do
56
- @cat.save!
57
- @cat.slug = 'ketzel'
58
- assert_equal 'tuxedo-stan', @cat.to_param
59
- end
16
+ it "includes ValidatePresence" do
17
+ assert Cat.new.is_a? Sluggi::ValidatePresence
60
18
  end
61
19
 
62
- describe ".reserved_slugs" do
63
- %w(create login users).each do |word|
64
- it "includes #{word}" do
65
- assert_includes Cat.reserved_slugs, word
66
- end
67
- end
68
-
69
- it "does not include valid slug" do
70
- refute_includes Cat.reserved_slugs, 'something'
71
- end
20
+ it "includes ValidateUniqueness" do
21
+ assert Cat.new.is_a? Sluggi::ValidateUniqueness
72
22
  end
73
23
 
74
- describe "validation" do
75
- it "reserved slug is invalid" do
76
- refute Cat.new(name: 'edit').valid?
77
- end
78
-
79
- it "blank slug is invalid" do
80
- refute Cat.new(name: '').valid?
81
- end
82
-
83
- it "sets slug on validation" do
84
- cat = Cat.new(name: 'Prince Chunk')
85
- assert cat.valid?
86
- assert_equal 'prince-chunk', cat.slug
87
- end
88
-
89
- it "is invalid when slug is taken" do
90
- Cat.create(slug: 'mrs-chippy')
91
- cat = Cat.new(name: 'Mrs. Chippy')
92
- refute cat.valid?
93
- assert_nil cat.to_param
94
- end
24
+ it "includes ValidateExclusionOf" do
25
+ assert Cat.new.is_a? Sluggi::ValidateExclusionOf
95
26
  end
96
27
 
97
- describe "candidates" do
98
- it "sets slug from candidates on validation" do
99
- cat = CandidateCat.new(name: 'Smokey')
100
- assert cat.valid?
101
- assert_equal 'smokey', cat.slug
102
- end
28
+ it "includes Model" do
29
+ assert Cat.new.is_a? Sluggi::Model
103
30
  end
104
-
105
31
  end
@@ -0,0 +1,12 @@
1
+ require "test_helper"
2
+
3
+ class ValidatePresenceTest < MiniTest::Spec
4
+ class Cat < ActiveRecord::Base
5
+ include Sluggi::ValidatePresence
6
+ end
7
+
8
+ it "validates presence of slug" do
9
+ refute Cat.new(slug: '').valid?
10
+ assert Cat.new(slug: 'foo').valid?
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ require "test_helper"
2
+
3
+ class ValidateUniquenessTest < MiniTest::Spec
4
+ class Cat < ActiveRecord::Base
5
+ include Sluggi::Model
6
+ include Sluggi::ValidateUniqueness
7
+
8
+ def slug_value
9
+ name
10
+ end
11
+
12
+ def slug_value_changed?
13
+ name_changed?
14
+ end
15
+ end
16
+
17
+ it "validates slug is unique" do
18
+ Cat.create(slug: 'mrs-chippy')
19
+ cat = Cat.new(name: 'Mrs. Chippy')
20
+ refute cat.valid?
21
+ assert_nil cat.to_param
22
+ end
23
+
24
+ end
@@ -0,0 +1,25 @@
1
+ require "test_helper"
2
+
3
+ class ValidatesExclusionOfTest < MiniTest::Spec
4
+ class Cat < ActiveRecord::Base
5
+ include Sluggi::ValidateExclusionOf
6
+ end
7
+
8
+ describe ".reserved_slugs" do
9
+ %w(create login users).each do |word|
10
+ it "includes #{word}" do
11
+ assert_includes Cat.reserved_slugs, word
12
+ end
13
+ end
14
+
15
+ it "does not include valid slug" do
16
+ refute_includes Cat.reserved_slugs, 'something'
17
+ end
18
+ end
19
+
20
+ describe "validation" do
21
+ it "ensures slug is not a reserved word" do
22
+ refute Cat.new(slug: 'edit').valid?
23
+ end
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sluggi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tee Parham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-27 00:00:00.000000000 Z
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -97,15 +97,23 @@ files:
97
97
  - lib/sluggi/generators/sluggi_generator.rb
98
98
  - lib/sluggi/history.rb
99
99
  - lib/sluggi/migrations/create_slugs.rb
100
+ - lib/sluggi/model.rb
100
101
  - lib/sluggi/slug.rb
101
102
  - lib/sluggi/slugged.rb
103
+ - lib/sluggi/validate_exclusion_of.rb
104
+ - lib/sluggi/validate_presence.rb
105
+ - lib/sluggi/validate_uniqueness.rb
102
106
  - lib/sluggi/version.rb
103
107
  - sluggi.gemspec
104
108
  - test/generator_test.rb
105
109
  - test/history_test.rb
110
+ - test/model_test.rb
106
111
  - test/slug_test.rb
107
112
  - test/slugged_test.rb
108
113
  - test/test_helper.rb
114
+ - test/validate_presence_test.rb
115
+ - test/validate_uniqueness_test.rb
116
+ - test/validates_exclusion_of_test.rb
109
117
  homepage: https://github.com/neighborland/sluggi
110
118
  licenses:
111
119
  - MIT
@@ -126,14 +134,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
134
  version: '0'
127
135
  requirements: []
128
136
  rubyforge_project:
129
- rubygems_version: 2.2.2
137
+ rubygems_version: 2.4.4
130
138
  signing_key:
131
139
  specification_version: 4
132
140
  summary: Rails Slug Generator
133
141
  test_files:
134
142
  - test/generator_test.rb
135
143
  - test/history_test.rb
144
+ - test/model_test.rb
136
145
  - test/slug_test.rb
137
146
  - test/slugged_test.rb
138
147
  - test/test_helper.rb
148
+ - test/validate_presence_test.rb
149
+ - test/validate_uniqueness_test.rb
150
+ - test/validates_exclusion_of_test.rb
139
151
  has_rdoc: