acts_more_seo 0.1.1 → 0.2.1

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.
data/CHANGELOG.rdoc CHANGED
@@ -1,2 +1,6 @@
1
1
  = Version 0.1.0
2
2
  * Gem existence started
3
+ = Version 0.2.0
4
+ * Changed API (backward compatibility included)
5
+ * Much better use (without an id in url)
6
+ * Way cooler ;)
data/README.md CHANGED
@@ -14,13 +14,51 @@ Gem makes your ActiveRecord models more SEO friendly. Changes URLs to look way b
14
14
 
15
15
  ## Example
16
16
 
17
+ First of all - remember to make URL fields uniq!
18
+
17
19
  class CoolElement < ActiveRecord::Base
18
20
  acts_more_seo :title
19
21
  end
20
22
 
21
- mod = CoolElement.create(:title => 'cool stuuf :)')
23
+ mod = CoolElement.create({:title => 'cool stuuf :)'})
22
24
  cool_element_path(mod) ===> cool_elements/12345-cool-stuff
23
25
 
26
+ You can also pass an array of columns like this
27
+
28
+ class CoolElement < ActiveRecord::Base
29
+ acts_more_seo :columns => [:name, :surname, :title]
30
+ end
31
+
32
+ mod = CoolElement.create({
33
+ :name => 'Maciej',
34
+ :surname => 'Mensfeld',
35
+ :title => 'cool stuuf :)'
36
+ })
37
+ cool_element_path(mod) ===> cool_elements/12345-maciej-mensfeld-cool-stuff
38
+
39
+ Further more - if you don't want to use na ID in your urls, just set use_id param to false
40
+
41
+ class CoolElement < ActiveRecord::Base
42
+ acts_more_seo :columns => [:name, :surname, :title], :use_id => false
43
+ end
44
+
45
+ mod = CoolElement.create({
46
+ :name => 'Maciej',
47
+ :surname => 'Mensfeld',
48
+ :title => 'cool stuuf :)'
49
+ })
50
+ cool_element_path(mod) ===> cool_elements/maciej-mensfeld-cool-stuff
51
+
52
+ However, if you do so - it is highly recommended to create string seo_url column in your model:
53
+
54
+ add_column :model, :seo_url, :string
55
+
56
+ so you can search via find_by_seo_url method:
57
+
58
+ CoolElement.find_by_seo_url(params[:id])
59
+
60
+ You don't need to update seo_url, gem will hook up with this field automatically if it exists.
61
+
24
62
  ## Note on Patches/Pull Requests
25
63
 
26
64
  * Fork the project.
data/Rakefile CHANGED
@@ -1,8 +1,9 @@
1
+ require 'psych'
1
2
  require 'rubygems'
2
3
  require 'rake'
3
4
  require 'echoe'
4
5
 
5
- Echoe.new('acts_more_seo', '0.1.1') do |p|
6
+ Echoe.new('acts_more_seo', '0.2.1') do |p|
6
7
  p.description = "Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better"
7
8
  p.url = "https://github.com/mensfeld/Css-Image-Embedder"
8
9
  p.author = "Maciej Mensfeld"
@@ -2,22 +2,20 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{acts_more_seo}
5
- s.version = "0.1.1"
5
+ s.version = "0.2.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Maciej Mensfeld"]
9
- s.cert_chain = ["/home/mencio/.cert_keys/gem-public_cert.pem"]
10
- s.date = %q{2011-04-17}
8
+ s.authors = [%q{Maciej Mensfeld}]
9
+ s.date = %q{2011-11-04}
11
10
  s.description = %q{Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better}
12
11
  s.email = %q{maciej@mensfeld.pl}
13
- s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.md", "lib/acts_more_seo.rb", "lib/string_ext.rb"]
14
- s.files = ["CHANGELOG.rdoc", "Gemfile", "MIT-LICENSE", "Manifest", "README.md", "Rakefile", "acts_more_seo.gemspec", "init.rb", "lib/acts_more_seo.rb", "lib/string_ext.rb", "spec/acts_more_seo_spec.rb", "spec/spec_helper.rb"]
12
+ s.extra_rdoc_files = [%q{CHANGELOG.rdoc}, %q{README.md}, %q{lib/acts_more_seo.rb}, %q{lib/string_ext.rb}]
13
+ s.files = [%q{CHANGELOG.rdoc}, %q{Gemfile}, %q{MIT-LICENSE}, %q{Manifest}, %q{README.md}, %q{Rakefile}, %q{acts_more_seo.gemspec}, %q{init.rb}, %q{lib/acts_more_seo.rb}, %q{lib/string_ext.rb}, %q{spec/acts_more_seo_spec.rb}, %q{spec/spec_helper.rb}]
15
14
  s.homepage = %q{https://github.com/mensfeld/Css-Image-Embedder}
16
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acts_more_seo", "--main", "README.md"]
17
- s.require_paths = ["lib"]
15
+ s.rdoc_options = [%q{--line-numbers}, %q{--inline-source}, %q{--title}, %q{Acts_more_seo}, %q{--main}, %q{README.md}]
16
+ s.require_paths = [%q{lib}]
18
17
  s.rubyforge_project = %q{acts_more_seo}
19
- s.rubygems_version = %q{1.5.2}
20
- s.signing_key = %q{/home/mencio/.cert_keys/gem-private_key.pem}
18
+ s.rubygems_version = %q{1.8.5}
21
19
  s.summary = %q{Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better}
22
20
 
23
21
  if s.respond_to? :specification_version then
data/lib/acts_more_seo.rb CHANGED
@@ -3,14 +3,40 @@ require "string_ext"
3
3
  module Acts
4
4
  module MoreSeo
5
5
 
6
+ class NoSeoUrlTable < StandardError; end
7
+
6
8
  def self.included(base)
7
9
  base.extend AddActsAsMethod
8
10
  end
9
11
 
10
12
  module AddActsAsMethod
11
- def acts_more_seo(seo_column = :name)
12
- cattr_accessor :seo_column
13
- self.seo_column = seo_column
13
+ def acts_more_seo(params = {})
14
+ # Backward compatibility
15
+ params = {:column => params} if params.is_a?(String) || params.is_a?(Symbol)
16
+ params = {:columns => params} if params.is_a?(Array)
17
+
18
+ columns = params[:column] || params[:columns] || :name
19
+ use_id = !params[:use_id].nil? ? params[:use_id] : true
20
+
21
+ if columns.is_a?(Array)
22
+ columns.collect!{|a| a.to_sym}
23
+ else
24
+ columns = columns.to_sym
25
+ end
26
+
27
+ if !use_id && !self.column_names.include?("#{:seo_url}")
28
+ raise NoSeoUrlTable , 'Create seo_url table for your model'
29
+ end
30
+
31
+ cattr_accessor :seo_columns
32
+ cattr_accessor :seo_use_id
33
+
34
+ before_update :update_seo_url
35
+ after_create :set_seo_url
36
+
37
+ self.seo_columns = columns
38
+
39
+ self.seo_use_id = use_id
14
40
  class_eval <<-END
15
41
  include Acts::MoreSeo::InstanceMethods
16
42
  END
@@ -20,6 +46,10 @@ module Acts
20
46
  # Istance methods
21
47
  module InstanceMethods
22
48
 
49
+ def self.included(aClass)
50
+ aClass.extend ClassMethods
51
+ end
52
+
23
53
  # Overwrite default to_param - should return nice url
24
54
  def to_param
25
55
  self.url
@@ -27,11 +57,54 @@ module Acts
27
57
 
28
58
  # Lets return nice and smooth url
29
59
  def url
30
- seo = self.send(self.class.seo_column)
31
- seo ? "#{self.id}-#{seo.to_url}" : self.id
60
+ # If there is more than one SEO column - prepare url "text" part
61
+ if self.class.seo_columns.is_a?(Array)
62
+ seo_parts = self.class.seo_columns.collect do |field|
63
+ el = self.send(field)
64
+ el.to_url if el
65
+ end
66
+ seo_parts.delete_if{|el| el.to_s.length == 0}
67
+ seo_path = seo_parts.join('-')
68
+ else
69
+ el = self.send(self.class.seo_columns)
70
+ seo_path = el ? el.to_url : ''
71
+ end
72
+
73
+ if self.class.seo_use_id
74
+ seo_path = "#{self.id}#{"-#{seo_path}" if seo_path && seo_path.length > 0}"
75
+ end
76
+
77
+ seo_path.length > 0 ? seo_path : "#{self.id}"
78
+ end
79
+
80
+ def update_seo_url
81
+ if self.class.seo_url_table?
82
+ self.update_column(:seo_url, self.to_param)
83
+ end
84
+ end
85
+
86
+ def set_seo_url
87
+ if self.class.seo_url_table?
88
+ self.update_column(:seo_url, self.to_param)
89
+ end
32
90
  end
33
91
 
34
92
  module ClassMethods
93
+
94
+ def seo_url_table?
95
+ self.column_names.include?("#{:seo_url}")
96
+ end
97
+
98
+ def find(*args)
99
+ super
100
+ rescue ActiveRecord::RecordNotFound
101
+ if !self.seo_use_id && !(el = find_by_seo_url(args.first, :first)).nil?
102
+ el
103
+ else
104
+ raise ActiveRecord::RecordNotFound
105
+ end
106
+ end
107
+
35
108
  end
36
109
  end
37
110
  end
@@ -11,13 +11,31 @@ class CoolerElement < ActiveRecord::Base
11
11
  acts_more_seo :title
12
12
  end
13
13
 
14
+ class SpecialElement < ActiveRecord::Base
15
+ acts_more_seo :columns => [:name, :surname, :title]
16
+ end
17
+
18
+ class BestElement < ActiveRecord::Base
19
+ acts_more_seo :columns => [:name, :surname, :title], :use_id => false
20
+ end
21
+
14
22
  describe CoolElement do
15
23
  subject { CoolElement }
16
24
 
25
+ context "when we have a class which has use_id => true" do
26
+ it "should find element unless id is corrupted" do
27
+ a = subject.create(:name => 'bla bla bla')
28
+ subject.find(a.id).should eql(a)
29
+ subject.find(a.to_param).should eql(a)
30
+ subject.find("#{a.to_param}aaa").should eql(a)
31
+ lambda { subject.find("134534dass") }.should raise_error(ActiveRecord::RecordNotFound)
32
+ end
33
+ end
34
+
17
35
  context "when there is no name" do
18
36
  it "should return only id" do
19
37
  a = subject.create
20
- a.to_param.should eql(a.id)
38
+ a.to_param.should eql(a.id.to_s)
21
39
  end
22
40
  end
23
41
 
@@ -30,7 +48,7 @@ describe CoolElement do
30
48
  context "and there are some url-not-friendly letters" do
31
49
  it "should remove them and return nice url" do
32
50
  a = subject.create(:name => 'ą')
33
- a.to_param.should eql("#{a.id}-aa")
51
+ a.to_param.should eql("#{a.id}-a")
34
52
  end
35
53
  end
36
54
  end
@@ -42,7 +60,17 @@ describe CoolerElement do
42
60
  context "when there is no name" do
43
61
  it "should return only id" do
44
62
  a = subject.create
45
- a.to_param.should eql(a.id)
63
+ a.to_param.should eql(a.id.to_s)
64
+ end
65
+
66
+ it "should be able to find existing element" do
67
+ a = subject.create
68
+ subject.find(a.id).should eql(a)
69
+ end
70
+
71
+ it "should raise error when there is no element" do
72
+ a = subject.create
73
+ lambda { subject.find(a.id+1) }.should raise_error(ActiveRecord::RecordNotFound)
46
74
  end
47
75
  end
48
76
 
@@ -50,13 +78,106 @@ describe CoolerElement do
50
78
  it "should return nice url" do
51
79
  a = subject.create(:title => 'bla bla bla')
52
80
  a.to_param.should eql("#{a.id}-bla-bla-bla")
81
+ subject.find(a.to_param).should eql(a)
53
82
  end
54
83
 
55
84
  context "and there are some url-not-friendly letters" do
56
85
  it "should remove them and return nice url" do
57
86
  a = subject.create(:title => 'ą')
58
- a.to_param.should eql("#{a.id}-aa")
87
+ a.to_param.should eql("#{a.id}-a")
59
88
  end
60
89
  end
61
90
  end
62
91
  end
92
+
93
+ describe SpecialElement do
94
+ subject { SpecialElement }
95
+
96
+ context "when there is no name" do
97
+ context "but surname and title exists" do
98
+ it "should return nice looking url " do
99
+ a = subject.create({:surname => 'mensfeld', :title => 'test abc'})
100
+ a.to_param.should eql("#{a.id}-mensfeld-test-abc")
101
+ end
102
+ end
103
+
104
+ context "and no other param" do
105
+ it "should return only id" do
106
+ a = subject.create()
107
+ a.to_param.should eql("#{a.id}")
108
+ end
109
+ end
110
+ end
111
+
112
+ context "when there are all the params" do
113
+ it "should return nice url" do
114
+ a = subject.create({:name => 'maciej', :surname => 'mensfeld', :title => 'test abc'})
115
+ a.to_param.should eql("#{a.id}-maciej-mensfeld-test-abc")
116
+ end
117
+ end
118
+ end
119
+
120
+
121
+ describe BestElement do
122
+ subject { BestElement }
123
+
124
+ context "when there is no surname" do
125
+ context "but surname and title exists" do
126
+ it "should return nice looking url " do
127
+ a = subject.create({:name => 'mensfeld', :title => 'test abc'})
128
+ a.to_param.should eql("mensfeld-test-abc")
129
+ a.seo_url.should eql("mensfeld-test-abc")
130
+ end
131
+ end
132
+ end
133
+
134
+ context "when there is no name" do
135
+ context "but surname and title exists" do
136
+ it "should return nice looking url " do
137
+ a = subject.create({:surname => 'mensfeld', :title => 'test abc'})
138
+ a.to_param.should eql("mensfeld-test-abc")
139
+ a.reload
140
+ a.seo_url.should eql("mensfeld-test-abc")
141
+ end
142
+ end
143
+
144
+ context "and no other param" do
145
+ it "should return only id" do
146
+ a = subject.create()
147
+ a.to_param.should eql("#{a.id}")
148
+ a.reload
149
+ a.seo_url.should eql("#{a.id}")
150
+ end
151
+ end
152
+ end
153
+
154
+ context "when there are all the params" do
155
+ it "should return nice url" do
156
+ a = subject.create({:name => 'maciej', :surname => 'mensfeld', :title => 'test abc'})
157
+ a.to_param.should eql("maciej-mensfeld-test-abc")
158
+ a.reload
159
+ a.seo_url.should eql("maciej-mensfeld-test-abc")
160
+ end
161
+ end
162
+
163
+ context "when we have a class which has use_id => false" do
164
+ it "should find element only when seo_url is same (or by id)" do
165
+ a = subject.create(:name => 'bla bla bla')
166
+ subject.find(a.id).should eql(a)
167
+ subject.find(a.to_param).should eql(a)
168
+ lambda { subject.find("#{a.to_param}aaa") }.should raise_error(ActiveRecord::RecordNotFound)
169
+ end
170
+ end
171
+
172
+ context "when updating object" do
173
+ it "should have refreshed seo_url" do
174
+ a = subject.create({:name => 'mensfeld', :title => 'test abc'})
175
+ a.to_param.should eql("mensfeld-test-abc")
176
+ a.name = 'kowalski'
177
+ a.save
178
+ a.to_param.should eql("kowalski-test-abc")
179
+ subject.find("kowalski-test-abc").should eql(a)
180
+ end
181
+ end
182
+
183
+ end
data/spec/spec_helper.rb CHANGED
@@ -21,5 +21,24 @@ ActiveRecord::Schema.define do
21
21
  create_table :cooler_elements do |table|
22
22
  table.string :title
23
23
  end
24
+
25
+ create_table :special_elements do |table|
26
+ table.string :title
27
+ table.string :name
28
+ table.string :surname
29
+ end
30
+
31
+ create_table :better_elements do |table|
32
+ table.string :title
33
+ table.string :name
34
+ table.string :surname
35
+ end
36
+
37
+ create_table :best_elements do |table|
38
+ table.string :title
39
+ table.string :name
40
+ table.string :surname
41
+ table.string :seo_url
42
+ end
24
43
  end
25
44
 
metadata CHANGED
@@ -1,73 +1,49 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: acts_more_seo
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
4
5
  prerelease:
5
- version: 0.1.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Maciej Mensfeld
9
9
  autorequire:
10
10
  bindir: bin
11
- cert_chain:
12
- - |
13
- -----BEGIN CERTIFICATE-----
14
- MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MQ8wDQYDVQQDDAZtYWNp
15
- ZWoxGDAWBgoJkiaJk/IsZAEZFghtZW5zZmVsZDESMBAGCgmSJomT8ixkARkWAnBs
16
- MB4XDTExMDQwOTA5NDcyMloXDTEyMDQwODA5NDcyMlowPzEPMA0GA1UEAwwGbWFj
17
- aWVqMRgwFgYKCZImiZPyLGQBGRYIbWVuc2ZlbGQxEjAQBgoJkiaJk/IsZAEZFgJw
18
- bDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL0+nG3V4/exIeiJ0IN+
19
- wVfq8Utcu4Qpo+58EIVMIu3FiK+8w6MBvatZnUrRu12pqWLw9xrUkCiYeRErD+jF
20
- AmdggIM/tu9CcjvURXH7VeTzOVA+pnV+eJWMD61o8HljFVcb/nyEYYVKErtr9/O4
21
- QrIGv5lnszq1PMj2sBMy2gOP1YnzawncMLmkpp/T5SU4JZ5gAktGMRVz8RxmZzF5
22
- 6NVqFLbuqSRSU5U//WJvZVJt8dycCGgQzBM4Vi3nkOWyjIF0BANf1TqnlU2u6s8d
23
- UK1AoDZfg5feef5e8eqoomHebX1opNGM/SOQhu3LRgax4rJfnl6VS3I2wighohsf
24
- AgcCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUGlrWBqxVieAPk7NEzBDp
25
- kM+iAMMwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAJMoyBaJs8boiz
26
- lFpbw6MWjk+7ZhqoHpFrWEV4nzb5GzyHZ7GU/pa1fSEQR0SCs+LnTLQbAYNQyUTT
27
- O+UsTuA7xzI//v6cSodv3Q9NbfoDlou74xv1NXorWoosQFMpVWrXv+c/1RqU3cq4
28
- WUr+rRiveEXG4tXOwkrpX8KH8xVp2vQZcGw3AXPqhzfqDGzpHd6ws3lk+8HoSrSo
29
- 2L68tDoxraF2Z2toAg9vfFw1+mOeDk1xVIPVcBy3tJxstHfHGHlQuMiRiDQX2b2D
30
- YYU8UWVt2841IwB5Dgl4O+atXhe9ZTBO0W32pl4Bq5CP9lhQRT1KL7sxfznJlF7Y
31
- BH3YFsdk
32
- -----END CERTIFICATE-----
33
-
34
- date: 2011-04-17 00:00:00 +02:00
35
- default_executable:
36
- dependencies:
37
- - !ruby/object:Gem::Dependency
11
+ cert_chain: []
12
+ date: 2011-11-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
38
15
  name: rspec
39
- prerelease: false
40
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &12118440 !ruby/object:Gem::Requirement
41
17
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
45
21
  version: 2.0.0
46
22
  type: :development
47
- version_requirements: *id001
48
- - !ruby/object:Gem::Dependency
49
- name: active_record
50
23
  prerelease: false
51
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *12118440
25
+ - !ruby/object:Gem::Dependency
26
+ name: active_record
27
+ requirement: &12117940 !ruby/object:Gem::Requirement
52
28
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: "0"
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
57
33
  type: :development
58
- version_requirements: *id002
59
- description: Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better
34
+ prerelease: false
35
+ version_requirements: *12117940
36
+ description: Gem makes your ActiveRecord models more SEO friendly. Changes URL to
37
+ look way better
60
38
  email: maciej@mensfeld.pl
61
39
  executables: []
62
-
63
40
  extensions: []
64
-
65
- extra_rdoc_files:
41
+ extra_rdoc_files:
66
42
  - CHANGELOG.rdoc
67
43
  - README.md
68
44
  - lib/acts_more_seo.rb
69
45
  - lib/string_ext.rb
70
- files:
46
+ files:
71
47
  - CHANGELOG.rdoc
72
48
  - Gemfile
73
49
  - MIT-LICENSE
@@ -80,38 +56,35 @@ files:
80
56
  - lib/string_ext.rb
81
57
  - spec/acts_more_seo_spec.rb
82
58
  - spec/spec_helper.rb
83
- has_rdoc: true
84
59
  homepage: https://github.com/mensfeld/Css-Image-Embedder
85
60
  licenses: []
86
-
87
61
  post_install_message:
88
- rdoc_options:
62
+ rdoc_options:
89
63
  - --line-numbers
90
64
  - --inline-source
91
65
  - --title
92
66
  - Acts_more_seo
93
67
  - --main
94
68
  - README.md
95
- require_paths:
69
+ require_paths:
96
70
  - lib
97
- required_ruby_version: !ruby/object:Gem::Requirement
71
+ required_ruby_version: !ruby/object:Gem::Requirement
98
72
  none: false
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: "0"
103
- required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
78
  none: false
105
- requirements:
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- version: "1.2"
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
109
83
  requirements: []
110
-
111
84
  rubyforge_project: acts_more_seo
112
- rubygems_version: 1.5.2
85
+ rubygems_version: 1.8.5
113
86
  signing_key:
114
87
  specification_version: 3
115
- summary: Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better
88
+ summary: Gem makes your ActiveRecord models more SEO friendly. Changes URL to look
89
+ way better
116
90
  test_files: []
117
-
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
@@ -1 +0,0 @@
1
- A 1/ɐ����a��o��f���9������[&�&ƫ{���_�JV�O7}�bƢ�O���{�΢��