easy-sitemaps 0.0.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 varchar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
File without changes
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = foo
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 varchar. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'tasks/rails'
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "easy-sitemaps"
8
+ gem.summary = %Q{Easy Sitemaps for Rails}
9
+ gem.email = "charlesmbowman@gmail.com"
10
+ gem.homepage = "http://github.com/varchar/foo"
11
+ gem.authors = ["varchar", "robustdj"]
12
+ gem.add_development_dependency "rspec", ">= 1.2.0"
13
+ gem.add_development_dependency "roxml", ">= 3.0"
14
+ gem.add_development_dependency "action_view", ">= 2.3.2"
15
+ gem.add_development_dependency "action_controller", ">= 2.3.2"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/test_*.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+ task :test => :check_dependencies
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "Sitemaps #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ ActiveRecord::Base.send :include, IP::Sitemap::ActiveRecord
2
+ load 'tasks/sitemaps'
@@ -0,0 +1,22 @@
1
+ module IP
2
+ module Sitemap
3
+ module ActiveRecord
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ extend ClassMethods
8
+
9
+ class_inheritable_accessor :sitemap_options
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+ def sitemap(options = {})
15
+ options.reverse_merge(:batch_size => 50000,
16
+ :route => "#{self.class.to_s.underscore}_url")
17
+ self.sitemap_options = options
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,104 @@
1
+ require 'ruby-debug'
2
+ require 'action_view'
3
+ require 'action_controller'
4
+ require 'zlib'
5
+
6
+ module IP
7
+ module Sitemap
8
+
9
+ class RouteMaker
10
+ include Singleton
11
+ include ::ActionController::UrlWriter
12
+ include ::ActionView::Helpers::TextHelper
13
+ include ::ActionView::Helpers::UrlHelper
14
+ include ::ActionView::Helpers::DateHelper
15
+ include ::ActionView::Helpers::TagHelper
16
+ include ::ActionView::Helpers::ActiveRecordHelper
17
+
18
+ def set_host(host)
19
+ self.class.default_url_options[:host] = host
20
+ end
21
+
22
+ end
23
+
24
+ class Processor
25
+
26
+ attr_accessor :urlsets, :output_directory, :host
27
+
28
+ def initialize(output_directory, host)
29
+ self.urlsets = []
30
+ self.output_directory = output_directory
31
+ self.host = host
32
+ end
33
+
34
+ def sitemap_classes
35
+ classes = ::ActiveRecord::Base.send(:subclasses).select{|klass| !klass.sitemap_options.nil? }
36
+ end
37
+
38
+ def process
39
+ batch = 1
40
+ sitemap_classes.each do |klass|
41
+ klass.find_in_batches(:batch_size => klass.sitemap_options[:batch_size]).each do |group|
42
+ xml = process_group(klass, group)
43
+ filename = "/#{klass.to_s.underscore}_urlset_#{batch}.xml"
44
+ filename += '.gz' if klass.sitemap_options[:compress]
45
+ urlsets << filename
46
+ create_file(filename, xml, klass)
47
+ create_index_file
48
+ batch += 1
49
+ end
50
+ end
51
+ end
52
+
53
+ def create_file(filename, xml, klass)
54
+ if klass.sitemap_options[:compress]
55
+ create_gz_file(filename, xml)
56
+ else
57
+ create_xml_file(filename, xml)
58
+ end
59
+ end
60
+
61
+ def create_gz_file(filename, xml)
62
+ ::Zlib::GzipWriter.open(output_directory + filename) do |gz|
63
+ gz.write xml
64
+ end
65
+ end
66
+
67
+ def create_xml_file(filename, xml)
68
+ File.open(output_directory + filename, "w") do |file|
69
+ file << xml
70
+ end
71
+ end
72
+
73
+ def create_index_file
74
+ sitemap_index = IP::Sitemap::SitemapIndex.new
75
+ sitemap_index.sitemaps = []
76
+ urlsets.each do |urlset|
77
+ sitemap = IP::Sitemap::Sitemap.new
78
+ sitemap.loc = host + urlset
79
+ sitemap_index.sitemaps << sitemap
80
+ end
81
+ doc = ROXML::XML::Document.new
82
+ doc.root = sitemap_index.to_xml
83
+ doc.save(output_directory + '/sitemap_index.xml')
84
+ end
85
+
86
+ def process_group(klass, group)
87
+ doc = ROXML::XML::Document.new
88
+ urlset = IP::Sitemap::Urlset.new
89
+ urlset.urls = []
90
+ group.each do |instance|
91
+ url = IP::Sitemap::Url.new
92
+ IP::Sitemap::RouteMaker.instance.set_host(host)
93
+ url.loc = IP::Sitemap::RouteMaker.instance.send(klass.sitemap_options[:route], instance)
94
+ url.lastmod = instance.updated_at.utc.strftime("%Y-%m-%dT%H:%M:%S+00:00")
95
+ url.changefreq = klass.sitemap_options[:changefreq] || 'daily'
96
+ url.priority = klass.sitemap_options[:priority] || instance.try(:priority) || 1
97
+ urlset.urls << url
98
+ end
99
+ doc.root = urlset.to_xml
100
+ doc.to_s
101
+ end
102
+ end
103
+ end
104
+ end
data/lib/ip/urlset.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'roxml'
2
+ module IP
3
+ module Sitemap
4
+
5
+ class Sitemap
6
+ include ROXML
7
+ xml_accessor :loc
8
+ end
9
+
10
+ class Url
11
+ include ROXML
12
+ xml_accessor :loc
13
+ xml_accessor :lastmod, :as => Date
14
+ xml_accessor :changefreq
15
+ xml_accessor :priority, :as => Float
16
+ end
17
+
18
+ class Urlset
19
+ include ROXML
20
+ xml_name :urlset
21
+ xml_accessor :xmlns, :from => '@xmlns'
22
+ xml_accessor :urls, :as => [IP::Sitemap::Url]
23
+
24
+ def xmlns
25
+ "http://www.sitemaps.org/schemas/sitemap/0.9"
26
+ end
27
+ end
28
+
29
+ class SitemapIndex
30
+ include ::ROXML
31
+ xml_name :sitemapindex
32
+ xml_accessor :sitemaps, :as => [IP::Sitemap::Sitemap]
33
+ end
34
+
35
+ end
36
+ end
Binary file
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + './../spec/resources/foo'
2
+ require File.dirname(__FILE__) + './../lib/ip/urlset'
3
+ require File.dirname(__FILE__) + './../lib/ip/processor'
4
+
5
+ describe IP::Sitemap::Processor do
6
+ before(:each) do
7
+ fixture_path = File.dirname(__FILE__) + './../spec/resources'
8
+ @xml = File.read(fixture_path + '/sitemap.xml')
9
+ @processor = IP::Sitemap::Processor.new(File.dirname(__FILE__) + './../spec/resources/public','http://www.insiderpages.com')
10
+ @route_maker = IP::Sitemap::RouteMaker.instance
11
+ @route_maker.stub!(:test_route_url).and_return("foo")
12
+ end
13
+
14
+ it "should have an output directory" do
15
+ @processor.output_directory.should == File.dirname(__FILE__) + './../spec/resources/public'
16
+ end
17
+
18
+ it "should return the urlset for the sitemap class" do
19
+ @processor.process_group(Foo, [Foo.new]).should == "<?xml version=\"1.0\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n <url>\n <loc>foo</loc>\n <lastmod>0012-12-12T00:00:00+00:00</lastmod>\n <changefreq>daily</changefreq>\n <priority>2</priority>\n </url>\n</urlset>\n"
20
+ end
21
+
22
+ it "should generate a file for each batch of urlsets" do
23
+ @processor.stub!(:sitemap_classes).and_return([Foo])
24
+ @processor.process
25
+ @processor.urlsets.should == ["/foo_urlset_1.xml"]
26
+ end
27
+
28
+ it "should write the xml file" do
29
+ @processor.stub!(:sitemap_classes).and_return([Foo])
30
+ @processor.process
31
+ File.exists?(File.dirname(__FILE__) + './../spec/resources/public' + @processor.urlsets.first).should == true
32
+ end
33
+
34
+ it "should generate the sitemap_index file" do
35
+ @processor.stub!(:sitemap_classes).and_return([Foo])
36
+ @processor.process
37
+ File.exists?(File.dirname(__FILE__) + './../spec/resources/public' + '/sitemap_index.xml').should == true
38
+ xml = File.read(File.dirname(__FILE__) + './../spec/resources/public' + '/sitemap_index.xml')
39
+ IP::Sitemap::SitemapIndex.from_xml(xml).sitemaps.first.loc.should == "http://www.insiderpages.com/foo_urlset_1.xml"
40
+ end
41
+
42
+ it "should gzip the urlsets" do
43
+ Foo.sitemap_options[:compress] = true
44
+ @processor.stub!(:sitemap_classes).and_return([Foo])
45
+ @processor.process
46
+ File.exists?(File.dirname(__FILE__) + './../spec/resources/public' + '/foo_urlset_1.xml.gz').should == true
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + './../lib/ip/urlset'
2
+
3
+ describe IP::Sitemap::Urlset do
4
+ before(:each) do
5
+ fixture_path = File.dirname(__FILE__) + './../spec/resources'
6
+ @xml = File.read(fixture_path + '/sitemap.xml')
7
+ end
8
+
9
+ it "#from_xml should parse the sitemap.xml file" do
10
+ urlset = IP::Sitemap::Urlset.from_xml(@xml)
11
+ url = urlset.urls.first
12
+ url.loc.should == 'http://www.example.com/'
13
+ url.lastmod.to_s.should == '2005-01-01'
14
+ url.changefreq.should == 'monthly'
15
+ url.priority.should == 0.8
16
+ end
17
+
18
+ it "#to_xml should create xml" do
19
+ urlset = IP::Sitemap::Urlset.new
20
+ url = IP::Sitemap::Url.new
21
+ url.loc = 'http://www.example.com/'
22
+ url.lastmod = Date.new(2005,1,1)
23
+ url.changefreq = 'monthly'
24
+ url.priority = 0.8
25
+ urlset.urls = [url]
26
+ urlset.to_xml.to_s.should == "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n <url>\n <loc>http://www.example.com/</loc>\n <lastmod>2005-01-01</lastmod>\n <changefreq>monthly</changefreq>\n <priority>0.8</priority>\n </url>\n</urlset>"
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ class Foo
2
+
3
+ def self.sitemap_options
4
+ {:batch_size => 50000, :route => :test_route_url, :priority => 2}
5
+ end
6
+
7
+ def self.find_in_batches(options = {})
8
+ [[Foo.new]]
9
+ end
10
+
11
+ def updated_at
12
+ DateTime.new(12,12,12) # Mon, 12 Dec 0012 00:00:00 +0000
13
+ end
14
+
15
+ end
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url>
4
+ <loc>foo</loc>
5
+ <lastmod>0012-12-12T00:00:00+00:00</lastmod>
6
+ <changefreq>daily</changefreq>
7
+ <priority>2</priority>
8
+ </url>
9
+ </urlset>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0"?>
2
+ <sitemapindex>
3
+ <sitemap>
4
+ <loc>http://www.insiderpages.com/foo_urlset_1.xml</loc>
5
+ </sitemap>
6
+ </sitemapindex>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url>
4
+ <loc>http://www.example.com/</loc>
5
+ <lastmod>2005-01-01</lastmod>
6
+ <changefreq>monthly</changefreq>
7
+ <priority>0.8</priority>
8
+ </url>
9
+ </urlset>
data/tasks/rails.rb ADDED
@@ -0,0 +1,2 @@
1
+ # $VERBOSE = nil
2
+ # Dir["#{Gem.searcher.find('sitemaps').full_gem_path}/tasks/*.rake"].each { |ext| load ext }
@@ -0,0 +1,14 @@
1
+ require File.join(File.dirname(__FILE__), '/../lib/ip/processor')
2
+
3
+ namespace :sitemap do
4
+
5
+ desc "Generates the sitemap"
6
+ task :generate do
7
+ require(File.join(RAILS_ROOT, 'config', 'environment'))
8
+ output_directory = ENV['OUTPUT_DIRECTORY'] || RAILS_ROOT + '/public'
9
+ host = ENV['HOST']
10
+ processor = IP::Sitemap::Processor.new(output_directory, host)
11
+ processor.process
12
+ end
13
+
14
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easy-sitemaps
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - varchar
8
+ - robustdj
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2010-04-01 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 1.2.0
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: roxml
28
+ type: :development
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "3.0"
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: action_view
38
+ type: :development
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.3.2
45
+ version:
46
+ - !ruby/object:Gem::Dependency
47
+ name: action_controller
48
+ type: :development
49
+ version_requirement:
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.3.2
55
+ version:
56
+ description:
57
+ email: charlesmbowman@gmail.com
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ extra_rdoc_files:
63
+ - LICENSE
64
+ - README
65
+ - README.rdoc
66
+ files:
67
+ - LICENSE
68
+ - README
69
+ - README.rdoc
70
+ - Rakefile
71
+ - VERSION
72
+ - init.rb
73
+ - lib/ip/active_record.rb
74
+ - lib/ip/processor.rb
75
+ - lib/ip/urlset.rb
76
+ - pkg/sitemaps-0.0.1.gem
77
+ - spec/ip/processor_spec.rb
78
+ - spec/ip/urlset_spec.rb
79
+ - spec/resources/foo.rb
80
+ - spec/resources/public/foo_urlset_1.xml
81
+ - spec/resources/public/foo_urlset_1.xml.gz
82
+ - spec/resources/public/sitemap_index.xml
83
+ - spec/resources/sitemap.xml
84
+ - tasks/rails.rb
85
+ - tasks/sitemaps.rake
86
+ has_rdoc: true
87
+ homepage: http://github.com/varchar/foo
88
+ licenses: []
89
+
90
+ post_install_message:
91
+ rdoc_options:
92
+ - --charset=UTF-8
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: "0"
100
+ version:
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: "0"
106
+ version:
107
+ requirements: []
108
+
109
+ rubyforge_project:
110
+ rubygems_version: 1.3.5
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Easy Sitemaps for Rails
114
+ test_files:
115
+ - spec/ip/processor_spec.rb
116
+ - spec/ip/urlset_spec.rb
117
+ - spec/resources/foo.rb