slugable 0.0.4 → 1.0.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.
@@ -1,3 +1,3 @@
1
1
  module Slugable
2
- VERSION = "0.0.4"
2
+ VERSION = '1.0.0'
3
3
  end
@@ -4,25 +4,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'slugable/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = "slugable"
7
+ gem.name = 'slugable'
8
8
  gem.version = Slugable::VERSION
9
- gem.authors = ["Miroslav Hettes"]
10
- gem.email = ["hettes@webynamieru.sk"]
9
+ gem.authors = ['Miroslav Hettes']
10
+ gem.email = ['hettes@webynamieru.sk']
11
11
  gem.description = %q{Add dsl method for automatic storing seo friendly url in database column}
12
12
  gem.summary = %q{Storing seo friendly url in column}
13
- gem.homepage = "https://github.com/mirrec/slugable"
13
+ gem.homepage = 'https://github.com/mirrec/slugable'
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
18
+ gem.require_paths = ['lib']
19
19
 
20
- gem.add_runtime_dependency "activerecord", ">= 3.0"
21
- gem.add_runtime_dependency "activesupport", ">= 3.0"
22
- gem.add_runtime_dependency "wnm_support", "~> 0.0.4"
20
+ gem.add_runtime_dependency 'activerecord', '>= 3.0', '< 5.0'
23
21
 
24
- gem.add_development_dependency "rspec", "~> 2.11.0"
25
- gem.add_development_dependency "rake", "~> 0.9.2.2"
26
- gem.add_development_dependency "sqlite3", "~> 1.3.6"
27
- gem.add_development_dependency "ancestry", "~> 1.3.0"
22
+ gem.add_development_dependency 'appraisal', '~> 2.1.0'
23
+ gem.add_development_dependency 'rspec', '~> 3.4.0'
24
+ gem.add_development_dependency 'rake', '~> 0.9.2.2'
25
+ gem.add_development_dependency 'sqlite3', '~> 1.3.11'
26
+ gem.add_development_dependency 'ancestry', '>= 1.3.0', '< 3.0'
27
+ gem.add_development_dependency 'pry'
28
+ gem.add_development_dependency 'simplecov'
29
+ gem.add_development_dependency 'codeclimate-test-reporter'
28
30
  end
@@ -0,0 +1,35 @@
1
+ require 'slugable/cache_layer'
2
+ require 'active_support/core_ext/string/inflections'
3
+
4
+ describe Slugable::CacheLayer do
5
+ MyModel = Class.new
6
+
7
+ let(:model) { MyModel }
8
+ let(:cache_storage) { double(:cache_storage) }
9
+
10
+ subject { Slugable::CacheLayer.new(cache_storage, model) }
11
+
12
+ describe '#read_slug' do
13
+ it 'use fetch for reading value for slug from cache storage' do
14
+ allow(cache_storage).to receive(:fetch).with('my_model/slug_column/1').and_return('hello')
15
+
16
+ expect(subject.read_slug(:slug_column, 1)).to eq 'hello'
17
+ end
18
+
19
+ it 'passes block that will be executed if cache storage does not have given value yet' do
20
+ allow(model).to receive(:find).with(1).and_return(double(:record, slug_column: 'hello'))
21
+
22
+ allow(cache_storage).to receive(:fetch).with('my_model/slug_column/1').and_yield
23
+
24
+ expect(subject.read_slug(:slug_column, 1)).to eq 'hello'
25
+ end
26
+ end
27
+
28
+ describe '#update' do
29
+ it 'writes new value to cache storage' do
30
+ expect(cache_storage).to receive(:write).with('my_model/slug_column/1', 'hello')
31
+
32
+ subject.update(:slug_column, 1, 'hello')
33
+ end
34
+ end
35
+ end
@@ -1,280 +1,217 @@
1
- require "spec_helper"
1
+ require 'spec_helper'
2
+ require 'support/hash_cache_storage'
2
3
 
3
- ActiveRecord::Base.send :extend, Slugable::HasSlug
4
+ hash_cache_storage = HashCacheStorage.new
4
5
 
5
- class Item < ActiveRecord::Base
6
- attr_accessible :name, :slug
7
-
8
- has_slug
9
- end
10
-
11
- class Page < ActiveRecord::Base
12
- attr_accessible :title, :seo_url
13
-
14
- has_slug :from => :title, :to => :seo_url
15
- end
16
-
17
- class Category < ActiveRecord::Base
18
- attr_accessible :name, :slug
19
-
20
- has_ancestry
21
- has_slug
22
- end
23
-
24
- class TreeItem < ActiveRecord::Base
25
- attr_accessible :name, :slug
26
-
27
- has_ancestry
28
- has_slug :cache_tree => false
29
- end
30
-
31
- class Product < ActiveRecord::Base
32
- attr_accessible :name, :slug
33
-
34
- has_slug :formatter => :my_formatter
6
+ Slugable.configure do |config|
7
+ config.tree_cache_storage = hash_cache_storage
35
8
  end
36
9
 
10
+ require 'support/set_up_models'
37
11
 
38
12
  describe Slugable::HasSlug do
39
13
  before(:each) do
40
- Category.clear_cached_slugs
14
+ hash_cache_storage.clear
41
15
  end
42
16
 
43
- context "default options" do
44
- it "should create fill_slug_from_name_to_slug" do
45
- Item.new.should respond_to :fill_slug_from_name_to_slug
46
- end
47
-
48
- it "should create format_slug_from_name_to_slug" do
49
- Item.new.should respond_to :format_slug_from_name_to_slug
50
- end
51
-
52
- it "should fill in slug parameter from attribute name and parametrize it" do
53
- name = "my name is"
54
- name.should_receive(:parameterize).and_return("my-name-is")
55
-
56
- item = Item.create!(:name => name)
57
- item.slug.should eq "my-name-is"
58
- end
59
-
60
- it "should fill in slug from attribute name if parameterize version of slug is blank" do
61
- item = Item.create!(:name => "my name is", :slug => "/")
62
- item.slug.should eq "my-name-is"
17
+ context 'method definitions' do
18
+ context 'default options' do
19
+ it 'creates all needed methods for slug' do
20
+ record = FlatItem.new
21
+ expect(record).to respond_to :slug_builder_for_slug
22
+ expect(record).to respond_to :prepare_slug_in_slug
23
+ expect(record).to respond_to :to_slug
24
+ expect(record).to respond_to :to_slug_was
25
+ expect(record).to respond_to :to_slug_will
26
+ end
63
27
  end
64
28
 
65
- it "should only parametrize slug attribute if slug is present" do
66
- item = Item.create!(:name => "my name is", :slug => "my url")
67
- item.slug.should eq "my-url"
29
+ context 'option with cache' do
30
+ it 'creates method that updates cache' do
31
+ record = TreeItem.new
32
+ expect(record).to respond_to :update_my_slug_cache
33
+ end
68
34
  end
69
35
  end
70
36
 
71
- context "given options" do
72
- it "should create fill_slug_from_title_to_seo_url" do
73
- Page.new.should respond_to :fill_slug_from_title_to_seo_url
74
- end
37
+ context 'callbacks' do
38
+ context 'default options' do
39
+ it 'fills in slug parameter from attribute apply a parameterize format to it' do
40
+ name = 'my name is'
75
41
 
76
- it "should create format_slug_from_title_to_seo_url" do
77
- Page.new.should respond_to :format_slug_from_title_to_seo_url
78
- end
79
-
80
- it "should fill in slug parameter from attribute title and parametrize it" do
81
- page = Page.create!(:title => "my name is")
82
- page.seo_url.should eq "my-name-is"
83
- end
42
+ item = FlatItem.create!(name: name)
43
+ expect(item.slug).to eq 'my-name-is'
44
+ end
84
45
 
85
- it "should fill in slug parameter from attribute title if parameterize version of slug is blank" do
86
- page = Page.create!(:title => "my name is", :seo_url => "/")
87
- page.seo_url.should eq "my-name-is"
88
- end
46
+ it 'fills in slug from attribute name if parameterize version of slug is blank' do
47
+ item = FlatItem.create!(name: 'my name is', slug: '')
48
+ expect(item.slug).to eq 'my-name-is'
49
+ end
89
50
 
90
- it "should only parametrize slug attribute if slug is present" do
91
- page = Page.create!(:title => "my name is", :seo_url => "my url")
92
- page.seo_url.should eq "my-url"
51
+ it 'does not change slug attribute if slug is present' do
52
+ item = FlatItem.create!(name: 'my name is', slug: 'my url')
53
+ expect(item.slug).to eq 'my-url'
54
+ end
93
55
  end
94
56
 
95
- it "should be able to change parameterize method" do
96
- name = "product"
97
- name.should_receive(:my_formatter).and_return("hello")
98
- product = Product.create!(:name => "my name is", :slug => name)
99
- product.slug.should eq "hello"
100
- end
57
+ context 'given options' do
58
+ it 'creates fill_slug_from_title_to_seo_url' do
59
+ expect(FlatPage.new).to respond_to :prepare_slug_in_seo_url
60
+ end
101
61
 
102
- it "should be able to disable tree caching" do
103
- tree_item = TreeItem.create!(:name => "my name is", :parent => TreeItem.create!(:name => "root"))
104
- tree_item.should_receive(:path).and_return([])
105
- tree_item.to_slug
106
- tree_item.should_receive(:path).and_return([])
107
- tree_item.to_slug
62
+ it 'fills in slug parameter from attribute title and parametrize it' do
63
+ page = FlatPage.create!(title: 'my name is')
64
+ expect(page.seo_url).to eq 'my-name-is'
65
+ end
108
66
 
109
- tree_item = Category.create!(:name => "my name is", :parent => Category.create!(:name => "root"))
110
- tree_item.should_not_receive(:path)
111
- tree_item.to_slug
67
+ it 'fills in slug parameter and use custom formatter' do
68
+ product = FlatProduct.create!(name: 'my name is', slug: 'product')
69
+ expect(product.slug).to eq 'hello-all-the-time'
70
+ end
112
71
  end
113
72
  end
114
73
 
115
- describe "to_slug" do
116
- context "default options" do
117
- it "should define method to_seo_url" do
118
- Item.new.should respond_to :to_slug
74
+ describe '#to_slug' do
75
+ context 'default options' do
76
+ it 'defines to_slug method' do
77
+ expect(FlatItem.new).to respond_to :to_slug
119
78
  end
120
79
 
121
- it "should return slug in string" do
122
- item = Item.create!(:name => "my name is", :slug => "my-url")
123
- item.to_slug.should eq "my-url"
80
+ it 'returns slug in string' do
81
+ item = FlatItem.create!(name: 'my name is', slug: 'my-url')
82
+ expect(item.to_slug).to eq 'my-url'
124
83
  end
125
84
  end
126
85
 
127
- context "given options" do
128
- it "should define method to_seo_url" do
129
- Page.new.should respond_to :to_seo_url
86
+ context 'given options' do
87
+ it 'defines method to_seo_url' do
88
+ expect(FlatPage.new).to respond_to :to_seo_url
130
89
  end
131
90
 
132
- it "should return slug in string" do
133
- page = Page.create!(:title => "my name is", :seo_url => "my-url")
134
- page.to_seo_url.should eq "my-url"
91
+ it 'returns slug in string' do
92
+ page = FlatPage.create!(title: 'my name is', seo_url: 'my-url')
93
+ expect(page.to_seo_url).to eq 'my-url'
94
+ end
95
+
96
+ it 'returns result from custom to_slug_builder' do
97
+ news = FlatNews.create!(name: 'news')
98
+ expect(news.to_slug).to eq "to_slug_#{news.id}"
135
99
  end
136
100
  end
137
101
 
138
- context "ancestry model" do
139
- it "should return array of slugs" do
140
- root = Category.create!(:name => "root", :slug => "root")
141
- child = Category.new(:name => "child", :slug => "child")
102
+ context 'tree models' do
103
+ it 'returns array of slugs' do
104
+ root = TreeCategory.create!(name: 'root', slug: 'root')
105
+ child = TreeCategory.new(name: 'child', slug: 'child')
142
106
  child.parent = root
143
107
  child.save!
144
108
 
145
- child.to_slug.should eq ["root", "child"]
109
+ expect(child.to_slug).to eq ['root', 'child']
146
110
  end
147
111
 
148
- it "should skip nil values from slug path" do
149
- root = Category.create!(:name => "root", :slug => "root")
150
- child = Category.new(:name => "child", :slug => "child")
112
+ it 'skips nil values from slug path' do
113
+ root = TreeCategory.create!(name: 'root', slug: 'root')
114
+ child = TreeCategory.new(name: 'child', slug: 'child')
151
115
  child.parent = root
152
116
  child.save!
153
117
 
154
- Category.update_all({:slug => nil}, {:id => root.id})
155
- Category.clear_cached_slugs
118
+ TreeCategory.where(id: root.id).update_all(slug: nil)
119
+ hash_cache_storage.clear
120
+
121
+ expect(child.to_slug).to eq ['child']
122
+ end
156
123
 
157
- child.to_slug.should eq ["child"]
124
+ it 'returns correct results also with caching support' do
125
+ child = TreeItem.create!(slug: 'child', parent: TreeItem.create!(slug: 'root'))
126
+ expect(child.to_slug).to eq ['root', 'child']
127
+ expect(child.to_slug).to eq ['root', 'child']
158
128
  end
159
129
  end
160
130
  end
161
131
 
162
- describe "to_slug_was" do
163
- context "default options" do
164
- it "should define method to_slug_was" do
165
- Item.new.should respond_to :to_slug_was
132
+ describe '#to_slug_was' do
133
+ context 'default options' do
134
+ it 'defines method to_slug_was' do
135
+ expect(FlatItem.new).to respond_to :to_slug_was
166
136
  end
167
137
 
168
- it "should return old slug in string" do
169
- item = Item.create!(:name => "my name is", :slug => "my-url")
170
- item.slug = "new-slug"
171
- item.to_slug_was.should eq "my-url"
138
+ it 'returns old slug in string' do
139
+ item = FlatItem.create!(name: 'my name is', slug: 'my-url')
140
+ item.slug = 'new-slug'
141
+ expect(item.to_slug_was).to eq 'my-url'
172
142
  end
173
143
  end
174
144
 
175
- context "given options" do
176
- it "should define method to_seo_url_was" do
177
- Page.new.should respond_to :to_seo_url_was
145
+ context 'given options' do
146
+ it 'defines method to_seo_url_was' do
147
+ expect(FlatPage.new).to respond_to :to_seo_url_was
178
148
  end
179
149
 
180
- it "should return future slug in string" do
181
- page = Page.create!(:title => "my name is", :seo_url => "my-url")
182
- page.seo_url = "hello-world"
183
- page.to_seo_url_was.should eq "my-url"
150
+ it 'returns future slug in string' do
151
+ page = FlatPage.create!(title: 'my name is', seo_url: 'my-url')
152
+ page.seo_url = 'hello-world'
153
+ expect(page.to_seo_url_was).to eq 'my-url'
154
+ end
155
+
156
+ it 'returns result from custom to_slug_builder' do
157
+ news = FlatNews.create!(name: 'news')
158
+ expect(news.to_slug_was).to eq "to_slug_was_#{news.id}"
184
159
  end
185
160
  end
186
161
 
187
- context "ancestry model" do
188
- it "should return array of old slugs" do
189
- root = Category.create!(:name => "root", :slug => "root")
190
- child = Category.new(:name => "child", :slug => "child")
162
+ context 'tree models' do
163
+ it 'returns array of old slugs' do
164
+ root = TreeCategory.create!(name: 'root', slug: 'root')
165
+ child = TreeCategory.new(name: 'child', slug: 'child')
191
166
  child.save!
192
167
 
193
168
  child.parent = root
194
- child.slug = "moved"
195
- child.to_slug_was.should eq ["child"]
169
+ child.slug = 'moved'
170
+ expect(child.to_slug_was).to eq ['child']
196
171
  end
197
172
  end
198
173
  end
199
174
 
200
- describe "to_slug_will" do
201
- context "default options" do
202
- it "should define method to_slug_will" do
203
- Item.new.should respond_to :to_slug_will
175
+ describe '#to_slug_will' do
176
+ context 'default options' do
177
+ it 'defines method to_slug_will' do
178
+ expect(FlatItem.new).to respond_to :to_slug_will
204
179
  end
205
180
 
206
- it "should return future slug in string" do
207
- item = Item.create!(:name => "my name is", :slug => "my-url")
208
- item.slug = "new slug"
209
- item.to_slug_will.should eq "new-slug"
181
+ it 'returns future slug in string' do
182
+ item = FlatItem.create!(name: 'my name is', slug: 'my-url')
183
+ item.slug = 'new slug'
184
+ expect(item.to_slug_will).to eq 'new-slug'
210
185
  end
211
186
  end
212
187
 
213
- context "given options" do
214
- it "should define method to_seo_url_will" do
215
- Page.new.should respond_to :to_seo_url_will
188
+ context 'given options' do
189
+ it 'defines method to_seo_url_will' do
190
+ expect(FlatPage.new).to respond_to :to_seo_url_will
216
191
  end
217
192
 
218
- it "should return slug in string" do
219
- page = Page.create!(:title => "my name is", :seo_url => "my-url")
220
- page.seo_url = "hello world"
221
- page.to_seo_url_will.should eq "hello-world"
193
+ it 'returns slug in string' do
194
+ page = FlatPage.create!(title: 'my name is', seo_url: 'my-url')
195
+ page.seo_url = 'hello world'
196
+ expect(page.to_seo_url_will).to eq 'hello-world'
222
197
  end
223
- end
224
198
 
225
- context "ancestry model" do
226
- it "should return array of slugs" do
227
- root = Category.create!(:name => "root", :slug => "root")
228
- child = Category.new(:name => "child", :slug => "child")
229
- child.save!
230
-
231
- child.parent = root
232
- child.slug = "move d"
233
- child.to_slug_will.should eq ["root", "move-d"]
199
+ it 'returns result from custom to_slug_builder' do
200
+ news = FlatNews.create!(name: 'news')
201
+ expect(news.to_slug_will).to eq "to_slug_will_#{news.id}"
234
202
  end
235
203
  end
236
- end
237
204
 
238
- describe "ancestry methods" do
239
- describe "all_slugs" do
240
- it "ancestry model class should respond to all_slugs" do
241
- Category.should respond_to :all_slugs
242
- end
243
-
244
- it "should return all slugs in hash where key is id and value is slug by itself" do
245
- root = Category.create!(:name => "root", :slug => "root")
246
- child = Category.new(:name => "child", :slug => "child")
247
- child.parent = root
205
+ context 'tree models' do
206
+ it 'returns array of slugs' do
207
+ root = TreeCategory.create!(name: 'root', slug: 'root')
208
+ child = TreeCategory.new(name: 'child', slug: 'child')
248
209
  child.save!
249
210
 
250
- Category.all_slugs.should eq({root.id => "root", child.id => "child"})
251
- end
252
-
253
- it "should update slug cache after save" do
254
- root = Category.create!(:name => "root", :slug => "root")
255
- Category.all_slugs.should eq({root.id => "root"})
256
-
257
- child = Category.new(:name => "child", :slug => "child")
258
- child.save! # force save
259
- Category.all_slugs.should eq({root.id => "root", child.id => "child"})
260
-
261
- child.slug = "updated-child"
262
- child.save # standard save
263
- Category.all_slugs.should eq({root.id => "root", child.id => "updated-child"})
264
- end
265
- end
266
-
267
- describe "clear_cached_slugs" do
268
- it "should clear cache for slug" do
269
- root = Category.create!(:name => "root", :slug => "root")
270
- Category.all_slugs.should eq({root.id => "root"})
271
-
272
- root.destroy
273
- Category.all_slugs.should eq({root.id => "root"})
274
-
275
- Category.clear_cached_slugs
276
- Category.all_slugs.should eq({})
211
+ child.parent = root
212
+ child.slug = 'move d'
213
+ expect(child.to_slug_will).to eq ['root', 'move-d']
277
214
  end
278
215
  end
279
216
  end
280
- end
217
+ end