acts_more_seo 0.3.2 → 0.4.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.
data/CHANGELOG.rdoc CHANGED
@@ -19,4 +19,6 @@ Backward compatibility improvements
19
19
  = Version 0.3.1
20
20
  * Dependencies fix
21
21
  = Version 0.3.2
22
- * Downcase fix
22
+ * Downcase fix
23
+ = Version 0.4.0
24
+ * Seo url history support for updating and searching
data/Manifest CHANGED
@@ -7,6 +7,11 @@ Rakefile
7
7
  acts_more_seo.gemspec
8
8
  init.rb
9
9
  lib/acts_more_seo.rb
10
+ lib/generators/acts_more_seo/install_generator.rb
11
+ lib/generators/acts_more_seo/templates/create_seo_history_migration.rb
12
+ lib/seo_finder.rb
13
+ lib/seo_formatter.rb
14
+ lib/seo_history.rb
10
15
  lib/string_ext.rb
11
16
  spec/acts_more_seo_spec.rb
12
17
  spec/spec_helper.rb
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  gem install acts_more_seo
6
6
 
7
7
  and in your Gemfile:
8
-
8
+
9
9
  gem 'acts_more_seo'
10
10
 
11
11
  ## About
@@ -36,7 +36,7 @@ You can also pass an array of columns like this
36
36
  })
37
37
  cool_element_path(mod) ===> cool_elements/12345-maciej-mensfeld-cool-stuff
38
38
 
39
- Further more - if you don't want to use na ID in your urls, just set use_id param to false
39
+ Further more - if you don't want to use an ID in your urls, just set use_id param to false
40
40
 
41
41
  class CoolElement < ActiveRecord::Base
42
42
  acts_more_seo :columns => [:name, :surname, :title], :use_id => false
@@ -45,7 +45,7 @@ Further more - if you don't want to use na ID in your urls, just set use_id para
45
45
  mod = CoolElement.create({
46
46
  :name => 'Maciej',
47
47
  :surname => 'Mensfeld',
48
- :title => 'cool stuuf :)'
48
+ :title => 'cool stuff :)'
49
49
  })
50
50
  cool_element_path(mod) ===> cool_elements/maciej-mensfeld-cool-stuff
51
51
 
@@ -59,8 +59,20 @@ so you can search via seo method:
59
59
 
60
60
  You don't need to update seo_url, gem will hook up with this field automatically if it exists.
61
61
 
62
+ If you want to maintain your urls history, run:
63
+
64
+ rails generate acts_more_seo:install
65
+
66
+ In order to create a SeoHistory table which will contain your urls history. History will be searchable (you don't need to do anything), just inform acts_more_seo that you want to use history:
67
+
68
+ class HisElement < ActiveRecord::Base
69
+ acts_more_seo :column => :name, :use_id => false, :history => true
70
+ end
71
+
72
+ After that, you can use find_by_seo and it will search also though the urls history.
73
+
62
74
  ## Note on Patches/Pull Requests
63
-
75
+
64
76
  * Fork the project.
65
77
  * Make your feature addition or bug fix.
66
78
  * Add tests for it. This is important so I don't break it in a future version unintentionally.
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rubygems'
3
3
  require 'rake'
4
4
  require 'echoe'
5
5
 
6
- Echoe.new('acts_more_seo', '0.3.2') do |p|
6
+ Echoe.new('acts_more_seo', '0.4.0') do |p|
7
7
  p.description = "Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better"
8
8
  p.url = "https://github.com/mensfeld/Css-Image-Embedder"
9
9
  p.author = "Maciej Mensfeld"
@@ -1,22 +1,22 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  Gem::Specification.new do |s|
4
- s.name = %q{acts_more_seo}
5
- s.version = "0.3.2"
4
+ s.name = "acts_more_seo"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
- s.authors = [%q{Maciej Mensfeld}]
9
- s.date = %q{2011-12-17}
10
- s.description = %q{Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better}
11
- s.email = %q{maciej@mensfeld.pl}
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}]
14
- s.homepage = %q{https://github.com/mensfeld/Css-Image-Embedder}
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}]
17
- s.rubyforge_project = %q{acts_more_seo}
18
- s.rubygems_version = %q{1.8.5}
19
- s.summary = %q{Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better}
8
+ s.authors = ["Maciej Mensfeld"]
9
+ s.date = "2012-02-25"
10
+ s.description = "Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better"
11
+ s.email = "maciej@mensfeld.pl"
12
+ s.extra_rdoc_files = ["CHANGELOG.rdoc", "README.md", "lib/acts_more_seo.rb", "lib/generators/acts_more_seo/install_generator.rb", "lib/generators/acts_more_seo/templates/create_seo_history_migration.rb", "lib/seo_finder.rb", "lib/seo_formatter.rb", "lib/seo_history.rb", "lib/string_ext.rb"]
13
+ s.files = ["CHANGELOG.rdoc", "Gemfile", "MIT-LICENSE", "Manifest", "README.md", "Rakefile", "acts_more_seo.gemspec", "init.rb", "lib/acts_more_seo.rb", "lib/generators/acts_more_seo/install_generator.rb", "lib/generators/acts_more_seo/templates/create_seo_history_migration.rb", "lib/seo_finder.rb", "lib/seo_formatter.rb", "lib/seo_history.rb", "lib/string_ext.rb", "spec/acts_more_seo_spec.rb", "spec/spec_helper.rb"]
14
+ s.homepage = "https://github.com/mensfeld/Css-Image-Embedder"
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acts_more_seo", "--main", "README.md"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = "acts_more_seo"
18
+ s.rubygems_version = "1.8.15"
19
+ s.summary = "Gem makes your ActiveRecord models more SEO friendly. Changes URL to look way better"
20
20
 
21
21
  if s.respond_to? :specification_version then
22
22
  s.specification_version = 3
data/lib/acts_more_seo.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  require "babosa"
2
2
  require "string_ext"
3
+ require "seo_formatter"
4
+ require "seo_finder"
5
+ require "seo_history"
3
6
 
4
7
  module Acts
5
8
  module MoreSeo
@@ -16,6 +19,7 @@ module Acts
16
19
 
17
20
  columns = params[:column] || params[:columns] || :name
18
21
  use_id = !params[:use_id].nil? ? params[:use_id] : true
22
+ history = params[:history] || false
19
23
 
20
24
  if columns.is_a?(Array)
21
25
  columns.collect!{|a| a.to_sym}
@@ -25,13 +29,22 @@ module Acts
25
29
 
26
30
  cattr_accessor :seo_columns
27
31
  cattr_accessor :seo_use_id
32
+ cattr_accessor :seo_history
28
33
 
29
34
  before_update :update_seo_url
30
35
  after_create :set_seo_url
31
36
 
32
37
  self.seo_columns = columns
33
-
38
+ self.seo_history = history
34
39
  self.seo_use_id = use_id
40
+
41
+ if self.seo_history
42
+ has_many :seo_histories,
43
+ :as => :seo_historable,
44
+ :dependent => :destroy,
45
+ :class_name => 'Acts::MoreSeo::SeoHistory'
46
+ end
47
+
35
48
  class_eval <<-END
36
49
  include Acts::MoreSeo::InstanceMethods
37
50
  END
@@ -52,9 +65,7 @@ module Acts
52
65
 
53
66
  # Lets return nice and smooth url
54
67
  def to_url
55
- seo_path = seo_text_part
56
- seo_path = "#{self.id}#{"-#{seo_path}" if seo_path && seo_path.length > 0}"
57
- seo_path.length > 0 ? seo_path : "#{self.id}"
68
+ Acts::MoreSeo::SeoFormatter.new(self).to_url
58
69
  end
59
70
  # Alias
60
71
  def url
@@ -62,21 +73,20 @@ module Acts
62
73
  end
63
74
 
64
75
  def to_seo
65
- if self.seo_use_id
66
- to_url
67
- else
68
- seo_link = seo_text_part.length > 0 ? seo_text_part : "#{self.id}"
69
- if !self.class.where("seo_url = ? AND id != ?", seo_link, self.id).limit(1).empty?
70
- to_url
71
- else
72
- seo_link
73
- end
74
- end
76
+ Acts::MoreSeo::SeoFormatter.new(self).to_seo
75
77
  end
76
78
 
77
79
  def update_seo_url
78
80
  if self.class.seo_url_table?
79
- self.update_column(:seo_url, to_seo)
81
+
82
+ new_url = to_seo
83
+
84
+ # Add old url to history if its different from the new one
85
+ if self.class.seo_history? && (new_url != self.seo_url)
86
+ self.seo_histories.create(:seo_url => self.seo_url)
87
+ end
88
+
89
+ self.update_column(:seo_url, new_url)
80
90
  end
81
91
  end
82
92
 
@@ -88,46 +98,24 @@ module Acts
88
98
 
89
99
  module ClassMethods
90
100
 
101
+ def seo_history?
102
+ self.seo_history && !self.seo_use_id
103
+ end
104
+
91
105
  def seo_url_table?
92
106
  self.column_names.include?("#{:seo_url}")
93
107
  end
94
108
 
95
109
  def find_by_seo!(id)
96
- if self.seo_use_id
97
- find(id)
98
- else
99
- find_by_seo_url! id, :first
100
- end
110
+ Acts::MoreSeo::Finder.new(self).search!(id)
101
111
  end
102
112
 
103
113
  def find_by_seo(id)
104
- if self.seo_use_id
105
- find_by_id(id)
106
- else
107
- find_by_seo_url id, :first
108
- end
114
+ Acts::MoreSeo::Finder.new(self).search(id)
109
115
  end
110
116
 
111
117
  end
112
118
 
113
- private
114
-
115
- def seo_text_part
116
- # If there is more than one SEO column - prepare url "text" part
117
- if self.class.seo_columns.is_a?(Array)
118
- seo_parts = self.class.seo_columns.collect do |field|
119
- el = self.send(field)
120
- el.to_url if el
121
- end
122
- seo_parts.delete_if{|el| el.to_s.length == 0}
123
- seo_path = seo_parts.join('-')
124
- else
125
- el = self.send(self.class.seo_columns)
126
- seo_path = el ? el.to_url : ''
127
- end
128
- seo_path
129
- end
130
-
131
119
  end
132
120
  end
133
121
  end
@@ -0,0 +1,13 @@
1
+ module ActsMoreSeo
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ def add_my_migration
6
+ timestamp = Time.now.strftime("%Y%m%d%H%M%S")
7
+ source = "create_seo_history_migration.rb"
8
+ target = "db/migrate/#{timestamp}_create_seo_history_migration.rb"
9
+ copy_file source, target
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ class CreateSeoHistoryMigration < ActiveRecord::Migration
2
+ def self.up
3
+
4
+ create_table :seo_histories do |t|
5
+ t.integer :seo_historable_id
6
+ t.string :seo_historable_type
7
+ t.string :seo_url
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :seo_histories, :seo_historable_id
12
+ add_index :seo_histories, :seo_historable_type
13
+ add_index :seo_histories, :seo_url
14
+ end
15
+
16
+ def self.down
17
+ drop_table :seo_histories
18
+ end
19
+ end
data/lib/seo_finder.rb ADDED
@@ -0,0 +1,63 @@
1
+ module Acts
2
+ module MoreSeo
3
+
4
+ # Used to search for apropriate element in seo_urls or history (if included)
5
+ class Finder
6
+
7
+ def initialize(klass)
8
+ @klass = klass
9
+ end
10
+
11
+ def search(name)
12
+ ret = search_in_table(name)
13
+
14
+ if !ret && @klass.seo_history?
15
+ ret = search_in_history(name)
16
+ end
17
+
18
+ ret
19
+ end
20
+
21
+ def search!(name)
22
+ search_in_table!(name)
23
+ rescue ActiveRecord::RecordNotFound => e
24
+ if @klass.seo_history?
25
+ ret = search_in_history(name)
26
+ return ret if ret
27
+ end
28
+ raise e
29
+ end
30
+
31
+ private
32
+
33
+ # Try to find element in an instance class table
34
+ def search_in_table(name)
35
+ if @klass.seo_use_id
36
+ @klass.find_by_id(name)
37
+ else
38
+ @klass.find_by_seo_url name, :first
39
+ end
40
+ end
41
+
42
+ # Try to find element in an instance class table and raise exception
43
+ # if it failes
44
+ def search_in_table!(name)
45
+ if @klass.seo_use_id
46
+ @klass.find(name)
47
+ else
48
+ @klass.find_by_seo_url! name, :first
49
+ end
50
+ end
51
+
52
+ # Try to find element in its seo history
53
+ def search_in_history(name)
54
+ sql = 'seo_url = ? AND seo_historable_type = ?'
55
+ ret = Acts::MoreSeo::SeoHistory.where(sql, name, @klass.to_s).limit(1).first
56
+ ret = ret.seo_historable if ret
57
+ ret
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,56 @@
1
+ module Acts
2
+ module MoreSeo
3
+
4
+ class SeoFormatter
5
+
6
+ def initialize(instance)
7
+ @instance = instance
8
+ @klass = instance.class
9
+ end
10
+
11
+ def to_url
12
+ seo_path = text_part
13
+ seo_path = "#{@instance.id}#{"-#{seo_path}" if seo_path && seo_path.length > 0}"
14
+ seo_path.length > 0 ? seo_path : "#{@instance.id}"
15
+ end
16
+
17
+ def to_seo
18
+ return @to_seo if @to_seo
19
+
20
+ if @instance.seo_use_id
21
+ @to_seo = to_url
22
+ else
23
+ seo_link = text_part.length > 0 ? text_part : "#{@instance.id}"
24
+ if !@klass.where("seo_url = ? AND id != ?", seo_link, @instance.id).limit(1).empty?
25
+ @to_seo = to_url
26
+ else
27
+ @to_seo = seo_link
28
+ end
29
+ end
30
+ @to_seo
31
+ end
32
+
33
+ private
34
+
35
+ # Prepare text part of a seo url (the one without an id)
36
+ def text_part
37
+ return @seo_path if @seo_path
38
+ # If there is more than one SEO column - prepare url "text" part
39
+ if @klass.seo_columns.is_a?(Array)
40
+ seo_parts = @klass.seo_columns.collect do |field|
41
+ el = @instance.send(field)
42
+ el.to_url if el
43
+ end
44
+ seo_parts.delete_if{|el| el.to_s.length == 0}
45
+ @seo_path = seo_parts.join('-')
46
+ else
47
+ el = @instance.send(@klass.seo_columns)
48
+ @seo_path = el ? el.to_url : ''
49
+ end
50
+ @seo_path
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,12 @@
1
+ module Acts
2
+ module MoreSeo
3
+
4
+ # Store the history of urls if they where changed
5
+ class SeoHistory < ActiveRecord::Base
6
+
7
+ belongs_to :seo_historable, :polymorphic => true
8
+
9
+ end
10
+
11
+ end
12
+ end
@@ -19,6 +19,10 @@ class BestElement < ActiveRecord::Base
19
19
  acts_more_seo :columns => [:name, :surname, :title], :use_id => false
20
20
  end
21
21
 
22
+ class HistorableElement < ActiveRecord::Base
23
+ acts_more_seo :columns => :name, :use_id => false, :history => true
24
+ end
25
+
22
26
  describe CoolElement do
23
27
  subject { CoolElement }
24
28
  before(:each){ subject.destroy_all }
@@ -130,7 +134,6 @@ describe SpecialElement do
130
134
  end
131
135
  end
132
136
 
133
-
134
137
  describe BestElement do
135
138
  subject { BestElement }
136
139
  before(:each){ subject.destroy_all }
@@ -228,3 +231,46 @@ describe BestElement do
228
231
  end
229
232
 
230
233
  end
234
+
235
+ describe HistorableElement do
236
+ subject { HistorableElement }
237
+ before(:each){ subject.destroy_all }
238
+
239
+ context "when we have polish letters" do
240
+ it "should turn them into global and use downcase" do
241
+ a = subject.create(:name => 'Kraj Żelaza')
242
+ a.name.to_url.should == 'kraj-zelaza'
243
+ end
244
+ end
245
+
246
+ context "when there is no name" do
247
+ it "should return only id" do
248
+ a = subject.create
249
+ a.to_param.should eql(a.id.to_s)
250
+ end
251
+ end
252
+
253
+ context "when we change element name" do
254
+ it "should be able to find it via old one also" do
255
+ a = subject.create(:name => 'Kraj Żelaza')
256
+ a.name.to_url.should == 'kraj-zelaza'
257
+
258
+ a.update_attributes(:name => 'Kraj Złota')
259
+ a.reload
260
+ subject.find_by_seo('kraj-zelaza').should eql a
261
+ subject.find_by_seo('kraj-zlota').should eql a
262
+ subject.find_by_seo('kraj-a').should eql nil
263
+ end
264
+
265
+ context "and the new seo_url looks the same as old one" do
266
+ it "should not remember it in history" do
267
+ nr = Acts::MoreSeo::SeoHistory.count
268
+ a = subject.create(:name => 'Kraj Żelaza')
269
+ a.update_attributes(:name => 'Kraj Żelaza')
270
+ nr.should eql Acts::MoreSeo::SeoHistory.count
271
+ end
272
+ end
273
+
274
+ end
275
+
276
+ end
data/spec/spec_helper.rb CHANGED
@@ -40,5 +40,15 @@ ActiveRecord::Schema.define do
40
40
  table.string :surname
41
41
  table.string :seo_url
42
42
  end
43
- end
44
43
 
44
+ create_table :historable_elements do |table|
45
+ table.string :name
46
+ table.string :seo_url
47
+ end
48
+
49
+ create_table :seo_histories do |table|
50
+ table.integer :seo_historable_id
51
+ table.string :seo_historable_type
52
+ table.string :seo_url
53
+ end
54
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_more_seo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-17 00:00:00.000000000Z
12
+ date: 2012-02-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: babosa
16
- requirement: &20403020 !ruby/object:Gem::Requirement
16
+ requirement: &11903760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *20403020
24
+ version_requirements: *11903760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &20402000 !ruby/object:Gem::Requirement
27
+ requirement: &11902800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *20402000
35
+ version_requirements: *11902800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: active_record
38
- requirement: &20401280 !ruby/object:Gem::Requirement
38
+ requirement: &11902200 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *20401280
46
+ version_requirements: *11902200
47
47
  description: Gem makes your ActiveRecord models more SEO friendly. Changes URL to
48
48
  look way better
49
49
  email: maciej@mensfeld.pl
@@ -53,6 +53,11 @@ extra_rdoc_files:
53
53
  - CHANGELOG.rdoc
54
54
  - README.md
55
55
  - lib/acts_more_seo.rb
56
+ - lib/generators/acts_more_seo/install_generator.rb
57
+ - lib/generators/acts_more_seo/templates/create_seo_history_migration.rb
58
+ - lib/seo_finder.rb
59
+ - lib/seo_formatter.rb
60
+ - lib/seo_history.rb
56
61
  - lib/string_ext.rb
57
62
  files:
58
63
  - CHANGELOG.rdoc
@@ -64,6 +69,11 @@ files:
64
69
  - acts_more_seo.gemspec
65
70
  - init.rb
66
71
  - lib/acts_more_seo.rb
72
+ - lib/generators/acts_more_seo/install_generator.rb
73
+ - lib/generators/acts_more_seo/templates/create_seo_history_migration.rb
74
+ - lib/seo_finder.rb
75
+ - lib/seo_formatter.rb
76
+ - lib/seo_history.rb
67
77
  - lib/string_ext.rb
68
78
  - spec/acts_more_seo_spec.rb
69
79
  - spec/spec_helper.rb
@@ -93,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
103
  version: '1.2'
94
104
  requirements: []
95
105
  rubyforge_project: acts_more_seo
96
- rubygems_version: 1.8.5
106
+ rubygems_version: 1.8.15
97
107
  signing_key:
98
108
  specification_version: 3
99
109
  summary: Gem makes your ActiveRecord models more SEO friendly. Changes URL to look