acts_more_seo 0.1.1 → 0.2.1

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