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.
@@ -1,58 +1,112 @@
1
1
  module DynamicSitemaps
2
2
  class Generator
3
- class << self
4
- def generate
5
- instance_eval open(DynamicSitemaps.config_path).read
6
- generate_index
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
- def generate_index
10
- IndexGenerator.new(sitemaps).generate
11
- end
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
- def sitemap(*args, &block)
14
- args << {} unless args.last.is_a?(Hash)
15
- args.last[:host] ||= host
16
- args.last[:folder] ||= folder
17
- sitemap = Sitemap.new(*args, &block)
18
- sitemaps << SitemapGenerator.new(sitemap).generate
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
- def sitemap_for(collection, options = {}, &block)
22
- raise "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)
42
+ def ping_search_engines
43
+ Pinger.ping_search_engines_with ping_urls
44
+ end
23
45
 
24
- name = options.delete(:name) || collection.model_name.underscore.pluralize.to_sym
25
- options[:collection] = collection
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
- sitemap(name, options, &block)
28
- end
52
+ ensure_valid_sitemap_name! sitemap
53
+ sitemap_names[sitemap.folder] << sitemap.name
29
54
 
30
- # Array of SitemapResult
31
- def sitemaps
32
- @sitemaps ||= []
33
- end
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
- def host(*args)
36
- if args.any?
37
- @host = args.first
38
- Rails.application.routes.default_url_options[:host] = @host
39
- else
40
- @host
41
- end
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
- def folder(*args)
45
- if args.any?
46
- @folder = args.first
47
- raise ArgumentError, "Folder can't be blank." if @folder.blank?
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
- FileUtils.rm_rf Dir.glob("#{DynamicSitemaps.path}/#{folder}/*")
50
- else
51
- # Ensure that the default folder is set and cleaned.
52
- folder DynamicSitemaps.folder if @folder.blank?
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
- @folder
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.path}/#{folder}/#{DynamicSitemaps.index_file_name}"
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.path}/#{folder}/#{sitemaps.first.files.first}"
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 ping_search_engines
5
- sitemap_urls = DynamicSitemaps.sitemap_ping_urls
6
- if sitemap_urls.any?
7
- puts "Pinging search engines..."
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
- puts "Done pinging search engines."
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
- puts "Pinging #{url} ..."
27
+ Logger.info "Pinging #{url} ..."
27
28
  begin
28
29
  Net::HTTP.get(URI.parse(url))
29
30
  rescue Exception => e
30
- puts "Failed to ping #{url} : #{e}"
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::DEFAULT_PER_PAGE
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.path}/#{folder}"
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
- puts "Generating sitemap..."
4
+ DynamicSitemaps::Logger.info "Generating sitemap..."
5
5
  DynamicSitemaps.generate_sitemap
6
- puts "Done generating sitemap in #{Time.now - start_time} seconds."
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
@@ -1,3 +1,3 @@
1
1
  module DynamicSitemaps
2
- VERSION = "2.0.0.beta"
2
+ VERSION = "2.0.0.beta2"
3
3
  end
@@ -3,5 +3,8 @@ host "www.example.com"
3
3
  sitemap :site do
4
4
  url root_url, last_mod: Time.now, change_freq: "daily", priority: 1.0
5
5
 
6
+ # Ping search engines after sitemap generation
7
+ # ping_with "http://#{host}/sitemap.xml"
8
+
6
9
  # TODO: Add examples
7
10
  end
@@ -1,3 +1,7 @@
1
1
  class Product < ActiveRecord::Base
2
- attr_accessible :name, :slug
2
+ attr_accessible :slug, :featured
3
+
4
+ def to_param
5
+ slug || id.to_s
6
+ end
3
7
  end
@@ -1,58 +1,7 @@
1
1
  Dummy::Application.routes.draw do
2
- # The priority is based upon order of creation:
3
- # first created -> highest priority.
2
+ root to: "home#index"
4
3
 
5
- # Sample of regular route:
6
- # match 'products/:id' => 'catalog#view'
7
- # Keep in mind you can assign values other than :controller and :action
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
@@ -0,0 +1,5 @@
1
+ host "www.mytest.com"
2
+
3
+ sitemap :site do
4
+ url root_url, last_mod: Time.now, change_freq: "daily", priority: 1.0
5
+ end
@@ -1,12 +1,10 @@
1
1
  class CreateProducts < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :products do |t|
4
- t.string :name
4
+ t.boolean :featured, default: false
5
5
  t.string :slug
6
6
 
7
7
  t.timestamps
8
8
  end
9
-
10
- add_index :products, :slug
11
9
  end
12
10
  end
@@ -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.string "name"
17
+ t.boolean "featured", :default => false
18
18
  t.string "slug"
19
- t.datetime "created_at", :null => false
20
- t.datetime "updated_at", :null => false
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
- test "truth" do
5
- assert_kind_of Module, DynamicSitemaps
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