sluggi 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: