dynamic_sitemaps 2.0.0.beta → 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.travis.yml +8 -0
- data/README.md +230 -55
- data/TODO.md +7 -0
- data/dynamic_sitemaps.gemspec +3 -0
- data/lib/dynamic_sitemaps.rb +44 -19
- data/lib/dynamic_sitemaps/generator.rb +94 -40
- data/lib/dynamic_sitemaps/index_generator.rb +2 -2
- data/lib/dynamic_sitemaps/logger.rb +22 -0
- data/lib/dynamic_sitemaps/pinger.rb +12 -7
- data/lib/dynamic_sitemaps/sitemap.rb +1 -9
- data/lib/dynamic_sitemaps/sitemap_generator.rb +7 -2
- data/lib/dynamic_sitemaps/tasks/sitemap.rake +2 -6
- data/lib/dynamic_sitemaps/version.rb +1 -1
- data/lib/generators/dynamic_sitemaps/templates/config.rb +3 -0
- data/test/dummy/app/models/product.rb +5 -1
- data/test/dummy/config/routes.rb +5 -56
- data/test/dummy/config/sitemap.rb +5 -0
- data/test/dummy/db/migrate/20130211190343_create_products.rb +1 -3
- data/test/dummy/db/schema.rb +3 -5
- data/test/dynamic_sitemaps_test.rb +49 -2
- data/test/generator_test.rb +404 -0
- data/test/pinger_test.rb +73 -0
- data/test/test_helper.rb +1 -0
- metadata +53 -12
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +0 -902
- data/test/dummy/log/test.log +0 -10
@@ -1,58 +1,112 @@
|
|
1
1
|
module DynamicSitemaps
|
2
2
|
class Generator
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# Generates the sitemap(s) and index based on the configuration file specified in DynamicSitemaps.config_path.
|
4
|
+
# If you supply a block, that block is evaluated instead of the configuration file.
|
5
|
+
def generate(&block)
|
6
|
+
create_temp_dir
|
7
|
+
if block
|
8
|
+
instance_eval &block
|
9
|
+
else
|
10
|
+
instance_eval open(DynamicSitemaps.config_path).read, DynamicSitemaps.config_path
|
7
11
|
end
|
12
|
+
generate_index
|
13
|
+
move_to_destination
|
14
|
+
ping_search_engines
|
15
|
+
ensure
|
16
|
+
remove_temp_dir
|
17
|
+
end
|
8
18
|
|
9
|
-
|
10
|
-
|
11
|
-
|
19
|
+
def generate_index
|
20
|
+
IndexGenerator.new(sitemaps).generate
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_temp_dir
|
24
|
+
remove_temp_dir
|
25
|
+
FileUtils.mkdir_p DynamicSitemaps.temp_path
|
26
|
+
end
|
27
|
+
|
28
|
+
def remove_temp_dir
|
29
|
+
FileUtils.rm_rf DynamicSitemaps.temp_path
|
30
|
+
end
|
12
31
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
32
|
+
def move_to_destination
|
33
|
+
sitemaps.map(&:folder).uniq.each do |folder|
|
34
|
+
destination = "#{DynamicSitemaps.path}/#{folder}"
|
35
|
+
FileUtils.mkdir_p destination
|
36
|
+
FileUtils.rm_rf Dir.glob("#{destination}/*")
|
37
|
+
FileUtils.mv Dir["#{DynamicSitemaps.temp_path}/#{folder}/*"], destination
|
19
38
|
end
|
39
|
+
remove_temp_dir
|
40
|
+
end
|
20
41
|
|
21
|
-
|
22
|
-
|
42
|
+
def ping_search_engines
|
43
|
+
Pinger.ping_search_engines_with ping_urls
|
44
|
+
end
|
23
45
|
|
24
|
-
|
25
|
-
|
46
|
+
def sitemap(*args, &block)
|
47
|
+
args << {} unless args.last.is_a?(Hash)
|
48
|
+
args.last[:host] ||= host
|
49
|
+
args.last[:folder] ||= folder
|
50
|
+
sitemap = Sitemap.new(*args, &block)
|
26
51
|
|
27
|
-
|
28
|
-
|
52
|
+
ensure_valid_sitemap_name! sitemap
|
53
|
+
sitemap_names[sitemap.folder] << sitemap.name
|
29
54
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
55
|
+
sitemaps << SitemapGenerator.new(sitemap).generate
|
56
|
+
end
|
57
|
+
|
58
|
+
def sitemap_for(collection, options = {}, &block)
|
59
|
+
raise ArgumentError, "The collection given to `sitemap_for` must respond to #find_each. This is for performance. Use `Model.scoped` to get an ActiveRecord relation that responds to #find_each." unless collection.respond_to?(:find_each)
|
34
60
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
61
|
+
name = options.delete(:name) || collection.model_name.underscore.pluralize.to_sym
|
62
|
+
options[:collection] = collection
|
63
|
+
|
64
|
+
sitemap(name, options, &block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def ensure_valid_sitemap_name!(sitemap)
|
68
|
+
raise ArgumentError, "Sitemap name :#{sitemap.name} has already been defined for the folder \"#{sitemap.folder}\". Please use `sitemap :other_name do ... end` or `sitemap_for <relation>, name: :other_name`." if sitemap_names[sitemap.folder].include?(sitemap.name)
|
69
|
+
raise ArgumentError, "Sitemap name :#{sitemap.name} conflicts with the index file name #{DynamicSitemaps.index_file_name}. Please change it using `sitemap :other_name do ... end`." if "#{sitemap.name}.xml" == DynamicSitemaps.index_file_name
|
70
|
+
end
|
71
|
+
|
72
|
+
# Array of SitemapResult
|
73
|
+
def sitemaps
|
74
|
+
@sitemaps ||= []
|
75
|
+
end
|
76
|
+
|
77
|
+
# Generated sitemap names
|
78
|
+
def sitemap_names
|
79
|
+
@sitemap_names ||= Hash.new { |h, k| h[k] = [] }
|
80
|
+
end
|
81
|
+
|
82
|
+
# URLs to ping after generation
|
83
|
+
def ping_urls
|
84
|
+
@ping_urls ||= []
|
85
|
+
end
|
86
|
+
|
87
|
+
def host(*args)
|
88
|
+
if args.any?
|
89
|
+
@host = args.first
|
90
|
+
Rails.application.routes.default_url_options[:host] = @host
|
91
|
+
else
|
92
|
+
@host
|
42
93
|
end
|
94
|
+
end
|
43
95
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
96
|
+
# Adds a sitemap URL to ping search engines with after generation.
|
97
|
+
def ping_with(sitemap_url)
|
98
|
+
ping_urls << sitemap_url
|
99
|
+
end
|
48
100
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
101
|
+
def folder(*args)
|
102
|
+
if args.any?
|
103
|
+
@folder = args.first
|
104
|
+
raise ArgumentError, "Folder can't be blank." if @folder.blank?
|
105
|
+
else
|
106
|
+
# Ensure that the default folder is set and cleaned.
|
107
|
+
folder DynamicSitemaps.folder if @folder.blank?
|
53
108
|
|
54
|
-
|
55
|
-
end
|
109
|
+
@folder
|
56
110
|
end
|
57
111
|
end
|
58
112
|
end
|
@@ -9,10 +9,10 @@ module DynamicSitemaps
|
|
9
9
|
|
10
10
|
def generate
|
11
11
|
sitemaps.group_by(&:folder).each do |folder, sitemaps|
|
12
|
-
index_path = "#{DynamicSitemaps.
|
12
|
+
index_path = "#{DynamicSitemaps.temp_path}/#{folder}/#{DynamicSitemaps.index_file_name}"
|
13
13
|
|
14
14
|
if !DynamicSitemaps.always_generate_index && sitemaps.count == 1 && sitemaps.first.files.count == 1
|
15
|
-
file_path = "#{DynamicSitemaps.
|
15
|
+
file_path = "#{DynamicSitemaps.temp_path}/#{folder}/#{sitemaps.first.files.first}"
|
16
16
|
FileUtils.copy file_path, index_path
|
17
17
|
File.delete file_path
|
18
18
|
else
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module DynamicSitemaps
|
2
|
+
class Logger
|
3
|
+
class << self
|
4
|
+
def info(message)
|
5
|
+
show message
|
6
|
+
Rails.logger.info message
|
7
|
+
end
|
8
|
+
|
9
|
+
def warn(message)
|
10
|
+
show message
|
11
|
+
Rails.logger.warn message
|
12
|
+
end
|
13
|
+
|
14
|
+
# Shows the message using puts unless testing.
|
15
|
+
def show(message)
|
16
|
+
unless Rails.env.test?
|
17
|
+
puts message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module DynamicSitemaps
|
2
2
|
class Pinger
|
3
3
|
class << self
|
4
|
-
def
|
5
|
-
sitemap_urls =
|
6
|
-
|
7
|
-
|
4
|
+
def ping_search_engines_with(sitemap_urls)
|
5
|
+
sitemap_urls = [sitemap_urls] unless sitemap_urls.is_a?(Array)
|
6
|
+
|
7
|
+
if sitemap_urls.any? && ping_for_environment?(Rails.env)
|
8
|
+
Logger.info "Pinging search engines..."
|
8
9
|
|
9
10
|
sitemap_urls.each do |url|
|
10
11
|
ping_search_engines_with_sitemap_url url
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
+
Logger.info "Done pinging search engines."
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -23,13 +24,17 @@ module DynamicSitemaps
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def ping(url)
|
26
|
-
|
27
|
+
Logger.info "Pinging #{url} ..."
|
27
28
|
begin
|
28
29
|
Net::HTTP.get(URI.parse(url))
|
29
30
|
rescue Exception => e
|
30
|
-
|
31
|
+
Logger.warn "Failed to ping #{url} : #{e}"
|
31
32
|
end
|
32
33
|
end
|
34
|
+
|
35
|
+
def ping_for_environment?(env)
|
36
|
+
DynamicSitemaps.ping_environments.map(&:to_s).include?(env.to_s)
|
37
|
+
end
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|
@@ -7,14 +7,6 @@ module DynamicSitemaps
|
|
7
7
|
# Sitemap.new(:site) do
|
8
8
|
# url root_url
|
9
9
|
# end
|
10
|
-
#
|
11
|
-
# Using an ActiveRecord relation:
|
12
|
-
#
|
13
|
-
# Sitemap.new(:site, Product.visible) do |product|
|
14
|
-
# url product
|
15
|
-
# url product_editions_path(product)
|
16
|
-
# end
|
17
|
-
|
18
10
|
def initialize(*args, &block)
|
19
11
|
if args.first.is_a?(Symbol)
|
20
12
|
@name = args.shift
|
@@ -36,7 +28,7 @@ module DynamicSitemaps
|
|
36
28
|
end
|
37
29
|
|
38
30
|
def per_page
|
39
|
-
@per_page ||= DynamicSitemaps
|
31
|
+
@per_page ||= DynamicSitemaps.per_page
|
40
32
|
end
|
41
33
|
|
42
34
|
# Generates sitemap XML files based on this sitemap
|
@@ -11,6 +11,7 @@ module DynamicSitemaps
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def generate
|
14
|
+
ensure_host!
|
14
15
|
write_beginning
|
15
16
|
write_urls
|
16
17
|
write_end
|
@@ -95,7 +96,7 @@ module DynamicSitemaps
|
|
95
96
|
end
|
96
97
|
|
97
98
|
def folder_path
|
98
|
-
"#{DynamicSitemaps.
|
99
|
+
"#{DynamicSitemaps.temp_path}/#{folder}"
|
99
100
|
end
|
100
101
|
|
101
102
|
def path
|
@@ -106,6 +107,10 @@ module DynamicSitemaps
|
|
106
107
|
sitemap.host
|
107
108
|
end
|
108
109
|
|
110
|
+
def ensure_host!
|
111
|
+
raise "No host specified. Please specify a host using `host \"www.mydomain.com\"` at the top of your sitemap configuration file." if sitemap.host.blank?
|
112
|
+
end
|
113
|
+
|
109
114
|
def file
|
110
115
|
@file ||= begin
|
111
116
|
files << file_name
|
@@ -146,7 +151,7 @@ module DynamicSitemaps
|
|
146
151
|
if date.is_a?(Date)
|
147
152
|
date.strftime("%Y-%m-%d")
|
148
153
|
else
|
149
|
-
date.to_datetime.strftime("%Y-%m-%dT%H:%M:%S%:z")
|
154
|
+
date.to_datetime.utc.strftime("%Y-%m-%dT%H:%M:%S%:z")
|
150
155
|
end
|
151
156
|
end
|
152
157
|
end
|
@@ -1,12 +1,8 @@
|
|
1
1
|
namespace :sitemap do
|
2
2
|
task :generate => :environment do
|
3
3
|
start_time = Time.now
|
4
|
-
|
4
|
+
DynamicSitemaps::Logger.info "Generating sitemap..."
|
5
5
|
DynamicSitemaps.generate_sitemap
|
6
|
-
|
7
|
-
|
8
|
-
if Rails.env.production?
|
9
|
-
DynamicSitemaps::Pinger.ping_search_engines
|
10
|
-
end
|
6
|
+
DynamicSitemaps::Logger.info "Done generating sitemap in #{Time.now - start_time} seconds."
|
11
7
|
end
|
12
8
|
end
|
data/test/dummy/config/routes.rb
CHANGED
@@ -1,58 +1,7 @@
|
|
1
1
|
Dummy::Application.routes.draw do
|
2
|
-
|
3
|
-
# first created -> highest priority.
|
2
|
+
root to: "home#index"
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# Sample of named route:
|
10
|
-
# match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
|
11
|
-
# This route can be invoked with purchase_url(:id => product.id)
|
12
|
-
|
13
|
-
# Sample resource route (maps HTTP verbs to controller actions automatically):
|
14
|
-
# resources :products
|
15
|
-
|
16
|
-
# Sample resource route with options:
|
17
|
-
# resources :products do
|
18
|
-
# member do
|
19
|
-
# get 'short'
|
20
|
-
# post 'toggle'
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# collection do
|
24
|
-
# get 'sold'
|
25
|
-
# end
|
26
|
-
# end
|
27
|
-
|
28
|
-
# Sample resource route with sub-resources:
|
29
|
-
# resources :products do
|
30
|
-
# resources :comments, :sales
|
31
|
-
# resource :seller
|
32
|
-
# end
|
33
|
-
|
34
|
-
# Sample resource route with more complex sub-resources
|
35
|
-
# resources :products do
|
36
|
-
# resources :comments
|
37
|
-
# resources :sales do
|
38
|
-
# get 'recent', :on => :collection
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
|
42
|
-
# Sample resource route within a namespace:
|
43
|
-
# namespace :admin do
|
44
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
45
|
-
# # (app/controllers/admin/products_controller.rb)
|
46
|
-
# resources :products
|
47
|
-
# end
|
48
|
-
|
49
|
-
# You can have the root of your site routed with "root"
|
50
|
-
# just remember to delete public/index.html.
|
51
|
-
# root :to => 'welcome#index'
|
52
|
-
|
53
|
-
# See how all your routes lay out with "rake routes"
|
54
|
-
|
55
|
-
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
56
|
-
# Note: This route will make all actions in every controller accessible via GET requests.
|
57
|
-
# match ':controller(/:action(/:id))(.:format)'
|
58
|
-
end
|
4
|
+
resources :products do
|
5
|
+
resources :comments
|
6
|
+
end
|
7
|
+
end
|
data/test/dummy/db/schema.rb
CHANGED
@@ -14,12 +14,10 @@
|
|
14
14
|
ActiveRecord::Schema.define(:version => 20130211190343) do
|
15
15
|
|
16
16
|
create_table "products", :force => true do |t|
|
17
|
-
t.
|
17
|
+
t.boolean "featured", :default => false
|
18
18
|
t.string "slug"
|
19
|
-
t.datetime "created_at",
|
20
|
-
t.datetime "updated_at",
|
19
|
+
t.datetime "created_at", :null => false
|
20
|
+
t.datetime "updated_at", :null => false
|
21
21
|
end
|
22
22
|
|
23
|
-
add_index "products", ["slug"], :name => "index_products_on_slug"
|
24
|
-
|
25
23
|
end
|
@@ -1,7 +1,54 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class DynamicSitemapsTest < ActiveSupport::TestCase
|
4
|
-
|
5
|
-
|
4
|
+
setup do
|
5
|
+
DynamicSitemaps.reset!
|
6
|
+
end
|
7
|
+
|
8
|
+
test "defaults" do
|
9
|
+
assert_equal Rails.root.join("public").to_s, DynamicSitemaps.path
|
10
|
+
assert_equal "sitemaps", DynamicSitemaps.folder
|
11
|
+
assert_equal "sitemap.xml", DynamicSitemaps.index_file_name
|
12
|
+
assert !DynamicSitemaps.always_generate_index
|
13
|
+
assert_equal Rails.root.join("config", "sitemap.rb").to_s, DynamicSitemaps.config_path
|
14
|
+
assert_equal 50000, DynamicSitemaps.per_page
|
15
|
+
assert_equal ["production"], DynamicSitemaps.ping_environments
|
16
|
+
assert_equal Rails.root.join("tmp", "dynamic_sitemaps").to_s, DynamicSitemaps.temp_path
|
17
|
+
end
|
18
|
+
|
19
|
+
test "configuration block" do
|
20
|
+
DynamicSitemaps.configure do |config|
|
21
|
+
config.folder = "mycustomfolder"
|
22
|
+
config.per_page = 1234
|
23
|
+
end
|
24
|
+
|
25
|
+
assert_equal "mycustomfolder", DynamicSitemaps.folder
|
26
|
+
assert_equal 1234, DynamicSitemaps.per_page
|
27
|
+
end
|
28
|
+
|
29
|
+
test "raises error on blank paths" do
|
30
|
+
assert_nothing_raised do
|
31
|
+
DynamicSitemaps.path = "/my/test/folder"
|
32
|
+
DynamicSitemaps.folder = "my_sitemaps"
|
33
|
+
DynamicSitemaps.config_path = "/my/config.rb"
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_raises ArgumentError do
|
37
|
+
DynamicSitemaps.path = ""
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_raises ArgumentError do
|
41
|
+
DynamicSitemaps.folder = ""
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_raises ArgumentError do
|
45
|
+
DynamicSitemaps.config_path = ""
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
test "raises error when using old sitemap ping urls" do
|
50
|
+
assert_raises RuntimeError do
|
51
|
+
DynamicSitemaps.sitemap_ping_urls = ["http://test.com/sitemap.xml"]
|
52
|
+
end
|
6
53
|
end
|
7
54
|
end
|