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.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.rvmrc +1 -0
- data/.travis.yml +26 -0
- data/Appraisals +24 -0
- data/README.md +152 -80
- data/Rakefile +14 -1
- data/changelog.md +50 -0
- data/db/schema.rb +22 -15
- data/gemfiles/activerecord_3.2.gemfile +9 -0
- data/gemfiles/activerecord_4.0.gemfile +8 -0
- data/gemfiles/activerecord_4.1.gemfile +8 -0
- data/gemfiles/activerecord_4.2.gemfile +8 -0
- data/lib/slugable.rb +10 -6
- data/lib/slugable/cache_layer.rb +24 -0
- data/lib/slugable/formatter/parameterize.rb +9 -0
- data/lib/slugable/has_slug.rb +99 -168
- data/lib/slugable/railtie.rb +1 -1
- data/lib/slugable/slug_builder/caching_tree_ancestry.rb +16 -0
- data/lib/slugable/slug_builder/flat.rb +24 -0
- data/lib/slugable/slug_builder/tree_ancestry.rb +28 -0
- data/lib/slugable/version.rb +1 -1
- data/slugable.gemspec +14 -12
- data/spec/slugable/cache_layer_spec.rb +35 -0
- data/spec/slugable/has_slug_spec.rb +136 -199
- data/spec/slugable/slugable_builder/caching_tree_ancestry_spec.rb +38 -0
- data/spec/slugable/slugable_builder/flat_spec.rb +42 -0
- data/spec/slugable/slugable_builder/tree_ancestry_spec.rb +55 -0
- data/spec/spec_helper.rb +25 -5
- data/spec/support/hash_cache_storage.rb +27 -0
- data/spec/support/set_up_models.rb +27 -0
- data/spec/support/simple_to_slug.rb +13 -0
- metadata +108 -64
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2b0a37a9a60ba3abef0792c337b76720cefc99ef
|
4
|
+
data.tar.gz: 8c892a3ce4d03dd42cf890d9c122a791e937d690
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 52a1957403eebed9c904e51d9b36b93ed7d5e7e49f0a1b4537ebcb3cf1ee6de480557f57a0f7d6cd3f7c2986c0d86cd4b1a714bfc04a6e67c81aeb6293c818ab
|
7
|
+
data.tar.gz: c4b5b0fe345489617eb9160867122e288b467a707e2b7d2adaf4dcb6b4cd6935f7e9ffd88120ef145b7dae7b1b4433cfd81f6b3a83906937ad63fe1bc0c55454
|
data/.gitignore
CHANGED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-2.2.2@slugable --create
|
data/.travis.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
cache: bundler
|
2
|
+
language: ruby
|
3
|
+
rvm:
|
4
|
+
- 1.9.3
|
5
|
+
- 2.2.2
|
6
|
+
before_install:
|
7
|
+
- rm .rvmrc
|
8
|
+
script:
|
9
|
+
- "bundle exec rspec spec/"
|
10
|
+
sudo: false
|
11
|
+
gemfile:
|
12
|
+
- gemfiles/activerecord_3.2.gemfile
|
13
|
+
- gemfiles/activerecord_4.0.gemfile
|
14
|
+
- gemfiles/activerecord_4.1.gemfile
|
15
|
+
- gemfiles/activerecord_4.2.gemfile
|
16
|
+
matrix:
|
17
|
+
exclude:
|
18
|
+
- rvm: 1.9.3
|
19
|
+
gemfile: gemfiles/activerecord_4.0.gemfile
|
20
|
+
- rvm: 1.9.3
|
21
|
+
gemfile: gemfiles/activerecord_4.1.gemfile
|
22
|
+
- rvm: 1.9.3
|
23
|
+
gemfile: gemfiles/activerecord_4.2.gemfile
|
24
|
+
addons:
|
25
|
+
code_climate:
|
26
|
+
repo_token: 3e779acb537014cbfd1a7c48c7a509d3197afe962cd1738e832a46b439919e24
|
data/Appraisals
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Appraisals
|
2
|
+
appraise "activerecord-3.2" do
|
3
|
+
gem "activerecord", "~> 3.2.1"
|
4
|
+
gem "ancestry", "~> 1.3.0"
|
5
|
+
|
6
|
+
gem "test-unit", "~> 3.0"
|
7
|
+
end
|
8
|
+
|
9
|
+
if RUBY_VERSION > "1.9.3"
|
10
|
+
appraise "activerecord-4.0" do
|
11
|
+
gem "activerecord", "~> 4.0.1"
|
12
|
+
gem "ancestry", "~> 2.1.0"
|
13
|
+
end
|
14
|
+
|
15
|
+
appraise "activerecord-4.1" do
|
16
|
+
gem "activerecord", "~> 4.1.1"
|
17
|
+
gem "ancestry", "~> 2.1.0"
|
18
|
+
end
|
19
|
+
|
20
|
+
appraise "activerecord-4.2" do
|
21
|
+
gem "activerecord", "~> 4.2.1"
|
22
|
+
gem "ancestry", "~> 2.1.0"
|
23
|
+
end
|
24
|
+
end
|
data/README.md
CHANGED
@@ -1,15 +1,39 @@
|
|
1
1
|
# Slugable
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
[](https://travis-ci.org/mirrec/slugable)
|
4
|
+
[](https://badge.fury.io/rb/slugable)
|
5
|
+
[](https://codeclimate.com/github/mirrec/slugable)
|
6
|
+
[](https://codeclimate.com/github/mirrec/slugable/coverage)
|
7
|
+
|
8
|
+
* adds support for creating seo friendly url to your active record models and simplifies generating url
|
9
|
+
* gem is tests against rails 3.2, 4.0, 4.1, 4.2 and ruby 1.9.3. and 2.2.2
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# model
|
13
|
+
class Article < ActiveRecord::Base
|
14
|
+
# has columns: id, name, slug
|
15
|
+
has_slug
|
16
|
+
end
|
17
|
+
|
18
|
+
# creating new
|
19
|
+
item = Article.create!(name: 'First article')
|
20
|
+
item.slug # => 'first-article'
|
21
|
+
item.to_slug # => 'first-article'
|
22
|
+
|
23
|
+
# routes to the article
|
24
|
+
get "articles/:slug" => "articles#show", as: :article
|
25
|
+
|
26
|
+
# view
|
27
|
+
link_to 'My first article', article_path(item.to_slug) # => '/articles/first-article'
|
28
|
+
```
|
7
29
|
|
8
30
|
## Installation
|
9
31
|
|
10
32
|
Add this line to your application's Gemfile:
|
11
33
|
|
12
|
-
|
34
|
+
```ruby
|
35
|
+
gem 'slugable'
|
36
|
+
```
|
13
37
|
|
14
38
|
And then execute:
|
15
39
|
|
@@ -21,91 +45,139 @@ Or install it yourself as:
|
|
21
45
|
|
22
46
|
## Usage
|
23
47
|
|
24
|
-
|
48
|
+
* default configuration converts name column to slug column and formatted by parameterize method from active support
|
49
|
+
* it internally use callbacks to do the job
|
50
|
+
* it also adds several convenient methods for generating url parts `to_slug`, `to_slug_was`, `to_slug_will`
|
25
51
|
|
26
|
-
|
27
|
-
|
52
|
+
```ruby
|
53
|
+
class Item < ActiveRecord::Base
|
54
|
+
# columns :name, :slug
|
28
55
|
|
29
|
-
|
30
|
-
|
56
|
+
has_slug # default from: :name, to: :slug
|
57
|
+
end
|
31
58
|
|
32
|
-
|
33
|
-
|
34
|
-
|
59
|
+
# then in code
|
60
|
+
item = Item.create!(name: "my name is")
|
61
|
+
item.slug # => "my-name-is"
|
35
62
|
|
36
|
-
|
63
|
+
item.to_slug # => "my-name-is"
|
37
64
|
|
38
|
-
|
65
|
+
item.slug = "new-slug"
|
39
66
|
|
40
|
-
|
41
|
-
|
42
|
-
|
67
|
+
item.to_slug_was # => "my-name-is"
|
68
|
+
item.to_slug_will # => "new-slug"
|
69
|
+
item.to_slug # => "new-slug"
|
70
|
+
```
|
43
71
|
|
44
72
|
you can override defaults by passing hash
|
45
73
|
|
74
|
+
```ruby
|
75
|
+
class Page < ActiveRecord::Base
|
76
|
+
# has columns: :id, :title, :seo_url
|
46
77
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
78
|
+
has_slug from: :title, to: :seo_url, formatter: lambda { |string| string.downcase }
|
79
|
+
end
|
80
|
+
|
81
|
+
# then in code
|
82
|
+
page = Page.create!(title: "NAME")
|
83
|
+
page.seo_url # => "name"
|
84
|
+
page.to_seo_url # => "name"
|
85
|
+
```
|
86
|
+
|
87
|
+
if model is a tree structure and you use [ancestry gem](https://github.com/stefankroes/ancestry),
|
88
|
+
tree like structure will be generated
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class Category < ActiveRecord::Base
|
92
|
+
# has columns: :id, :name, :slug
|
93
|
+
|
94
|
+
has_ancestry
|
95
|
+
has_slug
|
96
|
+
end
|
97
|
+
|
98
|
+
# then in code
|
99
|
+
root = Category.create!(name: "root", slug: "root")
|
100
|
+
root.slug # => "root"
|
101
|
+
root.to_slug # => ["root"]
|
102
|
+
|
103
|
+
child = Category.new(name: "child", slug: "child")
|
104
|
+
child.parent = root
|
105
|
+
child.save!
|
106
|
+
|
107
|
+
child.slug # => "child"
|
108
|
+
child.to_slug # => ["root", "child"]
|
109
|
+
|
110
|
+
branch = Category.create!(name: "branch", slug: "branch")
|
111
|
+
child.parent = branch
|
112
|
+
child.slug = "renamed"
|
113
|
+
|
114
|
+
child.to_slug_was # => ["root", "child"]
|
115
|
+
child.to_slug_will # => ["branch", "renamed"]
|
116
|
+
|
117
|
+
child.to_slug # => ["root", "child"]
|
118
|
+
child.save!
|
119
|
+
child.to_slug # => ["branch", "renamed"]
|
120
|
+
```
|
121
|
+
|
122
|
+
* You can cache slug for tree structure if you want to optimize performance, all you need is to pass cache storage object
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
class Category < ActiveRecord::Base
|
126
|
+
# has columns: :id, :name, :slug
|
127
|
+
|
128
|
+
has_ancestry
|
129
|
+
has_slug tree_cache_storage: Rails.cache
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
## Configuration
|
134
|
+
|
135
|
+
You can set up default formatter and default tree_cache_storage in you initializer.
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
class MyFormatter
|
139
|
+
def self.call(string)
|
140
|
+
string.my_own_parameterize
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
Slugable.configure do |config|
|
145
|
+
config.formatter = MyFormatter
|
146
|
+
config.tree_cache_storage = Rails.cache
|
147
|
+
end
|
148
|
+
```
|
149
|
+
|
150
|
+
`to_slug`, `to_slug_was` and `to_slug_will` methods are implemented by to_slug_builder. You can implement you own one and pass as configuration
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
# you own to slug builder
|
154
|
+
class StupidToSlug
|
155
|
+
def to_slug(record)
|
156
|
+
"to_slug_#{record.id}"
|
157
|
+
end
|
158
|
+
|
159
|
+
def to_slug_was(record)
|
160
|
+
"to_slug_was_#{record.id}"
|
161
|
+
end
|
162
|
+
|
163
|
+
def to_slug_will(record)
|
164
|
+
"to_slug_will_#{record.id}"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# model
|
169
|
+
class News < ActiveRecord::Base
|
170
|
+
# columns: :id, :name, :slug
|
171
|
+
|
172
|
+
has_slug to_slug_builder: StupidToSlug.new
|
173
|
+
end
|
174
|
+
|
175
|
+
# code
|
176
|
+
news = News.create!(name: 'whatever')
|
177
|
+
news.to_slug # => "to_slug_#{news.id}"
|
178
|
+
news.to_slug_was # => "to_slug_was_#{news.id}"
|
179
|
+
news.to_slug_will # => "to_slug_will_#{news.id}"
|
180
|
+
```
|
109
181
|
|
110
182
|
## Contributing
|
111
183
|
|
data/Rakefile
CHANGED
@@ -1 +1,14 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'rake'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
|
+
|
10
|
+
begin
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
12
|
+
task :default => :spec
|
13
|
+
rescue LoadError
|
14
|
+
end
|
data/changelog.md
CHANGED
@@ -1,3 +1,53 @@
|
|
1
|
+
# 1.0.0 (November 22, 2015)
|
2
|
+
## added
|
3
|
+
* add ability to pass cache storage to tree structure `tree_cache_storage`
|
4
|
+
* add ability to set default `formatter` and `tree_cache_storage` in config
|
5
|
+
```ruby
|
6
|
+
Slugable.configure do |config|
|
7
|
+
config.formatter = MyFormatter
|
8
|
+
config.tree_cache_storage = Rails.cache
|
9
|
+
end
|
10
|
+
```
|
11
|
+
* introduce slug builder
|
12
|
+
* add ability to pass own slug builder
|
13
|
+
```ruby
|
14
|
+
# you own to slug builder
|
15
|
+
class StupidToSlug
|
16
|
+
def to_slug(record)
|
17
|
+
"to_slug_#{record.id}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_slug_was(record)
|
21
|
+
"to_slug_was_#{record.id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_slug_will(record)
|
25
|
+
"to_slug_will_#{record.id}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# model
|
30
|
+
class News < ActiveRecord::Base
|
31
|
+
# columns: :id, :name, :slug
|
32
|
+
|
33
|
+
has_slug to_slug_builder: StupidToSlug.new
|
34
|
+
end
|
35
|
+
```
|
36
|
+
* travis ci for running tests
|
37
|
+
* tests run against ruby `1.9.3`, `2.2.2` and `activerecord` from >= `3.2` <= `4.2`
|
38
|
+
* test coverage
|
39
|
+
* code climate
|
40
|
+
## changed
|
41
|
+
* big internal refactoring
|
42
|
+
* `formatter` param now expect callable object
|
43
|
+
* `cache_tree` option has been change to `tree_cache_storage` and expect object that can store cache (e.g. Rails.cache), it is `nil` by default
|
44
|
+
* ruby version to `2.2.2`
|
45
|
+
* hash to new syntax
|
46
|
+
* all spec uses expect syntax
|
47
|
+
* `to_slug` method for tree structure now returns array all the time
|
48
|
+
## fixed
|
49
|
+
* several bugs with caching
|
50
|
+
|
1
51
|
# 0.0.4 (May 30, 2013)
|
2
52
|
## fixed
|
3
53
|
* `to_slug` method not skip nil in path
|
data/db/schema.rb
CHANGED
@@ -1,40 +1,47 @@
|
|
1
1
|
ActiveRecord::Schema.define do
|
2
|
-
create_table "
|
2
|
+
create_table "flat_items", force: true do |t|
|
3
3
|
t.string "name"
|
4
4
|
t.string "title"
|
5
5
|
t.string "slug"
|
6
6
|
t.string "seo_url"
|
7
|
-
t.datetime "created_at", :
|
8
|
-
t.datetime "updated_at", :
|
7
|
+
t.datetime "created_at", null: false
|
8
|
+
t.datetime "updated_at", null: false
|
9
9
|
end
|
10
10
|
|
11
|
-
create_table "
|
11
|
+
create_table "flat_pages", force: true do |t|
|
12
12
|
t.string "title"
|
13
13
|
t.string "seo_url"
|
14
|
-
t.datetime "created_at", :
|
15
|
-
t.datetime "updated_at", :
|
14
|
+
t.datetime "created_at", null: false
|
15
|
+
t.datetime "updated_at", null: false
|
16
16
|
end
|
17
17
|
|
18
|
-
create_table "
|
18
|
+
create_table "tree_categories", force: true do |t|
|
19
19
|
t.string "name"
|
20
20
|
t.string "ancestry"
|
21
21
|
t.string "slug"
|
22
|
-
t.datetime "created_at", :
|
23
|
-
t.datetime "updated_at", :
|
22
|
+
t.datetime "created_at", null: false
|
23
|
+
t.datetime "updated_at", null: false
|
24
24
|
end
|
25
25
|
|
26
|
-
create_table "
|
26
|
+
create_table "flat_products", force: true do |t|
|
27
27
|
t.string "name"
|
28
28
|
t.string "slug"
|
29
|
-
t.datetime "created_at", :
|
30
|
-
t.datetime "updated_at", :
|
29
|
+
t.datetime "created_at", null: false
|
30
|
+
t.datetime "updated_at", null: false
|
31
31
|
end
|
32
32
|
|
33
|
-
create_table "tree_items", :
|
33
|
+
create_table "tree_items", force: true do |t|
|
34
34
|
t.string "name"
|
35
35
|
t.string "ancestry"
|
36
36
|
t.string "slug"
|
37
|
-
t.datetime "created_at", :
|
38
|
-
t.datetime "updated_at", :
|
37
|
+
t.datetime "created_at", null: false
|
38
|
+
t.datetime "updated_at", null: false
|
39
|
+
end
|
40
|
+
|
41
|
+
create_table "flat_news", force: true do |t|
|
42
|
+
t.string "name"
|
43
|
+
t.string "slug"
|
44
|
+
t.datetime "created_at", null: false
|
45
|
+
t.datetime "updated_at", null: false
|
39
46
|
end
|
40
47
|
end
|